Skip to content

Commit

Permalink
Merge pull request #1311 from guardian/rk/new-set-username-route
Browse files Browse the repository at this point in the history
OAuth migration | Use new set username route
  • Loading branch information
raphaelkabo authored Feb 8, 2024
2 parents 5a45fb6 + 68344c5 commit 05dbf04
Show file tree
Hide file tree
Showing 8 changed files with 55 additions and 8 deletions.
22 changes: 22 additions & 0 deletions client/components/mma/identity/idapi/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { get } from 'lodash';
import {
addCSRFToken,
fetchWithDefaultParameters,
postRequest,
putRequest,
} from '@/client/utilities/fetch';
import type { User, UserError } from '../models';
Expand Down Expand Up @@ -194,3 +195,24 @@ export const read = async (): Promise<User> => {
).then((response) => response.json());
return toUser(response);
};

export const setUsername = async (user: Partial<User>): Promise<User> => {
const url = '/idapi/user/username';
const body = {
publicFields: {
username: user.username,
},
};
try {
const response: UserAPIResponse = await fetchWithDefaultParameters(
url,
addCSRFToken(postRequest(body)),
).then((response) => response.json());
if (isErrorResponse(response)) {
throw toUserError(response);
}
return toUser(response);
} catch (e) {
throw isErrorResponse(e) ? toUserError(e) : e;
}
};
3 changes: 3 additions & 0 deletions client/components/mma/identity/identity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ export const Users: UserCollection = {
getChangedFields(original: User, changed: User): Partial<User> {
return diffWithCompositeFields(original, changed);
},
async setUsername(user: User): Promise<User> {
return await UserAPI.setUsername(user);
},
};

export const ConsentOptions: ConsentOptionCollection = {
Expand Down
1 change: 1 addition & 0 deletions client/components/mma/identity/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export interface UserCollection {
save: (user: User) => Promise<User>;
saveChanges: (original: User, changed: User) => Promise<User>;
getChangedFields: (original: User, changed: User) => Partial<User>;
setUsername: (user: User) => Promise<User>;
}

export interface ConsentOption {
Expand Down
11 changes: 5 additions & 6 deletions client/components/mma/identity/publicProfile/PublicProfile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,7 @@ export const PublicProfile = (_: { path?: string }) => {
.catch(handleGeneralError);
}, []);

const saveUser = async (originalUser: User, values: User) => {
const changedUser = { ...originalUser, ...values };
return await Users.saveChanges(originalUser, changedUser);
};
const setUsername = async (values: User) => await Users.setUsername(values);

useEffect(() => {
if (error && errorRef.current) {
Expand All @@ -63,7 +60,9 @@ export const PublicProfile = (_: { path?: string }) => {
const usernameDisplay = (u: User) => (
<>
<WithStandardTopMargin>
<PageSection title="Username">{u.username}</PageSection>
<PageSection title="Username">
<span data-cy="username-display">{u.username}</span>
</PageSection>
</WithStandardTopMargin>
<WithStandardTopMargin>
<Lines n={1} />
Expand All @@ -75,7 +74,7 @@ export const PublicProfile = (_: { path?: string }) => {
<>
<ProfileFormSection
user={u}
saveUser={(values) => saveUser(u, values)}
saveUser={(values) => setUsername(values)}
onError={handleGeneralError}
onSuccess={setUser}
/>
Expand Down
1 change: 1 addition & 0 deletions cypress/lib/signInOkta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export const signInOkta = () => {
cy.visit('/');
cy.createTestUser({
isUserEmailValidated: true,
doNotSetUsername: true,
})?.then(({ emailAddress, finalPassword }) => {
cy.get('input[name=email]').type(emailAddress);
cy.get('input[name=password]').type(finalPassword);
Expand Down
3 changes: 3 additions & 0 deletions cypress/support/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ type IDAPITestUserOptions = {
password?: string;
deleteAfterMinute?: boolean;
isGuestUser?: boolean;
doNotSetUsername?: boolean;
};
type IDAPITestUserResponse = [
{
Expand Down Expand Up @@ -128,6 +129,7 @@ export const createTestUser = ({
isUserEmailValidated = false,
deleteAfterMinute = true,
isGuestUser = false,
doNotSetUsername = false,
}: IDAPITestUserOptions) => {
// Generate a random email address if none is provided.
const finalEmail = primaryEmailAddress || randomMailosaurEmail();
Expand All @@ -150,6 +152,7 @@ export const createTestUser = ({
password: finalPassword,
deleteAfterMinute,
isGuestUser,
doNotSetUsername,
} as IDAPITestUserOptions,
})
.then((res) => {
Expand Down
13 changes: 11 additions & 2 deletions cypress/tests/e2e/e2e.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,18 @@ describe('E2E with Okta', () => {
});

context('profile tab', () => {
it('should contain a username', () => {
it('should allow the user to set a username', () => {
const randomUsername = `testuser${Math.floor(
Math.random() * 100000,
)}`;
cy.visit('/public-settings');
cy.findByText('Username');
cy.get('input[name="username"]').type(randomUsername);
cy.findByText('Save changes').click();
cy.visit('/public-settings');
cy.get('span[data-cy="username-display"]').should(
'contain',
randomUsername,
);
});
});

Expand Down
9 changes: 9 additions & 0 deletions server/routes/idapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,15 @@ router.delete(
}),
);

router.post(
'/user/username',
csrfValidateMiddleware,
idapiProxyHandler({
url: '/user/me/username',
method: 'POST',
}),
);

// eslint-disable-next-line @typescript-eslint/no-explicit-any -- assume we don't know the range of possible types for the err argument?
router.use((err: any, _: Request, res: Response, next: NextFunction) => {
if (err.code && err.code === 'EBADCSRFTOKEN') {
Expand Down

0 comments on commit 05dbf04

Please sign in to comment.