Skip to content

Conversation

@clairep94
Copy link
Collaborator

@clairep94 clairep94 commented Oct 27, 2025

Context:

While doing the rough-work PR below, I realised that can be some refinements on the types previously defined. I also figured out how to manually test my local server via Postman, so I logged some things I wasn't sure about the shape of

(eg. What user-related type is attached to the Express.user? What is the shape of the user state in the redux store? Is it the same as the server?)

This also helped identify some areas where there are multiple sources of truth of user related properties in the client, which I've noted in comments, but have not addressed in this PR to not include logic changes.

Changes:

  • Add GetRootState type --> used to define the getState param of redux `actions
  • Migrate client/modules/User/actions
  • Migrate client/modules/User/reducers
  • Update PublicUser.apiKeys to SanitisedApiKeys[] -- previously DocumentArray<ApiKeyDocument>, but they should not include hashedKey and should be POJO
    • UserDocuement.apiKeys still has DocumentArray<ApiKeyDocument>
    • Update testUtils > createMockUser & its callers to reflect this

user.apiKeys is displayed in the client below & shows it's the SanitisedApiKey type without hashedKey:

Screenshot 2025-10-27 at 12 47 55

Please see #3705 for actual migration of the client/modules/User > API key stuff

Notes:

Cherry-picked relevant commits from the giant rough-work PR here for easier review

Checks:

I have verified that this pull request:

  • has no linting errors (npm run lint)
  • has no test errors (npm run test)
  • is from a uniquely-named feature branch and is up to date with the develop branch.
  • is descriptively named and links to an issue number, i.e. Fixes #123
  • meets the standards outlined in the accessibility guidelines

@clairep94 clairep94 marked this pull request as ready for review October 27, 2025 03:36
@clairep94 clairep94 added the pr05 Grant Projects pr05 Grant Projects label Oct 27, 2025
@clairep94 clairep94 changed the title Pr05 finals refine server and reducer types Pr05 Typescript Migration: Refine server/types & client/reducer types Oct 27, 2025
Comment on lines +35 to +44
/**
* - Method: `POST`
* - Endpoint: `/signup`
* - Authenticated: `false`
* - Id: `UserController.createUser`
*
* Description:
* - Create a new user
*/
export function signUpUser(formValues: CreateUserRequestBody) {
Copy link
Collaborator Author

@clairep94 clairep94 Oct 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

copying these JSDocs from the relevant server user controller method, so we get the benefit of the hints on hover in the client as well

Only did this for the user.controller methods, so there are some methods below which are in the server/passport controller or otherwise that haven't been migrated yet

Comment on lines +14 to +19
// TODO: use state of user from server as single source of truth:
// Currently using redux state below, but server also has similar info.
resetPasswordInitiate?: boolean;
resetPasswordInvalid?: boolean;
emailVerificationInitiate?: boolean;
emailVerificationTokenState?: 'checking' | 'verified' | 'invalid';
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if we might want to open an issue where we migrate to use just the server PublicUser.verified as the server has that, but the redux store.user has these additional properties?

Not sure if the logic above makes sense, as I haven't dug deeper into it with a proposal yet but just wanted to highlight

The server PublicUser.verified enum is the below, so there's a mismatch:

/** Possible email confirmation states */
export const EmailConfirmationStates = {
  Verified: 'verified',
  Sent: 'sent',
  Resent: 'resent'
} as const;

username: 'tester',
preferences: mockUserPreferences,
apiKeys: ([] as unknown) as Types.DocumentArray<ApiKeyDocument>,
apiKeys: [],
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for a PublicUser, apiKeys is SanitisedApiKey[]

export const mockBaseUserFull: Omit<User, 'createdAt'> = {
...mockBaseUserSanitised,
name: 'test user',
apiKeys: ([] as unknown) as Types.DocumentArray<ApiKeyDocument>,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for a UserDocument, apiKeys is DocumentArray<ApiKeyDocument> -- It needs access to methods like apiKeys.pull

...mockBaseUserSanitised,
...overrides
};
} as PublicUser;
Copy link
Collaborator Author

@clairep94 clairep94 Oct 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to make the return type of each case super explicit, but we seem to still need to cast the return value of calling this function anyway to resolve type-errors for when the usecase requires UserDocument methods

Comment on lines +11 to +30
export function sanitiseApiKey(key: ApiKeyDocument): SanitisedApiKey {
return {
id: key.id,
label: key.label,
lastUsedAt: key.lastUsedAt,
createdAt: key.createdAt
};
}

/**
* Sanitise user objects to remove sensitive fields
* @param user
* @returns Sanitised user
*/
export function userResponse(user: PublicUser | UserDocument): PublicUser {
export function userResponse(user: UserDocument): PublicUser {
return {
email: user.email,
username: user.username,
preferences: user.preferences,
apiKeys: user.apiKeys,
apiKeys: user.apiKeys.map((el) => sanitiseApiKey(el)),
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is one of the bigger changes on this PR:
After manual testing/logging what userResponse gives us on Postman, I saw that apiKeys is the SanitisedApiKey, with the last element containing token

Comment on lines +18 to +19
toJSON(options?: any): IApiKey;
toObject(options?: any): IApiKey;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previously typed this as SanitisedApiKey, but it's the full ApiKey till it gets sanitised

@clairep94 clairep94 changed the title Pr05 Typescript Migration: Refine server/types & client/reducer types Pr05 Typescript Migration #19: Refine server/types & client/reducer types Oct 27, 2025
@clairep94 clairep94 changed the title Pr05 Typescript Migration #19: Refine server/types & client/reducer types Pr05 Typescript Migration #20: Refine server/types & client/reducer types Oct 27, 2025
@clairep94
Copy link
Collaborator Author

@raclim @khanniie

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr05 Grant Projects pr05 Grant Projects

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant