Build a voting system for deciding where to have lunch.
-
2 types of users: admin and regular users
-
Admin can input a restaurant and it's lunch menu of the day (2-5 items usually, just a dish name and price)
-
Menu changes each day (admins do the updates)
-
Users can vote on which restaurant they want to have lunch at
-
Only one vote counted per user
-
If user votes again the same day:
- If it is before 11:00 we assume that he changed his mind.
- If it is after 11:00 then it is too late, vote can't be changed
-
Each restaurant provides new menu each day.
Requests to the API are made via the HTTP protocol with basic authorization. POST and PUT request's content must be transferred in JSON format, the Content-Type header must be set to "application/json".
"[email protected]:pass" "YWRtaW5AeWFuZGV4LnJ1OnBhc3M="
"[email protected]:pass" "dXNlckB5YS5ydTpwYXNz"
"[email protected]:password" "bGlzYTEyMkBnbWFpbC5jb206cGFzc3dvcmQ="
Authorization example for user [email protected]
"Authorization: Basic YWRtaW5AeWFuZGV4LnJ1OnBhc3M="
method: POST
path: /rest/profiles/register
curl -s -X POST -d '{"name": "Lisa", "email": "[email protected]", "password": "password"}' -H 'Content-Type:application/json;charset=UTF-8' http://{hostname}/rest/profiles/register
Request:
{
"name": "Lisa",
"email": "[email protected]",
"password": "password"
}
Response:
{
"id":10021,
"name":"Lisa",
"email":"[email protected]",
"enabled":true,
"roles": [
"ROLE_USER"
]
}
HTTP status codes:
| Code | Status | Description |
|---|---|---|
| 201 | Created | Normal status |
| 409 | Conflict | User exist |
| 422 | Unprocessable Entity | Any fields is not valid |
method: GET
path: /rest/profiles
curl -H "Authorization: Basic YWRtaW5AeWFuZGV4LnJ1OnBhc3M=" http://{hostname}/rest/profiles
Response:
{
"id": 10000,
"name": "Sergey",
"email": "[email protected]",
"enabled": true,
"roles": [
"ROLE_ADMIN"
]
}
HTTP status codes:
| Code | Status | Description |
|---|---|---|
| 200 | OK | |
| 401 | Unauthorized |
method: PUT
path: /rest/profiles
curl -s -X PUT -H "Authorization: Basic bGlzYUBnbWFpbC5jb206cGFzc3dvcmQ=" -d '{"id": 10021, "name": "Elisabeth", "email": "[email protected]", "password": "password"}' -H 'Content-Type:application/json;charset=UTF-8' http://{hostname}/rest/profiles
Request:
{
"id": 10021,
"name": "Elisabeth",
"email": "[email protected]",
"password": "password"
}
HTTP status codes:
| Code | Status | Description |
|---|---|---|
| 204 | No Content | Normal status |
| 401 | Unauthorized | |
| 409 | Conflict | User email exist |
| 422 | Unprocessable Entity | Any fields is not valid |
method: DELETE
path: /rest/profiles
curl -s -X DELETE -H "Authorization: Basic bGlzYUBnbWFpbC5jb206cGFzc3dvcmQ=" http://{hostname}/rest/profiles
HTTP status codes:
| Code | Status | Description |
|---|---|---|
| 204 | No Content | |
| 401 | Unauthorized |
method: GET
path: /rest/restaurants
curl -H "Authorization: Basic dXNlckB5YS5ydTpwYXNz" http://{hostname}/rest/restaurants
Response:
[
{
"id": 10006,
"name": "KFC3",
"city": "Москва",
"description": "Куриные бургеры и картошка",
"added": "2019-01-01",
"menus": null
},
{
"id": 10007,
"name": "McDs1",
"city": "Москва",
"description": "Бургеры и картошка",
"added": "2019-01-01",
"menus": null
},
...
]
HTTP status codes:
| Code | HTTP status | Description |
|---|---|---|
| 200 | OK |
method: GET
path: /rest/restaurants/{id}
curl -H "Authorization: Basic dXNlckB5YS5ydTpwYXNz" http://{hostname}/rest/restaurants/{id}
Response:
{
"id": 10006,
"name": "KFC3",
"city": "Москва",
"description": "Куриные бургеры и картошка",
"added": "2018-12-31",
"menus": [
{
"id": 10012,
"added": "2018-12-31",
"dishes": [
{
"id": 10019,
"name": "1Пицца",
"price": 279.49
},
{
"id": 10020,
"name": "2Пицца",
"price": 279.49
}
]
}
]
}
HTTP status codes:
| Code | Status | Description |
|---|---|---|
| 200 | OK | |
| 422 | Unprocessable Entity |
method: POST
path: /rest/restaurants
curl -s -X POST -d '{"name": "Гусли", "city": "Александров", "description": "Ресторан русской кухни"}' -H 'Content-Type:application/json;charset=UTF-8' -H "Authorization: Basic YWRtaW5AeWFuZGV4LnJ1OnBhc3M=" http://{hostname}/rest/restaurants
Request:
{
"name": "Гусли",
"city": "Александров",
"description": "Ресторан русской кухни"
}
Response:
{
"id": 10022,
"name": "Гусли",
"city": "Александров",
"description": "Ресторан русской кухни",
"added": "2018-12-31",
"menus": []
}
Response headers:
Location http://localhost:8080/rest/restaurants/10022
HTTP status codes:
| Code | Status | Description |
|---|---|---|
| 201 | Created | |
| 409 | Conflict | Restaurant with this name and city is exist |
| 422 | Unprocessable Entity |
method: PUT
path: /rest/restaurants/{id}
curl -s -X PUT -d '{"name": "Гусли", "city": "Александров", "description": "Ресторан русской кухни"}' -H 'Content-Type:application/json;charset=UTF-8' -H "Authorization: Basic YWRtaW5AeWFuZGV4LnJ1OnBhc3M=" http://{hostname}/rest/restaurants/{id}
Request:
{
"id": 10022,
"name": "Гусли",
"city": "Александров",
"description": "Ресторан традиционной русской кухни"
}
HTTP status codes:
| Code | Status | Description |
|---|---|---|
| 204 | No Content | |
| 409 | Conflict | |
| 422 | Unprocessable Entity |
method: DELETE
path: /rest/restaurants/{id}
curl -s -X DELETE -H "Authorization: Basic YWRtaW5AeWFuZGV4LnJ1OnBhc3M=" http://{hostname}/rest/restaurants/{id}
HTTP status codes:
| Code | Status | Description |
|---|---|---|
| 204 | No Content | Normal status |
| 422 | Unprocessable Entity | Not found entity |
method: POST
path: /rest/menus
curl -s -X POST -d '{"name": "Гусли", "city": "Александров", "description": "Ресторан русской кухни"}' -H 'Content-Type:application/json;charset=UTF-8' -H "Authorization: Basic YWRtaW5AeWFuZGV4LnJ1OnBhc3M=" http://{hostname}/rest/restaurants
Request:
{
"restaurantId": 10006,
"added": "2019-01-01",
"dishes": [
{
"name": "Ролл1",
"price": 270.15
},
{
"name": "Ролл2",
"price": 180.55
}
]
}
Response:
{
"id": 10025,
"added": "2019-01-01",
"dishes": [
{
"id": 10026,
"name": "Ролл1",
"price": 270.15
},
{
"id": 10027,
"name": "Ролл2",
"price": 180.55
}
]
}
Response headers:
Location http://localhost:8080/rest/menus/10025
HTTP status codes:
| Code | Status | Description |
|---|---|---|
| 201 | Created | Menu created with location |
| 409 | Conflict | Menu for that date is exist |
| 422 | Unprocessable Entity | Any fields is not valid |
method: GET
path: /rest/menus
curl -H "Authorization: Basic YWRtaW5AeWFuZGV4LnJ1OnBhc3M=" http://{hostname}/rest/menus
Response:
[
{
"id": 10010,
"restaurantId": 10006,
"dishes": [
{
"id": 10013,
"name": "Картошка",
"price": 70.15
},
{
"id": 10014,
"name": "Бургер куриный",
"price": 80.55
},
{
"id": 10015,
"name": "Салат",
"price": 100.35
}
],
"added": "2018-12-14"
},
...
]
HTTP status codes:
| Code | HTTP status | Description |
|---|---|---|
| 200 | OK | Normal status |
| 403 | Forbidden | Need admin role |
method: GET
path: /rest/menus/{id}
curl -H "Authorization: Basic YWRtaW5AeWFuZGV4LnJ1OnBhc3M=" http://{hostname}/rest/menus/{id}
Response:
{
"id": 10010,
"added": "2018-12-14",
"dishes": [
{
"id": 10013,
"name": "Картошка",
"price": 70.15
},
{
"id": 10014,
"name": "Бургер куриный",
"price": 80.55
},
{
"id": 10015,
"name": "Салат",
"price": 100.35
}
]
}
HTTP status codes:
| Code | HTTP status | Description |
|---|---|---|
| 200 | OK | Normal status |
| 403 | Forbidden | Need admin role |
method: GET
path: /rest/menus/by
| Request param | type | required | example |
|---|---|---|---|
| restaurantId | Number | true | 10006 |
| date | Date ISO 8601 | false | 2018-12-14 |
curl -H "Authorization: Basic YWRtaW5AeWFuZGV4LnJ1OnBhc3M=" http://{hostname}/rest/menus/by?restaurantId={id}&date={date}
Response:
[
{
"id": 10010,
"added": "2018-12-14",
"dishes": [
{
"id": 10013,
"name": "1Картошка",
"price": 70.15
},
{
"id": 10014,
"name": "2Бургер куриный",
"price": 80.55
},
{
"id": 10015,
"name": "3Салат",
"price": 100.35
}
]
},
{
"id": 10012,
"added": "2019-01-01",
"dishes": [
{
"id": 10019,
"name": "1Пицца",
"price": 279.49
},
{
"id": 10020,
"name": "2Пицца",
"price": 279.49
}
]
}
]
HTTP status codes:
| Code | HTTP status | Description |
|---|---|---|
| 200 | OK | Normal status |
| 403 | Forbidden | Need admin role |
method: PUT
path: /rest/menus/{id}
curl -s -X PUT -d '{"id": "10010", "restaurantId": 10006, "added": "2018-12-14", "dishes": [{"name": "Ролл1", "price": 270.15},{"name": "Ролл2", "price": 280.55}]}' -H 'Content-Type:application/json;charset=UTF-8' -H "Authorization: Basic YWRtaW5AeWFuZGV4LnJ1OnBhc3M=" http://{hostname}/rest/menus/{id}
Request:
{
"id": 10010,
"restaurantId": 10006,
"added": "2018-12-14",
"dishes": [
{
"name": "Ролл1",
"price": 270.15
},
{
"name": "Ролл2",
"price": 280.55
}
]
}
HTTP status codes:
| Code | Status | Description |
|---|---|---|
| 204 | No Content | Normal status |
| 409 | Conflict | |
| 422 | Unprocessable Entity | Any fields is not valid |
method: DELETE
path: /rest/menus/{id}
curl -s -X DELETE -H "Authorization: Basic YWRtaW5AeWFuZGV4LnJ1OnBhc3M=" http://{hostname}/rest/menus/{id}
HTTP status codes:
| Code | Status | Description |
|---|---|---|
| 204 | No Content | Normal status |
| 422 | Unprocessable Entity | Not found entity |
method: POST
path: /rest/votes/for
| Request param | type | required | example |
|---|---|---|---|
| restaurantId | Number | true | 10006 |
curl -s -X POST -H "Authorization: Basic YWRtaW5AeWFuZGV4LnJ1OnBhc3M=" http://{hostname}/rest/votes/for?restaurantId=10006
HTTP status codes:
| Code | Status | Description |
|---|---|---|
| 204 | No Content | Normal status |
| 409 | Conflict | Restaurant not found |
| 412 | Precondition Failed | Vote time is expired |
method: GET
path: /rest/votes
curl -H "Authorization: Basic YWRtaW5AeWFuZGV4LnJ1OnBhc3M=" http://{hostname}/rest/votes
response:
[
{
"id": 10022,
"date": "2019-01-02",
"userEmail": "[email protected]",
"restaurant": {
"id": 10006,
"name": "KFC3",
"city": "Москва",
"description": "Куриные бургеры и картошка",
"added": "2019-01-02",
"menus": null
}
},
...
]