04 -- Data Flow: Admin Service
This document describes the data flow for every Admin Service endpoint using Mermaid sequence diagrams, and provides business logic flowcharts for the most complex service methods. It covers admin authentication (passwordless), project management, and user management.
1. Admin Registration Flow
Заголовок раздела «1. Admin Registration Flow»1.1 POST /v1/admin/auth/register
Заголовок раздела «1.1 POST /v1/admin/auth/register»Initiates passwordless registration by validating the admin email domain, checking for existing users and cooldowns, then generating and sending a verification code.
sequenceDiagram autonumber actor Client participant Controller as AdminAuthController participant Service as AdminAuthService participant UserService as UserService participant Redis as RedisClientService participant Email as EmailSenderService
Client->>+Controller: POST /v1/admin/auth/register {email} Controller->>+Service: register(dto)
Service->>Service: Validate email domain against ADMIN_ALLOWED_DOMAINS alt Domain not allowed Service-->>Controller: BadRequestException("Invalid email domain") Controller-->>Client: 400 Bad Request end
Service->>+UserService: findOneByEmail(email) UserService-->>-Service: user | null alt User already exists Service-->>Controller: ConflictException("User already exists") Controller-->>Client: 409 Conflict end
Service->>+Redis: get("ADMIN_VERIFICATION_RESEND_CODE:email={email}") Redis-->>-Service: cooldown | null alt Cooldown active Service-->>Controller: TooManyRequestsException("Please wait before resending") Controller-->>Client: 429 Too Many Requests end
Service->>Service: getRandomCode(6) -> code
Service->>+Redis: set("ADMIN_VERIFICATION_CODE:email={email}", code, TTL=900s) Redis-->>-Service: OK Service->>+Redis: set("ADMIN_VERIFICATION_RESEND_CODE:email={email}", "1", TTL=120s) Redis-->>-Service: OK
Service->>+Email: sendAdminVerificationEmail(email, code) Email-->>-Service: sent
Service-->>-Controller: { message: "Verification code sent" } Controller-->>-Client: 201 { message: "Verification code sent" }1.2 POST /v1/admin/auth/register/verify
Заголовок раздела «1.2 POST /v1/admin/auth/register/verify»Verifies the registration code, creates the user with ADMIN role, establishes a session, and returns a JWT token pair.
sequenceDiagram autonumber actor Client participant Controller as AdminAuthController participant Service as AdminAuthService participant Redis as RedisClientService participant UserService as UserService participant RoleService as UserOnRole participant SessionService as SessionService participant TokenAdmin as TokenAdminService participant TokenService as TokenService participant DB as PostgreSQL
Client->>+Controller: POST /v1/admin/auth/register/verify {email, code, fingerprint} Controller->>+Service: registerVerify(dto)
Service->>+Redis: get("ADMIN_VERIFICATION_CODE:email={email}") Redis-->>-Service: storedCode | null alt Code not found (expired) Service-->>Controller: NotFoundException("Verification code expired") Controller-->>Client: 404 Not Found end
alt Code does not match Service-->>Controller: BadRequestException("Invalid verification code") Controller-->>Client: 400 Bad Request end
Service->>+Redis: del("ADMIN_VERIFICATION_CODE:email={email}") Redis-->>-Service: OK
Note over Service,DB: @Transactional() begins Service->>+UserService: create({email}) (no password) UserService->>DB: INSERT INTO users DB-->>UserService: user UserService-->>-Service: user
Service->>+RoleService: create({userId, roleType: ADMIN}) RoleService->>DB: INSERT INTO user_on_role DB-->>RoleService: userOnRole RoleService-->>-Service: userOnRole
Service->>+SessionService: create({userId, fingerprint}) SessionService->>DB: INSERT INTO sessions DB-->>SessionService: session SessionService-->>-Service: session Note over Service,DB: @Transactional() commits
Service->>+TokenAdmin: generateAdminTokenPair(payload) TokenAdmin-->>-Service: {accessToken, refreshToken}
Service->>+TokenService: saveOne({sessionId, tokenId, ...}) TokenService->>DB: INSERT INTO tokens DB-->>TokenService: token TokenService-->>-Service: token
Service-->>-Controller: {accessToken, refreshToken} Controller-->>-Client: 201 {accessToken, refreshToken} + Set-Cookie(refreshToken)2. Admin Login Flow
Заголовок раздела «2. Admin Login Flow»2.1 POST /v1/admin/auth/login
Заголовок раздела «2.1 POST /v1/admin/auth/login»Initiates passwordless login by verifying admin role, checking the user is not blocked, then generating and sending a verification code.
sequenceDiagram autonumber actor Client participant Controller as AdminAuthController participant Service as AdminAuthService participant UserService as UserService participant Redis as RedisClientService participant Email as EmailSenderService
Client->>+Controller: POST /v1/admin/auth/login {email} Controller->>+Service: login(dto)
Service->>+UserService: findOneByEmail(email, include: userOnRole.role) UserService-->>-Service: user | null alt User not found Service-->>Controller: NotFoundException("User not found") Controller-->>Client: 404 Not Found end
Service->>Service: Check user has ADMIN role alt User does not have ADMIN role Service-->>Controller: ForbiddenException("Not an admin") Controller-->>Client: 403 Forbidden end
Service->>Service: Check user.isBlocked === false alt User is blocked Service-->>Controller: ForbiddenException("User is blocked") Controller-->>Client: 403 Forbidden end
Service->>+Redis: get("ADMIN_VERIFICATION_RESEND_CODE:email={email}") Redis-->>-Service: cooldown | null alt Cooldown active Service-->>Controller: TooManyRequestsException("Please wait before resending") Controller-->>Client: 429 Too Many Requests end
Service->>Service: getRandomCode(6) -> code
Service->>+Redis: set("ADMIN_VERIFICATION_CODE:email={email}", code, TTL=900s) Redis-->>-Service: OK Service->>+Redis: set("ADMIN_VERIFICATION_RESEND_CODE:email={email}", "1", TTL=120s) Redis-->>-Service: OK
Service->>+Email: sendAdminVerificationEmail(email, code) Email-->>-Service: sent
Service-->>-Controller: { message: "Verification code sent" } Controller-->>-Client: 200 { message: "Verification code sent" }2.2 POST /v1/admin/auth/login/verify
Заголовок раздела «2.2 POST /v1/admin/auth/login/verify»Verifies the login code, finds or creates a session, and returns a JWT token pair.
sequenceDiagram autonumber actor Client participant Controller as AdminAuthController participant Service as AdminAuthService participant Redis as RedisClientService participant UserService as UserService participant SessionService as SessionService participant TokenAdmin as TokenAdminService participant TokenService as TokenService participant DB as PostgreSQL
Client->>+Controller: POST /v1/admin/auth/login/verify {email, code, fingerprint} Controller->>+Service: loginVerify(dto)
Service->>+Redis: get("ADMIN_VERIFICATION_CODE:email={email}") Redis-->>-Service: storedCode | null alt Code not found (expired) Service-->>Controller: NotFoundException("Verification code expired") Controller-->>Client: 404 Not Found end
alt Code does not match Service-->>Controller: BadRequestException("Invalid verification code") Controller-->>Client: 400 Bad Request end
Service->>+Redis: del("ADMIN_VERIFICATION_CODE:email={email}") Redis-->>-Service: OK
Service->>+UserService: findOneByEmail(email) UserService-->>-Service: user
Service->>+SessionService: findOneBy({userId: user.id, fingerprint}) SessionService-->>-Service: session | null
alt Session not found Service->>+SessionService: create({userId: user.id, fingerprint}) SessionService->>DB: INSERT INTO sessions DB-->>SessionService: session SessionService-->>-Service: session end
Service->>+TokenAdmin: generateAdminTokenPair(payload) TokenAdmin-->>-Service: {accessToken, refreshToken}
Service->>+TokenService: saveOne({sessionId, tokenId, ...}) TokenService->>DB: UPSERT INTO tokens DB-->>TokenService: token TokenService-->>-Service: token
Service->>+SessionService: update(session.id, {tokenId}) SessionService->>DB: UPDATE sessions DB-->>SessionService: session SessionService-->>-Service: session
Service-->>-Controller: {accessToken, refreshToken} Controller-->>-Client: 200 {accessToken, refreshToken} + Set-Cookie(refreshToken)3. Admin Token Refresh
Заголовок раздела «3. Admin Token Refresh»3.1 POST /v1/admin/auth/refresh
Заголовок раздела «3.1 POST /v1/admin/auth/refresh»Validates the refresh token via the AdminRefreshTokenGuard, then generates a new token pair and rotates the stored token.
sequenceDiagram autonumber actor Client participant Guard as AdminRefreshTokenGuard participant Controller as AdminAuthRefreshTokenController participant Service as AdminAuthRefreshTokenService participant SessionService as SessionService participant TokenAdmin as TokenAdminService participant TokenService as TokenService participant DB as PostgreSQL
Client->>+Guard: POST /v1/admin/auth/refresh (Cookie: refreshToken, Headers: fingerprint, sessionId) Guard->>Guard: Validate refresh JWT with admin secret
alt Token invalid or expired Guard-->>Client: 401 Unauthorized else Token valid Guard->>+Controller: Request (tokenPayload injected) end
Controller->>Controller: @GetTokenPayload() -> tokenPayload Controller->>Controller: @HeaderFingerprint() -> fingerprint Controller->>Controller: @HeaderSessionId() -> sessionId
Controller->>+Service: refresh(tokenPayload, fingerprint, sessionId)
Service->>+SessionService: findOneById(sessionId) SessionService-->>-Service: session | null alt Session not found Service-->>Controller: UnauthorizedException("Session not found") Controller-->>Client: 401 Unauthorized end
Service->>Service: Validate session.fingerprint === fingerprint alt Fingerprint mismatch Service-->>Controller: UnauthorizedException("Invalid fingerprint") Controller-->>Client: 401 Unauthorized end
Service->>+TokenAdmin: generateAdminTokenPair(newPayload) TokenAdmin-->>-Service: {accessToken, refreshToken}
Service->>+TokenService: updateOne(tokenPayload.tokenId, {newTokenId, ...}) TokenService->>DB: UPDATE tokens DB-->>TokenService: token TokenService-->>-Service: token
Service-->>-Controller: {accessToken, refreshToken} Controller-->>-Client: 200 {token: accessToken} + Set-Cookie(refreshToken)4. Admin Project Management
Заголовок раздела «4. Admin Project Management»4.1 GET /v1/admin/projects
Заголовок раздела «4.1 GET /v1/admin/projects»Lists all non-deleted projects with optional filtering by status, category, and title search. Returns a paginated response.
sequenceDiagram autonumber actor Client participant Guard as AdminAccessTokenGuard participant Controller as AdminProjectController participant Service as AdminProjectService participant Repo as AdminProjectRepository participant Mapper as MapperService participant DB as PostgreSQL
Client->>+Guard: GET /v1/admin/projects?status=X&category=Y&title=Z&page=1&limit=10 (Bearer accessToken) Guard->>Guard: Validate access JWT with admin secret
alt Not authenticated Guard-->>Client: 401 Unauthorized else Authenticated Guard->>+Controller: Request (user context injected) end
Controller->>+Service: findAll(query)
Service->>Service: Build where clause Note over Service: { deletedAt: null, ...(status), ...(category), ...(title: contains/insensitive) }
Service->>+Repo: findManyAndPaginate({ where, include: { customer: { include: { user: { select: {id, email} } } } }, paginate: getPaginate(query) }) Repo->>+DB: SELECT projects with joins DB-->>-Repo: rows + count Repo-->>-Service: paginatedResult
Service->>+Mapper: toPaginateResponse(result, AdminProjectResponseDto) Mapper-->>-Service: paginatedResponse
Service-->>-Controller: paginatedResponse Controller-->>-Client: 200 PaginatedResponse<AdminProjectResponseDto>4.2 GET /v1/admin/projects/:id
Заголовок раздела «4.2 GET /v1/admin/projects/:id»Retrieves a single non-deleted project by ID, including owner details.
sequenceDiagram autonumber actor Client participant Guard as AdminAccessTokenGuard participant Controller as AdminProjectController participant Service as AdminProjectService participant Repo as AdminProjectRepository participant DB as PostgreSQL
Client->>+Guard: GET /v1/admin/projects/:id (Bearer accessToken) Guard->>Guard: Validate access JWT with admin secret
alt Not authenticated Guard-->>Client: 401 Unauthorized else Authenticated Guard->>+Controller: Request end
Controller->>+Service: findOneByIdOrFail(id)
Service->>+Repo: findOne({ where: { id, deletedAt: null }, include: { customer: { include: { user: true } } } }) Repo->>+DB: SELECT project WHERE id AND deletedAt IS NULL DB-->>-Repo: project | null Repo-->>-Service: project | null
alt Project not found Service-->>Controller: NotFoundException("Project not found") Controller-->>Client: 404 Not Found else Project found Service-->>-Controller: AdminProjectResponseDto Controller-->>-Client: 200 AdminProjectResponseDto end4.3 PATCH /v1/admin/projects/:id
Заголовок раздела «4.3 PATCH /v1/admin/projects/:id»Updates a project. If the status field is being changed, validates the transition against PROJECT_STATUS_TRANSITIONS.
sequenceDiagram autonumber actor Client participant Guard as AdminAccessTokenGuard participant Controller as AdminProjectController participant Service as AdminProjectService participant Repo as AdminProjectRepository participant DB as PostgreSQL
Client->>+Guard: PATCH /v1/admin/projects/:id (Bearer accessToken) {status?, title?, ...} Guard->>Guard: Validate access JWT with admin secret
alt Not authenticated Guard-->>Client: 401 Unauthorized else Authenticated Guard->>+Controller: Request end
Controller->>+Service: updateOneById(id, dto)
Service->>+Repo: findOne({ where: { id, deletedAt: null } }) Repo->>+DB: SELECT project DB-->>-Repo: project | null Repo-->>-Service: project | null
alt Project not found Service-->>Controller: NotFoundException("Project not found") Controller-->>Client: 404 Not Found end
alt dto contains status change Service->>Service: Check PROJECT_STATUS_TRANSITIONS[currentStatus] includes newStatus alt Invalid transition Service-->>Controller: BadRequestException("Invalid status transition") Controller-->>Client: 400 Bad Request end end
Service->>+Repo: update(id, dto) Repo->>+DB: UPDATE projects SET ... WHERE id DB-->>-Repo: updatedProject Repo-->>-Service: updatedProject
Service-->>-Controller: AdminProjectResponseDto Controller-->>-Client: 200 AdminProjectResponseDto4.4 DELETE /v1/admin/projects/:id
Заголовок раздела «4.4 DELETE /v1/admin/projects/:id»Soft-deletes a project by setting deletedAt to the current timestamp.
sequenceDiagram autonumber actor Client participant Guard as AdminAccessTokenGuard participant Controller as AdminProjectController participant Service as AdminProjectService participant Repo as AdminProjectRepository participant DB as PostgreSQL
Client->>+Guard: DELETE /v1/admin/projects/:id (Bearer accessToken) Guard->>Guard: Validate access JWT with admin secret
alt Not authenticated Guard-->>Client: 401 Unauthorized else Authenticated Guard->>+Controller: Request end
Controller->>+Service: softDeleteOneById(id)
Service->>+Repo: findOne({ where: { id, deletedAt: null } }) Repo->>+DB: SELECT project DB-->>-Repo: project | null Repo-->>-Service: project | null
alt Project not found Service-->>Controller: NotFoundException("Project not found") Controller-->>Client: 404 Not Found end
Service->>+Repo: update(id, { deletedAt: new Date() }) Repo->>+DB: UPDATE projects SET deletedAt = NOW() WHERE id DB-->>-Repo: updatedProject Repo-->>-Service: updatedProject
Service-->>-Controller: void Controller-->>-Client: 204 No Content5. Admin User Management
Заголовок раздела «5. Admin User Management»5.1 GET /v1/admin/users
Заголовок раздела «5.1 GET /v1/admin/users»Lists all users with optional filtering by role, blocked status, and email search. Returns a paginated response.
sequenceDiagram autonumber actor Client participant Guard as AdminAccessTokenGuard participant Controller as AdminUserController participant Service as AdminUserService participant Repo as AdminUserRepository participant Mapper as MapperService participant DB as PostgreSQL
Client->>+Guard: GET /v1/admin/users?role=X&isBlocked=true&email=Z&page=1&limit=10 (Bearer accessToken) Guard->>Guard: Validate access JWT with admin secret
alt Not authenticated Guard-->>Client: 401 Unauthorized else Authenticated Guard->>+Controller: Request end
Controller->>+Service: findAll(query)
Service->>Service: Build where clause Note over Service: { ...(role: via userOnRole filter), ...(isBlocked), ...(email: contains/insensitive) }
Service->>+Repo: findManyAndPaginate({ where, include: { userOnRole: { include: { role: true } } }, paginate: getPaginate(query) }) Repo->>+DB: SELECT users with joins DB-->>-Repo: rows + count Repo-->>-Service: paginatedResult
Service->>+Mapper: toPaginateResponse(result, AdminUserResponseDto) Mapper-->>-Service: paginatedResponse
Service-->>-Controller: paginatedResponse Controller-->>-Client: 200 PaginatedResponse<AdminUserResponseDto>5.2 GET /v1/admin/users/:id
Заголовок раздела «5.2 GET /v1/admin/users/:id»Retrieves a single user by ID with full details including roles, profile, and associated projects.
sequenceDiagram autonumber actor Client participant Guard as AdminAccessTokenGuard participant Controller as AdminUserController participant Service as AdminUserService participant Repo as AdminUserRepository participant DB as PostgreSQL
Client->>+Guard: GET /v1/admin/users/:id (Bearer accessToken) Guard->>Guard: Validate access JWT with admin secret
alt Not authenticated Guard-->>Client: 401 Unauthorized else Authenticated Guard->>+Controller: Request end
Controller->>+Service: findOneByIdOrFail(id)
Service->>+Repo: findOne({ where: { id }, include: { userOnRole: { include: { role: true } }, profile: true, customer: { include: { projects: true } } } }) Repo->>+DB: SELECT user with joins DB-->>-Repo: user | null Repo-->>-Service: user | null
alt User not found Service-->>Controller: NotFoundException("User not found") Controller-->>Client: 404 Not Found else User found Service-->>-Controller: AdminUserDetailResponseDto Controller-->>-Client: 200 AdminUserDetailResponseDto end5.3 PATCH /v1/admin/users/:id/block
Заголовок раздела «5.3 PATCH /v1/admin/users/:id/block»Blocks a non-admin user by setting isBlocked to true. Prevents blocking users with the ADMIN role.
sequenceDiagram autonumber actor Client participant Guard as AdminAccessTokenGuard participant Controller as AdminUserController participant Service as AdminUserService participant Repo as AdminUserRepository participant DB as PostgreSQL
Client->>+Guard: PATCH /v1/admin/users/:id/block (Bearer accessToken) Guard->>Guard: Validate access JWT with admin secret
alt Not authenticated Guard-->>Client: 401 Unauthorized else Authenticated Guard->>+Controller: Request end
Controller->>+Service: blockUser(id)
Service->>+Repo: findOne({ where: { id }, include: { userOnRole: { include: { role: true } } } }) Repo->>+DB: SELECT user with roles DB-->>-Repo: user | null Repo-->>-Service: user | null
alt User not found Service-->>Controller: NotFoundException("User not found") Controller-->>Client: 404 Not Found end
Service->>Service: Check if user has ADMIN role alt User has ADMIN role Service-->>Controller: ForbiddenException("Cannot block admin") Controller-->>Client: 403 Forbidden end
Service->>+Repo: update(id, { isBlocked: true }) Repo->>+DB: UPDATE users SET isBlocked = true WHERE id DB-->>-Repo: updatedUser Repo-->>-Service: updatedUser
Service-->>-Controller: { message: "User blocked" } Controller-->>-Client: 200 { message: "User blocked" }5.4 PATCH /v1/admin/users/:id/unblock
Заголовок раздела «5.4 PATCH /v1/admin/users/:id/unblock»Unblocks a user by setting isBlocked to false.
sequenceDiagram autonumber actor Client participant Guard as AdminAccessTokenGuard participant Controller as AdminUserController participant Service as AdminUserService participant Repo as AdminUserRepository participant DB as PostgreSQL
Client->>+Guard: PATCH /v1/admin/users/:id/unblock (Bearer accessToken) Guard->>Guard: Validate access JWT with admin secret
alt Not authenticated Guard-->>Client: 401 Unauthorized else Authenticated Guard->>+Controller: Request end
Controller->>+Service: unblockUser(id)
Service->>+Repo: findOne({ where: { id } }) Repo->>+DB: SELECT user DB-->>-Repo: user | null Repo-->>-Service: user | null
alt User not found Service-->>Controller: NotFoundException("User not found") Controller-->>Client: 404 Not Found end
Service->>+Repo: update(id, { isBlocked: false }) Repo->>+DB: UPDATE users SET isBlocked = false WHERE id DB-->>-Repo: updatedUser Repo-->>-Service: updatedUser
Service-->>-Controller: { message: "User unblocked" } Controller-->>-Client: 200 { message: "User unblocked" }6. Business Logic Flowcharts
Заголовок раздела «6. Business Logic Flowcharts»6.1 AdminAuthService.register()
Заголовок раздела «6.1 AdminAuthService.register()»Domain validation, user existence check, cooldown enforcement, code generation, Redis storage, and email dispatch.
flowchart TD A["register(dto)"] --> B{"Is email domain\nin ADMIN_ALLOWED_DOMAINS?"} B -- No --> C["Throw BadRequestException\n(Invalid email domain)"] B -- Yes --> D["UserService.findOneByEmail(email)"] D --> E{"User exists?"} E -- Yes --> F["Throw ConflictException\n(User already exists)"] E -- No --> G["Redis.get\nADMIN_VERIFICATION_RESEND_CODE:email"] G --> H{"Cooldown active?"} H -- Yes --> I["Throw TooManyRequestsException\n(Please wait before resending)"] H -- No --> J["Generate code = getRandomCode(6)"] J --> K["Redis.set\nADMIN_VERIFICATION_CODE:email\nTTL = 900s"] K --> L["Redis.set\nADMIN_VERIFICATION_RESEND_CODE:email\nTTL = 120s"] L --> M["EmailSenderService\n.sendAdminVerificationEmail(email, code)"] M --> N["Return { message:\nVerification code sent }"]6.2 AdminAuthService.registerVerify()
Заголовок раздела «6.2 AdminAuthService.registerVerify()»Code validation, transactional user + role + session creation, and token pair generation.
flowchart TD A["registerVerify(dto)"] --> B["Redis.get\nADMIN_VERIFICATION_CODE:email"] B --> C{"Code found?"} C -- No --> D["Throw NotFoundException\n(Verification code expired)"] C -- Yes --> E{"Code matches\ndto.code?"} E -- No --> F["Throw BadRequestException\n(Invalid verification code)"] E -- Yes --> G["Redis.del\nADMIN_VERIFICATION_CODE:email"] G --> H["BEGIN @Transactional()"] H --> I["UserService.create\n({email}, no password)"] I --> J["UserOnRole.create\n({userId, roleType: ADMIN})"] J --> K["SessionService.create\n({userId, fingerprint})"] K --> L["COMMIT @Transactional()"] L --> M["TokenAdminService\n.generateAdminTokenPair(payload)"] M --> N["TokenService.saveOne\n({sessionId, tokenId})"] N --> O["Return {accessToken,\nrefreshToken}\n+ Set-Cookie"]6.3 AdminProjectService.updateOneById()
Заголовок раздела «6.3 AdminProjectService.updateOneById()»Project existence check followed by status transition validation against the allowed transitions map.
flowchart TD A["updateOneById(id, dto)"] --> B["AdminProjectRepository.findOne\n({id, deletedAt: null})"] B --> C{"Project found?"} C -- No --> D["Throw NotFoundException\n(Project not found)"] C -- Yes --> E{"dto.status\nprovided?"} E -- No --> G["AdminProjectRepository\n.update(id, dto)"] E -- Yes --> F{"Is dto.status in\nPROJECT_STATUS_TRANSITIONS\n[project.status]?"} F -- No --> H["Throw BadRequestException\n(Invalid status transition\nfrom current to target)"] F -- Yes --> G G --> I["Return AdminProjectResponseDto"]6.4 AdminUserService.blockUser()
Заголовок раздела «6.4 AdminUserService.blockUser()»User existence check and admin role guard preventing admins from blocking other admins.
flowchart TD A["blockUser(id)"] --> B["AdminUserRepository.findOne\n({id}, include: userOnRole.role)"] B --> C{"User found?"} C -- No --> D["Throw NotFoundException\n(User not found)"] C -- Yes --> E{"User has\nADMIN role?"} E -- Yes --> F["Throw ForbiddenException\n(Cannot block admin)"] E -- No --> G["AdminUserRepository.update\n(id, {isBlocked: true})"] G --> H["Return { message:\nUser blocked }"]7. Data Flow Summary Table
Заголовок раздела «7. Data Flow Summary Table»| # | Endpoint | Data Stores Touched | Side Effects |
|---|---|---|---|
| 1 | POST /admin/auth/register | Redis (read cooldown, write code + cooldown) | Email sent |
| 2 | POST /admin/auth/register/verify | Redis (read + delete code), PostgreSQL (insert user, user_on_role, session, token) | Cookie set |
| 3 | POST /admin/auth/login | PostgreSQL (read user + roles), Redis (read cooldown, write code + cooldown) | Email sent |
| 4 | POST /admin/auth/login/verify | Redis (read + delete code), PostgreSQL (read user, find/create session, upsert token) | Cookie set |
| 5 | POST /admin/auth/refresh | PostgreSQL (read session, update token) | Cookie set |
| 6 | GET /admin/projects | PostgreSQL (read projects + customer + user) | None |
| 7 | GET /admin/projects/:id | PostgreSQL (read project + customer + user) | None |
| 8 | PATCH /admin/projects/:id | PostgreSQL (read + update project) | None |
| 9 | DELETE /admin/projects/:id | PostgreSQL (read + soft-update project) | None |
| 10 | GET /admin/users | PostgreSQL (read users + roles) | None |
| 11 | GET /admin/users/:id | PostgreSQL (read user + roles + profile + projects) | None |
| 12 | PATCH /admin/users/:id/block | PostgreSQL (read user + roles, update isBlocked) | None |
| 13 | PATCH /admin/users/:id/unblock | PostgreSQL (read + update user) | None |