Files
Pulse-API/README.md
T
github-classroom[bot] 1209dfe48d Initial commit
2024-02-26 19:09:59 +00:00

238 lines
20 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# PROD v2: Pulse Backend
Ваши коллеги разрабатывают социальную сеть для инвесторов. Уже совсем скоро им нужно сдавать проект, а вся команда бэкенд-разработчиков ушла в отпуск.
Кто-то проболтался о том, что вы знакомы с Git, HTTP, Docker, PostgreSQL и e2e-тестами. Это именно то, что нужно ребятам (а если с чем-то не знакомы, они рассчитывают на ваши навыки поиска информации)! Помогите коллегам успеть завершить проект до дедлайна и реализуйте новое HTTP API :)
Результатом выполнения данного задания является Github репозиторий с исходным кодом приложения (директория `solution`).
## Про приложение
Приложение должно представлять из себя HTTP сервер, реализующий необходимое [API](./tests/openapi.yml). В наследие от предыдущей команды вам достался инстанс PostgreSQL, который необходимо использовать для хранения данных.
Приложение должно конфигурироваться через переменные окружения:
- `SERVER_ADDRESS` — хост и порт, которые будет _слушать_ запущенный HTTP сервер. Например, `0.0.0.0:8080`.
- `SERVER_PORT` — содержит порт; запущенный сервер должен слушать IP `0.0.0.0` и указанный порт. Используйте эту переменную, если вам не подошел формат данных в переменной `SERVER_ADDRESS` (переданный параметры равнозначны).
- `POSTGRES_CONN` — DSN- **или** URL-строка для подключения к PostgreSQL. С форматами можно ознакомиться [здесь](https://pkg.go.dev/github.com/jackc/pgx/v4/pgxpool@v4.11.0#ParseConfig).
Пример: `user=postgres password=postgres host=localhost port=5432 dbname=pulse sslmode=verify-ca pool_max_conns=10`.
Учитывая современные реалии, приложение будет запускаться через Docker контейнер. В репозитории присутствует Dockerfile, с помощью которого будет собираться образ приложения.
Список используемых зависимостей не ограничен, однако вы должны убедиться, что необходимые зависимости загружаются и подключаются в Dockerfile.
Описание API находится ниже, но если вы хотите ознакомиться с точными требованиями, не стесняйтесь использовать Swagger и предоставленную [Open API спецификацию](./tests/openapi.yml).
Тестирование решения происходит с помощью Github CI. Для отправки решения на тестирование необходимо обновить исходный код вашего репозитория на Github (git commit & git push).
**Вы можете редактировать файлы в директории `solution`. Если в репозитории содержатся изменения в других файлах, решение не будет принято.**
## Оценивание
Для получения баллов за группу тестов решение должно пройти все тесты из данной группы.
Группы тестов могут зависеть друг от друга. Если группа B зависит от группы B, при тестировании группы B могут использоваться эндпоинты, участвовавшие в тестировании группы A. Это свойство транзитивно!
| Название группы | Описание | Баллы | От каких групп зависит |
|------------------|------------------------------------|-------|------------------------|
| 01/ping | Успешный ответ на `/api/ping`. | 1 | |
| 02/countries | Получение и фильтрация стран. | 6 | |
| 03/auth/register | Регистрация пользователей. | 6 | - 02/countries |
| 04/auth/sign-in | Аутентификация и получение токена. | 7 | - 03/auth/register |
| 05/me | Получение и редактирование собственного профиля. | 8 | - 04/auth/sign-in |
| 06/profiles | Получение профиля по логину. | 5 | - 04/auth/sign-in |
| 07/password | Изменение пароля. | 7 | - 05/me |
| 08/friends | Друзья! | 12 | - 04/auth/sign-in |
| 09/posts/publish | Публикация поста и получение по ID. | 12 | - 05/me<br>- 08/friends |
| 10/posts/feed | Получение новостной ленты. | 16 | - 09/posts/publish |
| 11/posts/likes | Лайки и дизлайки. | 20 | - 10/posts/feed |
В спорных ситуациях будет оцениваться качество кода.
На данный момент в Github CI тестирование производится на публичном наборе тестов. Данные тесты помогают провалидировать минимальную логику приложения, **но не гарантируют прохождения финальных тестов**.
## Группы тестов
### Общие требования
**У всех эндпоинтов есть префикс `/api`.**
Обратите внимание, возврат успешного ответа на `GET /api/ping` является **обязательным условием для начала тестирования приложения**.
Поступающие запросы и возвращаемые ответы должны соответствовать структуре и требованиям, описанным в [Open API](./tests/openapi.yml) спецификации. Обращайте внимание на ожидаемые status code, ограничения по длине и разрешенные символы в строках.
### 01/ping
Достаточно реализовать возврат успешного ответа (с кодом `200`) на запрос `GET /api/ping`. Содержимое тела ответа при этом не валидируется, можно возвращать `"ok"`.
Данная логика является блокирующей для всех остальных групп тестов.
### 02/countries
Как и в любом большом проекте у нас есть собственный словарь стран, который используется при регистрации пользователей и может учитываться рекомендательными системами и системой локализации контента.
Про каждую страну известны следующие данные:
```json
{
"name": "полное название",
"alpha2": "двухбуквенный код страны",
"alpha3": "трехбуквенный код страны",
"region": "географический регион"
}
```
Необходимо реализовать следующие эндпоинты:
- `GET /countries` &mdash; получить список доступных стран, доступна фильтрация по регионам.
- `GET /countries/{alpha2}` &mdash; получить страну по её уникальному двухбуквенному коду.
Самое интересное: **для получения списка стран необходимо использовать предоставленную СУБД PostgreSQL**.
Данные находятся в таблице `countries`, которая имеет следующее определение:
```sql
CREATE TABLE countries (
id SERIAL PRIMARY KEY,
name TEXT,
alpha2 TEXT,
alpha3 TEXT,
region TEXT
);
INSERT INTO countries (name, alpha2, alpha3, region) VALUES
('Åland Islands','AX','ALA','Europe'),
('Albania','AL','ALB','Europe'),
...;
```
При тестировании в Github CI база данных уже будет содержать нужный набор данных. Обратите внимание, данные в публичном и закрытом наборе тестов могут отличаться.
### 03/auth/register
Эндпоинт `/auth/register` используется для первичной регистрации пользователей.
Сервер должен поддерживать базу данных пользователей, валидировать запросы и не допускать наличия пользователей с эквивалентными регистрационными данными.
Не храните пароль пользователей в [открытом виде](https://security.stackexchange.com/questions/36833/why-should-i-hash-passwords), используется хеширование (например, bcrypt).
### 04/auth/sign-in
Эндпоинт `/auth/sign-in` предназначен для аутентификации пользователя по логину и паролю и генерации сессионного токена,
который в дальнейшем будет использоваться для генерации запросов.
Генерируемый токен должен уникально идентифицировать пользователя и быть сложным для подбора (можно использовать JWT).
Данный токен в дальнейшем будет передаваться пользователем в заголовке `Authorization: Bearer {token}`, и приложение должно уметь понять, какой пользователь хочет сделать запрос.
Временно будем считать, что время действия токена ограничено одним часом.
### 05/me
Эндпоинт `/me/profile` используется для получения и редактирования параметров собственного профиля пользователя. Действие зависит от указанного метода (`GET` и `PATCH`).
Сервер должен идентифицировать пользователя по переданному токену. Значение токена будет подставляться в заголовок `Authorization` в формате `Bearer {token}`. Например, `Authorization: Bearer $deddz$@pp...`.
В запросе на редактирование профиля передаются значения только тех полей, которые необходимо обновить.
### 06/profiles
Эндпоинт `/profiles/{login}` позволяет получить профиль другого пользователя по логину.
Обратите внимание, в некоторых ситуациях профиль пользователя получить нельзя (в зависимости от значения параметра `isPublic`). Для получения дополнительных деталей ознакомьтесь со спецификацией API.
### 07/password
С помощью `/me/updatePassword` у пользователя появляется возможность изменить пароль от своего аккаунта.
После изменения пароля:
- Аутентификация со старым паролем становится невозможной.
- Все ранее выпущенные токены должны быть отозваны.
После успешной смены пароля при попытке получить свой профиль со старым токеном пользователь должен получать ошибку.
### 08/friends
В приложении появляется возможность добавлять и удалять других пользователей в друзья.
И конечно же можно посмотреть список своих друзейЙ
Чтобы не нагружать сервера и клиенты слишком сильно, в запросах на получение списка друзей используется пагинация.
С помощью параметров `offset` и `limit` можно "постранично" получить весь список друзей, запрашивая данные порционно.
Вам потребуется запоминать дату и время последнего добавления в друзья для корректно сортировки и реализации пагинации.
### 09/posts/publish
В данной группе проверяется возможность создавать публикации со стороны пользователей.
Сервер должен генерировать уникальные идентификаторы и запоминать время создания публикаций.
У пользователя есть доступ к своим постам, постам пользователей с публичным профилем и постам других пользователей, которые добавили данного пользователя в друзья.
В данной группе не проверяются поля с лайками и дизлайками.
### 10/posts/feed
У пользователей появилась возможность смотреть новостную ленту со своими и чужими постами. Вместе с пагинацией.
В данной группе не проверяются поля с лайками и дизлайками.
### 11/posts/likes
Самое интересное: пользователи могут поставить лайк и дизлайк публикации, к которой у них есть доступ.
Всегда запоминается последняя реакция пользователя. Если пользователь поставил лайк два раза подряд, эффект лайка остается.
В полях `likesCount` и `dislikesCount` необходимо отразить уникальное число лайков и дизлайков.`
## Тестирование
Для тестирования решения отразите ваши изменения в Github репозитории. Разрешено изменять только директорию `solution`, иначе тесты не будут запущены.
### Тестирование в CI
Для тестирования решений используется [Github CI](https://docs.github.com/en/actions/automating-builds-and-tests/about-continuous-integration). При отправке новых изменений в репозиторий на Github активируется тестирующий пайплайн.
Пайплайн состоит из двух этапов:
- Сборка Docker образа с вашим приложением (на основании исходного кода репозитория и Dockerfile).
- Запуск тестов. Для каждой группы тестов
- запускаются Docker контейнеры с вашим приложением и PostgreSQL;
- тестирующая система дожидается успешного (`200`) ответа на `GET /api/ping`, на это дается не более 10 секунд;
- приложение считается запущенным и начинается запуск HTTP тестов из тестируемой группы.
Проверьте, что ваше приложение готово запускать HTTP сервер на адресе, переданном в переменной окружения `SERVER_ADDRESS`. **В качестве хоста (IP) передается `0.0.0.0`, а не localhost или 127.0.0.1. Это важно!**
Также проверьте локально, что Docker образ с вашим приложением собирается (выполните `docker build .` в директории `solution`).
Существующие ограничения:
- Решению выделяется 3 vCPU, 6 GB RAM и до 1 GB дискового пространства (не учитывая PostgreSQL).
- В рамках тестирования ваше приложение не должно завершать работу (помните о защите от Exception, panic и прочих причинах аварийного завершения).
- Сетевое взаимодействие разрешено только с PostgreSQL и тестирующей системой. Обращаться к сторонним ресурсам по сети нельзя.
Во вкладке Actions можно найти лог тестирования, в котором будут отражены результаты запуска тестов на публичном наборе тестов.
Прохождение публичного набора тестов не дает гарантию прохождения финальных тестов.
### Локальное тестирование
Для локального тестирования вы можете пользоваться [Postman](https://www.postman.com/). В директории проекта кто-то из коллег оставил [Postman коллекцию](./tests/public-tests.json) с публичными тестами для API. Не забудьте переопределить `base_url` в переменных коллекции.
Для инициализации СУБД PostgreSQL можно использовать [заранее подготовленный скрипт](./tests/init-database.sh), из которого можно выудить SQL запросы.
Чтобы локальное тестирование было максимально приближенным к тестированию в CI, мы рекомендуем запускать PostgreSQL и ваше приложение в Docker контейнерах (связанных одной сетью).
## Changelog
Как это часто бывает, заказчики проекта вносят правки в требования!
Ваших коллег ждала та же участь... Заказчики просили передать, что они будут стараться делать как можно меньше изменений.
Но удача на нашей стороне! Коллеги будут фиксировать все правки в данном документе и вести ченджлог изменений.