|
| 1 | +# Boundary Sync REST API Design |
| 2 | + |
| 3 | +## Context |
| 4 | + |
| 5 | +Based on the [data model](./adr-001-data-models.md), the following REST API design is proposed to access it: |
| 6 | + |
| 7 | +### Authentication |
| 8 | + |
| 9 | +| Path | Method | Body | Authentication | Responses | Notes | |
| 10 | +| --------------- | ------ | --------- | -------------- | ----------------------------------------------------- | -------------------------------------------- | |
| 11 | +| `/auth/login/` | GET | - | Allow Any | 200 OK,<br />401 Not Authorized | Returns loging JSON if current session valid | |
| 12 | +| `/auth/login/` | POST | `{ ... }` | Allow Any | 200 OK,<br />400 Bad Request,<br />401 Not Authorized | Used for starting new valid session | |
| 13 | +| `/auth/logout/` | POST | - | Logged In User | 200 OK | Used for logging out | |
| 14 | + |
| 15 | +Also present are `/auth/password/reset/` and `/auth/password/reset/confirm/` endpoints that come from `dj_rest_auth`. |
| 16 | + |
| 17 | +### Boundaries |
| 18 | + |
| 19 | +| Path | Method | Body | Authentication | Responses | Notes | |
| 20 | +| ------------------------------------------- | ------ | ------------------------ | -------------- | ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | |
| 21 | +| `/boundaries/` | GET | - | Logged In User | 200 OK | Returns list of all boundaries the user has access to | |
| 22 | +| `/boundaries/?utilities=1,3,5,8` | GET | - | Logged In User | 200 OK,<br />401 Not Authorized | Returns list of boundaries in the given utilities. If the user does not have access to that utility, returns a 401 | |
| 23 | +| `/boundaries/` | POST | `{ ... }` | Contributor | 201 Created,<br />400 Bad Request,<br />401 Not Authorized | Creates a new boundary if the payload is correct and the user is authorized | |
| 24 | +| `/boundaries/{id}/` | GET | - | Logged In User | 200 OK,<br />404 Not Found | Returns boundary details if the user has access to it, else 404s. Includes all details about the boundary. | |
| 25 | +| `/boundaries/{id}/shape/` | PUT | `{ ... }` | Contributor | 200 OK,<br />404 Not Found | Updates the latest submission's shape | |
| 26 | +| `/boundaries/{id}/reference-images/` | POST | `{ ... }` | Contributor | 200 OK,<br />404 Not Found | Adds a new reference image to the boundary | |
| 27 | +| `/boundaries/{id}/reference-images/{id}/` | PUT | `{ ... }` | Contributor | 200 OK,<br />404 Not Found | Updates a reference image | |
| 28 | +| `/boundaries/{id}/submit/` | POST | `{ notes }` | Contributor | 200 OK,<br />404 Not Found | Submits the boundary | |
| 29 | +| `/boundaries/{id}/review/` | POST | `{ notes, annotations }` | Validator | 200 OK,<br />404 Not Found | Reviews a boundary | |
| 30 | +| `/boundaries/{id}/review/annotations/{id}/` | PUT | `{ annotation }` | Validator | 200 OK,<br />404 Not Found | Updates an annotation in the latest review. Older reviews are read-only, so no need to specify review id. | |
| 31 | +| `/boundaries/{id}/draft/` | POST | - | Contributor | 200 OK,<br />404 Not Found | Creates a new draft submission for a boundary after a review | |
| 32 | +| `/boundaries/{id}/approve/` | POST | - | Validator | 200 OK,<br />404 Not Found | Approves a boundary | |
| 33 | +| `/boundaries/{id}/unapprove/` | POST | - | Validator | 200 OK,<br />404 Not Found | Unapproves a boundary | |
| 34 | + |
| 35 | +### User |
| 36 | + |
| 37 | +| Path | Method | Body | Authentication | Responses | Notes | |
| 38 | +| -------------------- | ------ | --------- | -------------- | -------------------------- | ---------------------------------- | |
| 39 | +| `/user/{id}/profile` | PUT | `{ ... }` | Contributor | 200 OK,<br />404 Not Found | Update contributor contact details | |
| 40 | + |
| 41 | +## Notes |
| 42 | + |
| 43 | +Any thing that a Contributor or Validator can do, an Administrator can also do. |
| 44 | + |
| 45 | +A payload Body of `-` means that there is no body required. A payload Body of `{ ... }` means that there is a required body, but is not elaborated here. |
| 46 | + |
| 47 | +All endpoints that are marked as requiring a Logged In User will also return 401 Not Authorized if accessed without proper credentials. |
| 48 | + |
| 49 | +When we return `404 Not Found` for objects that the User does not have permissions to, we're using a pattern like this: |
| 50 | + |
| 51 | +```python |
| 52 | +@permission_classes((IsAuthenticated,)) |
| 53 | +def get_boundary(request, id): |
| 54 | + user = request.user |
| 55 | + boundary = get_object_or_404(Boundary, id) |
| 56 | + submission = boundary.get_latest_submission_for(user) |
| 57 | + |
| 58 | + serializer = SubmissionSerializer(submission) |
| 59 | + return Response(serializer.data) |
| 60 | +``` |
| 61 | + |
| 62 | +where `get_latest_submission_for` is along these lines: |
| 63 | + |
| 64 | +```python |
| 65 | +class Boundary(models.Model): |
| 66 | + ... |
| 67 | + |
| 68 | + def get_latest_submission_for(self, user): |
| 69 | + if user.role == CONTRIBUTOR: |
| 70 | + if self.utility not in user.utilities: |
| 71 | + raise Http404 |
| 72 | + |
| 73 | + if user.role == VALIDATOR: |
| 74 | + if self.utility.state not in user.states: |
| 75 | + raise Http404 |
| 76 | + |
| 77 | + return self.submissions.latest('created_at') |
| 78 | +``` |
0 commit comments