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

Add routes for user management #1

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions doc/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,70 @@ Adds a row to the `mail_unsubscribes` table, preventing email form being sent to

Requires an authentication token granting admin privileges. A request `Content-Type` of `application/x-www-form-urlencoded` is required. Renders the template with the data in the body.

User Management
---------------

Most of these APIs operate on the data stored in members' records. The following mapping from database schema to JSON representation (as keys on a user object) is established for use with this API:
- `id`: The internal database ID is exposed as an integer `db_id`. This may not be null.
remexre marked this conversation as resolved.
Show resolved Hide resolved
- `name`: The name is exposed as the string `name`. This may not be null.
- `x500`: The (psuedo-)x500 is exposed as the string `x500`. This may not be null.
- `card`: The long UCard number is exposed as the string `card`. This must be exactly 17 characters. This may be null instead.
- `email`: The email is exposed as the string `email`. This may not be null.
- `discordID`: The discord ID is exposed as the string `discordID`. This (as opposed to an integer) is adopted for the same (bad) reasons as the official Discord API, as well as interop with said API. This may be null.

The term "canonical user object" is used to refer to a user object with all of the preceding keys set. User objects that are missing a key may be used to e.g. represent a change to make. Missing keys do not mean the value of the field is null.
remexre marked this conversation as resolved.
Show resolved Hide resolved

### POST `/api/thetis/users/search`

**UNIMPLEMENTED**

Requires an authentication token granting `user.list`.
Takes the parameter `query`, which is a user object. Returns an object containing the following keys:
602p marked this conversation as resolved.
Show resolved Hide resolved

- `found`: A list of canonical user objects, matching the `query`

Matching here means that for all user objects returned, all fields set in the `query` will match the fields set in the user object. Fields that do not have a key set in the `query` are not used to search - setting null requires the field be null, not setting the key imposes no restrictions on the field's value. In psuedocode:

```python
for user in returned:
for key, value in query:
user[key] == query[key]
```

An empty `query` object will return all users.

TODO: Decide if we want fuzzy matching etc

### GET `/api/thetis/users/me`

**UNIMPLEMENTED**

Requires a user authentication token.
Returns the canonical user object for the user whose token was used to make the request.

### GET `/api/thetis/users/user/<id>`

**UNIMPLEMENTED**

`id` is a base-10 integer corresponding to the `db_id` of the user you wish to access.
remexre marked this conversation as resolved.
Show resolved Hide resolved
Requires an authentication token granting view permissions for the user.
Copy link
Contributor

Choose a reason for hiding this comment

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

uh which caps?

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh, yeah, so we don't have a users.view cap that is separate from users.list. users.list presumably allows you to see the details for all listed users, so we need something more fine-grained. I'd propose

cap(Id, users.view(Id)).
cap(Id, users.view(_)) :- cap(Id, users.list).

Copy link
Contributor

Choose a reason for hiding this comment

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

Ugh, really we should have users.view(Id, Property); e.g. the discord bot shouldn't have access to people's card numbers etc.

And really that should apply to searches too, but I can't think of a way to do that sanely...

If we aren't doing fine-grained permissions for search, it'd ideally be separate from view so that could do fine-grained permissions.

If that seems OTT though, I'm fine with yours.

Returns the canonical user object for the user with database id `<id>`.

### POST `/api/thetis/users/user/<id>`

**UNIMPLEMENTED**

`id` is a base-10 integer corresponding to the `db_id` of the user you wish to access.
Requires an authentication token granting the requisite `user.modify.<field>(db_id)` privileges.
Takes a parameter `update` containing a user object with one or more fields set. Updates those fields on the user with database id `<id>` and returns a canonical user object for that user.

### POST `/api/thetis/users/user/new`

**UNIMPLEMENTED**

Requires an authentication token granting `user.add`.
Copy link
Contributor

Choose a reason for hiding this comment

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

acmw semantics?

Takes a parameter `user` which is a user object with all fields but `db_id` set. Adds the user to the database and returns the canonical user object representing them.

Other
-----

Expand Down