МАГ Девелопмент — это компания, где создаются инновационные сервисы на стыке информационных технологий, транспортной логистики и торговли.
Наши вакансии на сайте http://magdv.com.
Необходимо реализовать систему для редактирования любого json-документа методом PATCH. Клиент системы должен иметь возможность создать пустой черновик документа. Пока документ находится в статусе черновик, его можно редактировать сколько угодно раз. Черновик документа можно опубликовать. После публикации документ больше редактировать нельзя.
Данное задание может считаться обучающим. Мы не ожидаем что вы являетесь опытным программистом, однако если вы готовы изучить технологии и выполнить это задание - мы ждем вас к нам в стажеры.
Время исполнения | 8-16ч опытным разработчиком |
Фреймворк | Yii2, Zend, Laravel, Symfony, свой вариант вокруг PSR-* |
Сторонние пакеты | любые |
Php | >=7.1 |
Db | postgres, mysql |
- Разместить код на любом доступном git-резпозитории.
- Описать файл
README.md
, описать как запустить проект. - Соблюдать единый code-style на протяжении всего проекта
- Обязательна документация для каждого метода, класса и поля. Указание типов обязательно.
- Первый коммит в проекте должен быть - настройка и конфигурация фреймворка (скелета).
- Отчет в виде затраченного времени, полнота исполнения задания, а также, возникшие проблемы сложности и их решения, пожелания, комментарий и пр.
POST /api/v1/document/
- создаем черновик документаGET /api/v1/document/{id}
- получить документ по idPATCH /api/v1/document/{id}
- редактировать документPOST /api/v1/document/{id}/publish
- опубликовать документGET /api/v1/document/?page=1&perPage=20
- получить список документов с пагинацией, сортировка в последние созданные сверху.
Дополнительные условия:
- Если документ не найден, то в ответе возвращается 404 код.
- При попытке редактирования документа, который уже опубликован, должно возвращаться 400.
- Попытка опубликовать уже опубликованный документ возвращает 200.
- Все запросы на конкретный документ возвращают этот документ. JsonSchema ответа с документом.
- Список документов возвращается в виде массива документов и значений пагинации. JsonSchema списка документов.
- Запрос
PATCH
отправляется с телом json в соответсвующей иерархии документа, все поля, кромеpayload
игнорируются. Еслиpayload
не передан, то ответ 400.
document = {
id: "some-uuid-string",
status: "draft|published",
payload: Object,
createAt: "iso-8601 date time with time zone",
modifyAt: "iso-8601 date time with time zone"
}
Патчинг проводится согласно RFC-7396.
Запрос:
POST /api/v1/document HTTP/1.1
accept: application/json
Ответ:
HTTP/1.1 200 OK
content-type: application/json
{
"document": {
"id": "718ce61b-a669-45a6-8f31-32ba41f94784",
"status": "draft",
"payload": {},
"createAt": "2018-09-01 20:00:00+07:00",
"modifyAt": "2018-09-01 20:00:00+07:00"
}
}
Запрос:
PATCH /api/v1/document/718ce61b-a669-45a6-8f31-32ba41f94784 HTTP/1.1
accept: application/json
content-type: application/json
{
"document": {
"payload": {
"actor": "The fox",
"meta": {
"type": "quick",
"color": "brown"
},
"actions": [
{
"action": "jump over",
"actor": "lazy dog"
}
]
}
}
}
Ответ:
HTTP/1.1 200 OK
content-type: application/json
{
"document": {
"id": "718ce61b-a669-45a6-8f31-32ba41f94784",
"status": "draft",
"payload": {
"actor": "The fox",
"meta": {
"type": "quick",
"color": "brown"
},
"actions": [
{
"action": "jump over",
"actor": "lazy dog"
}
]
},
"createAt": "2018-09-01 20:00:00+07:00",
"modifyAt": "2018-09-01 20:01:00+07:00"
}
}
Запрос:
PATCH /api/v1/document/718ce61b-a669-45a6-8f31-32ba41f94784 HTTP/1.1
accept: application/json
content-type: application/json
{
"document": {
"payload": {
"meta": {
"type": "cunning",
"color": null
},
"actions": [
{
"action": "eat",
"actor": "blob"
},
{
"action": "run away"
}
]
}
}
}
Ответ:
HTTP/1.1 200 OK
content-type: application/json
{
"document": {
"id": "718ce61b-a669-45a6-8f31-32ba41f94784",
"status": "draft",
"payload": {
"actor": "The fox",
"meta": {
"type": "cunning",
},
"actions": [
{
"action": "eat",
"actor": "blob"
},
{
"action": "run away"
}
]
},
"createAt": "2018-09-01 20:00:00+07:00",
"modifyAt": "2018-09-01 20:02:00+07:00"
}
}
Запрос:
POST /api/v1/document/718ce61b-a669-45a6-8f31-32ba41f94784/publish HTTP/1.1
accept: application/json
Ответ:
HTTP/1.1 200 OK
content-type: application/json
{
"document": {
"id": "718ce61b-a669-45a6-8f31-32ba41f94784",
"status": "published",
"payload": {
"actor": "The fox",
"meta": {
"type": "cunning",
},
"actions": [
{
"action": "eat",
"actor": "blob"
},
{
"action": "run away"
}
]
},
"createAt": "2018-09-01 20:00:00+07:00",
"modifyAt": "2018-09-01 20:03:00+07:00"
}
}
Запрос:
GET /api/v1/document/?page=1 HTTP/1.1
accept: application/json
Ответ:
HTTP/1.1 200 OK
content-type: application/json
{
"document": [
{
"id": "718ce61b-a669-45a6-8f31-32ba41f94784",
"status": "published",
"payload": {
"actor": "The fox",
"meta": {
"type": "cunning",
},
"actions": [
{
"action": "eat",
"actor": "blob"
},
{
"action": "run away"
}
]
},
"createAt": "2018-09-01 20:00:00+07:00",
"modifyAt": "2018-09-01 20:03:00+07:00"
}
],
"pagination": {
"page": 1,
"perPage": 20,
"total": 1
}
}
Опциональные задания не являются обязательными, однако, если вы не будете испытывать сложности с их реализацией, то, вероятно, вы опытный разработчик. Если же сложности все-таки возникают, то значит есть повод их преодолеть и получить новые знания. В задачах ниже описаны примерные задания. Полнота и способ их исполнения - целиком продукт вашего творчества, ведь программист - творческая профессия.
Попробуйте реализовать хотя бы одну задачу. Даже если у вас не получиться, мы будем рады тому что вы попробовали. Опциональные задания повысят вас в наших глазах как разработчика.
Необходимо описать минимальный набор тестов, для того чтобы убедиться что ваше приложение работоспособно. Желательно использовать php-unit или codeception.
Составить план работ/модулей которые надо реализовать. Дать оценку времени, которое будет затрачено на каждый из пунктов. Оформить каждый пункт как отдельный коммит. По окончанию реализации задачи записать сколько реально времени было потрачено.
В итоге получить примерно такую таблицу:
# | Задача | Оценка | Затрачено | Комментарий |
---|---|---|---|---|
1 | Настройка окружения | 1ч | 40м | Нашел хорошую инструкцию |
2 | Установка фрэймворка | 20м | 30м | Забыл установить composer |
3 | ............ | ... | ... | ... |
Завернуть ваше приложение в Docker контейнер. Написать скрипт разворачивания приложения одной командой.
Самый удобный способ для этого, конечно, docker-compose.
- Добавить возможность получения списка документов с пагинатором по пути
/
- Просмотр конкретного документа по пути
/document/{id}
.
Внешний вид нас не интересует - поэтому не стоит пытаться сделать все идеально. Важен способ реализации и время которое вы на это затратите. Лучше использовать готовые решения и фреймворки. Ограничений нет - полная свобода творчества.
В вашем приложении вы могли использовать готовый модуль для патча. Если это так, то попробуйте реализовать алгоритм патчинга самостоятельно.
Реализовать авторизацию без пароля POST /api/v1/login
Запрос:
POST /api/v1/login HTTP/1.1
accept: application/json
content-type: application/json
{
"login": "root"
}
Ответ:
HTTP/1.1 200 OK
content-type: application/json
{
"user": "root",
"token": "q56lVCW9aIW6Gs01F5N9raaQordCb8HW",
"until": 1537352295
}
token - это случайная строка из символов. until - это unix timestamp до которого действует токен.
Аутентификация должна проходить по заголовку в запросе. Например:
GET /api/v1/document/718ce61b-a669-45a6-8f31-32ba41f94784 HTTP/1.1
accept: application/json
Authorization: bearer q56lVCW9aIW6Gs01F5N9raaQordCb8HW
Требования:
- Каждый раз когда пользователь авторизуется - он получает новый токен.
- Если пользователь шлет любой запрос с несуществующим токеном или с просроченным токеном - то должен вернуться ответ с кодом 401.
- Аноним может видеть список опубликованных документов, а также загружать конкретный опубликованный документ.
- Аноним при попытке обратиться к PATCH и POST запросам будет получать ошибку 401.
- Документ может создать только пользователь.
- Редактировать и опубликовать документ может только пользователь создавший его.
- Пользователь в списке документов видит только свои неопубликованные документы и опубликованные документы других пользователей, но не видит неопубликованные документы других.
- Пользователь при попытке обратиться к чужому, неопубликованному документу получает 403.
- Время действия токена - 1 час.
Как будет вести себя ваше приложения с учетом попыток обновления одного документа несколькими клиентами одновременно? Если есть проблемы - надо их устранить.