Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use AJV to validate User JSON when getting a User by ID #1464

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

NicMcPhee
Copy link
Member

@NicMcPhee NicMcPhee commented Jan 22, 2024

This PR introduces the AJV library, which we can use to validate JSON objects, i.e., confirm that they have all the right fields. At the moment, for example, the server could send any kind of weird stuff back when we request a User, and the Angular code never really checks that or generates a meaningful error.

This PR should be considered the start of a process, only checking one specific case, namely checking that the object UserService#getUserById receives from the HTTP request is actually an instance of the User type. If we merge this in, we would then want to do create issues for additional validation.

  • Anything that comes from the server via an HTTP request should be validated
  • Anything that comes from a form (i.e., from user input) should be validated
    • This second one is arguably less necessary since we've got lots of validation on the form for adding a new user, but it's still probably a good idea.

The "important" parts of this PR are:

  • Adding a dependency on ajv
  • Adding "strictNullChecks": true in tsconfig.json
    • This is needed for ajv to work; without it AJV can't tell properly distinguish between required and optional fields (I think).
  • Adding a JSON schema to user.ts
    • I set the _id field to optional since there are number places where we have a User without an ID. The
      main one is when someone enters a new User in a form, that won't (yet) have an ID. It's also an issue in
      some of the tests, where we don't provide a ID.
  • Adding a JSON schema to user-role.ts
    • We ended up pulling UserRole out into its own file while we were here

This is necessary to get AJV to work so it can "tell the difference" between required and optional fields in a type definition.
This also pulls `UserRole` out into its own file.

The new `validateUser` function can be used to determine whether any JavaScript value is in fact an instance of the type `User`.

I had to make `_id` optional, since there are numerous places where we don't (yet) have an ID. As an example, when adding a user, we don't have an ID because that will come from the server when we actually add it.
The key part of this is the change to `getUserById`, where we now use the `validateUser()` function to check that the `user` value we got in the HTTP response from the server really is an instance of `User`. If it's not, we throw an error.

The other changes to this file are introductions of `!` to say that code should fail is a value is `null`. For example:

```typescript
return this.httpClient!.get<User[]>(...
```

the `!` says that if `this.httpClient` is `null` this should fail straightaway. This was only necessary because I had to say that the injected `httpClient` in the constructor could have the value `null`. I'm not happy about adding `null` as an option there, but I can figure out how to get the injection to work so that the mocked version of the service doesn't have to provide an `HttpClient`.

I _think_ the solution to that is to get rid of the `MockUserService` and instead just stub what we need where we need it. Then we could get rid of `HttpClient | null`, and we wouldn't need all those `!`s.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant