2024-02-26 19:09:59 +00:00
2024-02-26 19:09:59 +00:00
2024-02-26 19:09:59 +00:00

PROD v2: Pulse Backend

Ваши коллеги разрабатывают социальную сеть для инвесторов. Уже совсем скоро им нужно сдавать проект, а вся команда бэкенд-разработчиков ушла в отпуск.

Кто-то проболтался о том, что вы знакомы с Git, HTTP, Docker, PostgreSQL и e2e-тестами. Это именно то, что нужно ребятам (а если с чем-то не знакомы, они рассчитывают на ваши навыки поиска информации)! Помогите коллегам успеть завершить проект до дедлайна и реализуйте новое HTTP API :)

Результатом выполнения данного задания является Github репозиторий с исходным кодом приложения (директория solution).

Про приложение

Приложение должно представлять из себя HTTP сервер, реализующий необходимое API. В наследие от предыдущей команды вам достался инстанс PostgreSQL, который необходимо использовать для хранения данных.

Приложение должно конфигурироваться через переменные окружения:

  • SERVER_ADDRESS — хост и порт, которые будет слушать запущенный HTTP сервер. Например, 0.0.0.0:8080.

  • SERVER_PORT — содержит порт; запущенный сервер должен слушать IP 0.0.0.0 и указанный порт. Используйте эту переменную, если вам не подошел формат данных в переменной SERVER_ADDRESS (переданный параметры равнозначны).

  • POSTGRES_CONN — DSN- или URL-строка для подключения к PostgreSQL. С форматами можно ознакомиться здесь. Пример: user=postgres password=postgres host=localhost port=5432 dbname=pulse sslmode=verify-ca pool_max_conns=10.

Учитывая современные реалии, приложение будет запускаться через Docker контейнер. В репозитории присутствует Dockerfile, с помощью которого будет собираться образ приложения.

Список используемых зависимостей не ограничен, однако вы должны убедиться, что необходимые зависимости загружаются и подключаются в Dockerfile.

Описание API находится ниже, но если вы хотите ознакомиться с точными требованиями, не стесняйтесь использовать Swagger и предоставленную Open API спецификацию.

Тестирование решения происходит с помощью 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
- 08/friends
10/posts/feed Получение новостной ленты. 16 - 09/posts/publish
11/posts/likes Лайки и дизлайки. 20 - 10/posts/feed

В спорных ситуациях будет оцениваться качество кода.

На данный момент в Github CI тестирование производится на публичном наборе тестов. Данные тесты помогают провалидировать минимальную логику приложения, но не гарантируют прохождения финальных тестов.

Группы тестов

Общие требования

У всех эндпоинтов есть префикс /api.

Обратите внимание, возврат успешного ответа на GET /api/ping является обязательным условием для начала тестирования приложения.

Поступающие запросы и возвращаемые ответы должны соответствовать структуре и требованиям, описанным в Open API спецификации. Обращайте внимание на ожидаемые status code, ограничения по длине и разрешенные символы в строках.

01/ping

Достаточно реализовать возврат успешного ответа (с кодом 200) на запрос GET /api/ping. Содержимое тела ответа при этом не валидируется, можно возвращать "ok".

Данная логика является блокирующей для всех остальных групп тестов.

02/countries

Как и в любом большом проекте у нас есть собственный словарь стран, который используется при регистрации пользователей и может учитываться рекомендательными системами и системой локализации контента.

Про каждую страну известны следующие данные:

{
    "name": "полное название",
    "alpha2": "двухбуквенный код страны",
    "alpha3": "трехбуквенный код страны",
    "region": "географический регион"
}

Необходимо реализовать следующие эндпоинты:

  • GET /countries — получить список доступных стран, доступна фильтрация по регионам.

  • GET /countries/{alpha2} — получить страну по её уникальному двухбуквенному коду.

Самое интересное: для получения списка стран необходимо использовать предоставленную СУБД PostgreSQL.

Данные находятся в таблице countries, которая имеет следующее определение:

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 используется для первичной регистрации пользователей.

Сервер должен поддерживать базу данных пользователей, валидировать запросы и не допускать наличия пользователей с эквивалентными регистрационными данными.

Не храните пароль пользователей в открытом виде, используется хеширование (например, 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. При отправке новых изменений в репозиторий на 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. В директории проекта кто-то из коллег оставил Postman коллекцию с публичными тестами для API. Не забудьте переопределить base_url в переменных коллекции.

Для инициализации СУБД PostgreSQL можно использовать заранее подготовленный скрипт, из которого можно выудить SQL запросы.

Чтобы локальное тестирование было максимально приближенным к тестированию в CI, мы рекомендуем запускать PostgreSQL и ваше приложение в Docker контейнерах (связанных одной сетью).

Changelog

Как это часто бывает, заказчики проекта вносят правки в требования! Ваших коллег ждала та же участь... Заказчики просили передать, что они будут стараться делать как можно меньше изменений.

Но удача на нашей стороне! Коллеги будут фиксировать все правки в данном документе и вести ченджлог изменений.

S
Description
My solution for the second qualifying stage of the PROD Olympiad. Passes all tests.
Readme 164 KiB
Languages
Python 77.5%
Shell 21.7%
Dockerfile 0.8%