Skip to content

Commit 100e8d0

Browse files
authored
Merge pull request #115 from azavea/tt/rest-api-design
2 parents cf2f6ad + 33e064e commit 100e8d0

File tree

2 files changed

+79
-0
lines changed

2 files changed

+79
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3636
- Add RTK Query [#101](https://github.com/azavea/iow-boundary-tool/pull/101)
3737
- Add navigation bar and logout button [#109](https://github.com/azavea/iow-boundary-tool/pull/109)
3838
- Style submission detail page [#104](https://github.com/azavea/iow-boundary-tool/pull/104)
39+
- Add ADR for REST API [#115](https://github.com/azavea/iow-boundary-tool/pull/115)
3940

4041
### Changed
4142

doc/arch/adr-002-rest-api.md

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
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

Comments
 (0)