Процесс онбординга компании (для фронтов)
Дано:
- Компания, заключившая с нами договор об аутсорсе (?).
- E-mails менеджеров компании, которым мы высылаем инвайт.
Шаг 1. Регистрация
- От лица нашей основной компании - SWAP Administration Company мы рассылаем всем работникам и менеджерам инвайты на вход в систему.
Допустим, UUID нашей основной компании - 3e908dab-591c-4247-ab73-68d99e7dd8d7 (SWAP Administration Company).
Посмотреть UUID для компании можно здесь: https://api.dev.goswap.app/admin/common/company/
| HTTP | |
|---|---|
1 2 3 4 5 6 7 8 | |
Здесь стоит пояснить важную деталь:
- Компания "SWAP Administration" (наша системная админ-компания) может приглашать ТОЛЬКО менеджеров компании для регистрации ими их компаний. То есть проще говоря, в пэйлоуде
invited_by_company == "3e908dab-591c-4247-ab73-68d99e7dd8d7". -
Когда компании приглашают сотрудников или работников - они приглашают их от имени СВОЕЙ компании (допустим, её id:
c0bb3efa-fb2b-4a1d-bc30-62a7a9456636), в этом случае в пэйлоуде будетinvited_by_company == "c0bb3efa-fb2b-4a1d-bc30-62a7a9456636" -
При создании приглашения менеджерам компании на бэкэнде автоматически регистрируются их временные1 аккаунты (со временным паролем - токеном от приглашения) и они получают письмо на свои почтовые адреса о том, что компания "SWAP Administration" (или другая - инициатор выдачи приглашений пользователям) приглашает вас зарегистрироваться в системе SWAP по уникальной ссылке.
Вот как это письмо выглядит (персональные данные замазаны):

-
Пользователь переходит по этой ссылке (или qrcode, который представляет эту же ссылку) из письма, тем самым инициируя вход в систему под временным паролем.
Внутри себя фронтэнд:
Сначала вызывает проверку этого токена:
HTTP 1POST api.dev.goswap.app/v1/client-invitations/verify-token/1gk9EzSJdfxvgUALOZHY2cASuPmzrhgdPfJoyAkOugcИ если токен валиден, проверка возвращает ему email пользователя в пэйлоуде.
Дальше фронт логинит пользователя с данными, которые пришли ему при переходе по ссылке в письме.
Где
email- query param 'email', аpassword- query param 'token'.HTTP 1 2
POST api.dev.goswap.app/v1/auth/regular/login/ {"email": "[email protected]", "password": "1gk9EzSJdfxvgUALOZHY2cASuPmzrhgdPfJoyAkOugc"}И помещает вернувшиеся
access_tokenиverify_tokenиз пэйлоуда в cookies после успешного входа в систему.Фронты, внимание!
Вы выполняете этот запрос когда пользователь переходит по ссылке или qrcode из email на сайт. Проще говоря - пользователь должен быть уже залогинен в свой временный аккаунт, когда зайдёт на экран с установкой пароля. Иначе пароль не сменится!
POST api.dev.goswap.app/v1/auth/regular/password/change/работает только для активного (то есть залогинившегося) пользователя!Вопрос: а может ли залогинить пользователя бэк и вернуть хидеры авторизации в verify token?
Ответ: Фактически это будет неправильным поведением с точки зрения логики верификации. Верификация - не производит авторизацию, она проверяет только факт валидности токена. Аутентификация и верификация - априори два разных процесса, имеющих абсолютно разную логику.
-
Авторизовавшись (бесшовно для фронта), пользователь - менеджер компании попадает на страницу создания нового пароля (экран 1.0). Ему остаётся только поменять временный пароль на свой и установить дату рождения, ФИО и т.д. Это два запроса:
- Смена пароля
HTTP 1 2
POST api.dev.goswap.app/v1/auth/regular/password/change/ {"new_password1": "<new_password>", "new_password2": "<new_password>"}- Обновление базовых данных аккаунта уже авторизованного пользователя
HTTP 1 2 3 4 5 6
PATCH api.dev.goswap.app/v1/auth/regular/user/ { "username": "kai_alves_lima", "full_name": "Kai Alves Lima", "birth_date": "1968-01-08" }
Однако фронтам стоит учесть, что созданный аккаунт временный (вы получите эту инфу в результате выполнения запроса POST core.dev.goswap.app/api/v1/auth/regular/login/ в поле "is_verified": false объекта user) и после запроса на сохранение данных запросить ещё отправку верификационного email, выполнив следующий запрос:
| HTTP | |
|---|---|
1 2 | |
Шаг 2. Создание (открытие) клиентской сессии
Клиентская сессия - это все данные, которые мы сохраняем с разных формочек на клиенте и которые будут использованы для синхронизации между устройствами.
Сейчас объясню на примере.
Условно, начал сотрудник компании заполнение профиля компании в телефоне, затем понял, что некоторые документы у него только на компе и решил перейти на комп. И чтобы ему не вводить всё по новой - мы сохраняем состояние его клиентской сессии в БД. Затем, когда он переходит за комп, и авторизуется в системе - мы находим открытую его сессию на телефоне с данными форм и переносим их на комп. После чего сессию на телефоне мы можем закрыть или оставить. Любые изменения в формах на фронте влекут за собой вызов следующего запроса:
| HTTP | |
|---|---|
1 2 | |
Фронты, внимание!
Этот запрос полностью меняет содержимое полей (не prepend, а замена!), поэтому вы должны отправлять мне ВСЕ поля, включая неизменённые. Возможно в дальнейшем я поправлю эту логику, когда пойму, как лучше сделать.
Для создания (открытия) клиентской сессии в первую очередь нужно сгенерировать session_id.
Сгенерировать {session_id} нужно на фронтэнде, например, вот таким способом:
| JavaScript | |
|---|---|
1 | |
Допустим, эта команда сгенерировала нам следующий Session ID: i4mch15iicbvhhrhpx1bohv1zvvzeidulmi
Для открытия клиентской сессии на бэкэнде нужно выполнить следующий POST запрос (не забывая прикрепить хидеры клиентского приложения):
| Bash | |
|---|---|
1 2 3 4 5 6 7 8 | |
Данные для хидеров можно посмотреть здесь: https://api.dev.goswap.app/admin/authentication/clientapplication/
Для фронтэнда берём Web, для мобильных устройств Mobile.
В ответ вернётся подобный response:
| Text Only | |
|---|---|
1 2 3 4 5 6 7 8 9 | |
Шаг 3. Заполнение базовых данных компании
Создаём компанию (не профиль, а саму компанию). В фигме это экран 1.1 на странице company - тот, что слева от этого экрана. Прямая ссылка на него: https://www.figma.com/design/GTSngpLtUDwLxAwGL4aa7D/mobile-SWAP?node-id=2435-50847&t=JHQ6Bd8yrKOKs8r4-4
| HTTP | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 | |
Как это всё работает (диаграмма)
flowchart TD
%% nodes description
node_start((start))
node_end((end))
step1["
Компания SWAP Administration создаёт приглашение (в бэкофисе или джанговской админке сервиса core) для конкретного менеджера компании по его email (например [email protected]).
При создании приглашения автоматически генерируется пригласительная ссылка,
вида <a href='#'>https://dev.goswap.app/invite/?token=1gk9EzSJdfxvgUALOZHY2cASuPmzrhgdPfJoyAkOugc&[email protected]&role=COMPANY_MANAGER</a>
и пользователю автоматически создаётся (если не был создан) аккаунт на бэкэнде по его email со временным паролем.
"]
step2["
По этой ссылке осуществляется переход на фронтэнд.
"]
step3["
На фронтэнде проверяется валидность токена <code>1gk9EzSJdfxvgUALOZHY2cASuPmzrhgdPfJoyAkOugc</code>
посредством отправки на бэкэнд запроса POST <a href='#'>https://api.dev.goswap.app/v1/client-invitations/verify-token/1gk9EzSJdfxvgUALOZHY2cASuPmzrhgdPfJoyAkOugc</a>
"]
step4{"Токен валидный (т.е. существует и не просрочен?)"}
step5["404 Not Found (если не существует) или 410 Gone (если просрочен)"]
step6["
Фронтэнд генерирует Id сессии и отправляет на бэкэнд POST запрос для открытия новой сессии (не забывая прикрепить хидеры клиентского приложения).
POST <a href="">https://api.dev.goswap.app/v1/auth/client-sessions/{session_id}</a>
"]
step7["
Когда сессия открылась, фронтэнд забирает <code>session_id</code> из вернувшегося пэйлоуда и использует его для авторизации сессии либо
в header <code>X-SWAP-CLIENT-SESSION-ID</code>, либо в cookie <code>swap_client_session_id</code>
"]
step8["
Проверить состояние сессии можно в любой момент по запросу
GET <a href>https://api.dev.goswap.app/v1/auth/client-sessions/{session_id}</a>
(не забываем прикрепить хидеры клиентского приложения)
Если сессия просрочилась - вернётся 410 Gone.
Если сессии с таким <code>session_id</code> не существует - вернётся 404 Not found.
В противном случае вернётся следующая детализация сессии:
{'id': '3f087e5f-3e07-4d31-a625-8fc1d1d597c3', 'expired_at': '2025-08-01T08:03:36.850059Z', 'created_at': '2025-07-31T08:03:36.850059Z', 'updated_at': '2025-07-31T08:03:36.850079Z', 'session_id': 'aSjrlYnFhsWrOeE1y0d38VyZsq47nzFddOWWfq2HPic', 'token': 'DfIsocWnQrZAHT65cJmIpZoWvH_k7hJyTBCICFDhWro', 'time_to_live': 86400}
"]
%% flowchart
node_start --> step1
step1 --> step2
step2 --> step3
step3 --> step4
step4 --> |Нет| step5
step4 --> |Да| step6
step5 --> step1
step6 --> step7
step7 --> step8
step8 --> node_end
-
временные - потому что все неверифицированные аккаунты чистятся определённой таской в кронтабе, условно - раз в неделю ↩