DB: PostgresSQL
Framework: express, nestJS Зависит от описания в вакансии и вашего опыта
Реализовать CRUD для сущностей User и Tags.
field | type |
---|---|
uid | uuid |
string(100) | |
password | string(100) |
nickname | string(30) |
password: должен содержать как минимум одну цифру, одну заглавную и одну строчную буквы.
password: минимальная длинна 8 символов
field | type |
---|---|
id | int |
creator | uuid |
name | string(40) |
sortOrder | int default(0) |
creator uid пользователя создавшего тэг, только он может его менять и удалять из базы
Эту таблицу нужно сделать самим
Сделать сервис с REST API и авторизациею по JWT bearer token.
Настроить CORS для доступа с любого origin.
- Пароли не хранить в открытом виде
- Реализовать валидацию полей на api запросы с кодами ответов и сообщениями об ошибке в теле ответа.
- Развернуть проект в любом удобном месте, что бы можно было прогнать тесты и проверить.
- Код на github или gitlab
- Придерживаться принципам SOLID
- Токен авторизации живет 30 минут
- Реализовать endpoint для обновления токена
- Создать миграции
- Написать сопроводительную документация в README.md для разворота
- Реализовать offset или пагинацию для сущности TAG
- Реализовать Сортировку по полю sortOrder и(или) полю name для сущности TAG
- Использовать DTO
- Писать интерфейсы и реализовывать их
- Желательно не использовать ORM
- Написать DockerFile для приложения
- Написать docker-composer для локального разворота приложения
- Реализовать кеширование
- Покрыть тестами сами api
- Добавить генерацию swagger документации для api методов (или написать ручками и положит в проект в директорию /doc)
- POST /signin
{
"email": "example@exe.com",
"password": "example",
"nickname": "nickname"
}
Валидировать password, email, nickname
RETURN:
{
"token": "token",
"expire": "1800"
}
- POST /login
{
"email": "example@exe.com",
"password": "example"
}
RETURN:
{
"token": "token",
"expire": "1800"
}
-
POST /logout
HEADER:
Authorization: Bearer {token}
Ниже идущие api закрыты под авторизацией
-
GET /user
HEADER:
Authorization: Bearer {token}
RETURN:
{
"email": "example@exe.com",
"nickname": "example",
"tags": [
{
"id": "id",
"name": "example",
"sortOrder": "0"
}
]
}
-
PUT /user
HEADER:
Authorization: Bearer {token}
{
"email": "example@exe.com",
"password": "example",
"nickname": "example"
}
Все поля опциональные
Валидировать password, email, nickname
Проверять на дублирование email и nickname в базе
RETURN :
{
"email": "example@exe.com",
"nickname": "example"
}
-
DELETE /user
HEADER:
Authorization: Bearer {token}
Разлогиниваем и удаляем пользователя
-
POST /tag
HEADER:
Authorization: Bearer {token}
{
"name": "example",
"sortOrder": "0"
}
sortOrder опционально по default 0 Проверять на дублирование name в базе и максимальную длину
RETURN :
{
"id": "id",
"name": "example",
"sortOrder": "0"
}
-
GET /tag/{id}
HEADER:
Authorization: Bearer {token}
RETURN :
{
"creator": {
"nickname": "example",
"uid": "exam-pl-eUID"
},
"name": "example",
"sortOrder": "0"
}
-
GET /tag?sortByOrder&sortByName&offset=10&length=10
HEADER:
Authorization: Bearer {token}
sortByOrder, offset SortByName, length опциональны
length количество элементов в выборке
Если выбрали подход с страницами, то ипсользуйте параметры page и pageSize вместо offset и length
RETURN :
{
"data": [
{
"creator": {
"nickname": "example",
"uid": "exam-pl-eUID"
},
"name": "example",
"sortOrder": "0"
},
{
"creator": {
"nickname": "example",
"uid": "exam-pl-eUID"
},
"name": "example",
"sortOrder": "0"
}
],
"meta": {
"offset": 10,
"length": 10,
"quantity": 100
}
}
quantity общее количество элементов в выборке
-
PUT /tag/{id}
HEADER:
Authorization: Bearer {token}
Тэг может менять только владелец
{
"name": "example",
"sortOrder": "0"
}
name или sortOrder опциональны
RETURN :
{
"creator": {
"nickname": "example",
"uid": "exam-pl-eUID"
},
"name": "example",
"sortOrder": "0"
}
- DELETE /tag/{id}
HEADER: Authorization: Bearer {token}
Тэг может удалить только владелец
Каскадом удалем все связанные записи с этим Тэгом
-
POST /user/tag
HEADER:
Authorization: Bearer {token}
{
"tags": [1, 2]
}
Проверяем тэги на наличие в базе и добавляем к пользователю пачкой (атомарной операцией)
Пример: Если тэга с id 2 нет в базе то и тэг с id 1 не добавится пользователю
RETURN :
{
"tags": [
{
"id": 1,
"name": "example",
"sortOrder": "0"
},
{
"id": 2,
"name": "example",
"sortOrder": "0"
},
{
"id": 3,
"name": "example",
"sortOrder": "0"
}
]
}
-
DELETE /user/tag/{id}
HEADER:
Authorization: Bearer {token}
RETURN :
{
"tags": [
{
"id": 1,
"name": "example",
"sortOrder": "0"
},
{
"id": 2,
"name": "example",
"sortOrder": "0"
},
{
"id": 3,
"name": "example",
"sortOrder": "0"
}
]
}
-
GET /user/tag/my
HEADER:
Authorization: Bearer {token}
Отдаем список тэгов в которых пользователь является создателем
RETURN :
{
"tags": [
{
"id": 1,
"name": "example",
"sortOrder": "0"
},
{
"id": 2,
"name": "example",
"sortOrder": "0"
},
{
"id": 3,
"name": "example",
"sortOrder": "0"
}
]
}