- Added services and use cases for managing account details, including changing passwords and updating profiles. - Introduced error handling for duplicate emails and password mismatches. - Created controllers for handling account-related requests in the Express framework. - Updated API routes to include new account management endpoints. - Enhanced the account profile schema to support email updates. - Implemented tests for account management functionalities to ensure reliability and correctness.
302 lines
5.6 KiB
Markdown
302 lines
5.6 KiB
Markdown
# Identity Auth API
|
|
|
|
## Endpoints activos
|
|
|
|
```http
|
|
GET /identity/account
|
|
PATCH /identity/account
|
|
POST /identity/account/change-password
|
|
POST /identity/auth/login
|
|
POST /identity/auth/refresh
|
|
POST /identity/auth/logout
|
|
GET /identity/auth/session
|
|
GET /companies/available
|
|
```
|
|
|
|
## Endpoints que no forman parte del diseño vigente
|
|
|
|
No documentar ni crear como ruta válida:
|
|
|
|
```http
|
|
GET /identity/companies
|
|
GET /account/companies
|
|
```
|
|
|
|
Motivo:
|
|
|
|
- `identity` no debe devolver fichas completas de empresa.
|
|
- `companies` ya depende de `identity` para autenticación.
|
|
- Un endpoint de ese tipo introduciría el ciclo `identity -> companies -> identity`.
|
|
|
|
## POST `/identity/auth/login`
|
|
|
|
### Request
|
|
|
|
```ts
|
|
export type LoginWithPasswordRequestDTO = {
|
|
email: string;
|
|
password: string;
|
|
};
|
|
```
|
|
|
|
### Response
|
|
|
|
```ts
|
|
export type LoginWithPasswordResponseDTO = {
|
|
access_token: string;
|
|
refresh_token: string;
|
|
account: AuthenticatedAccountDTO;
|
|
};
|
|
```
|
|
|
|
```ts
|
|
export type AuthenticatedAccountDTO = {
|
|
id: string;
|
|
email: string;
|
|
name: string;
|
|
avatar_url: string | null;
|
|
language_code: string;
|
|
};
|
|
```
|
|
|
|
### Notas
|
|
|
|
- no requiere `Authorization`
|
|
- no requiere `X-Company-Id`
|
|
- no devuelve companies accesibles
|
|
- no devuelve roles ni permisos
|
|
- el access token no contiene `companyId`
|
|
|
|
## POST `/identity/auth/refresh`
|
|
|
|
### Request
|
|
|
|
```ts
|
|
export type RefreshSessionRequestDTO = {
|
|
refresh_token: string;
|
|
};
|
|
```
|
|
|
|
### Response
|
|
|
|
```ts
|
|
export type RefreshSessionResponseDTO = {
|
|
access_token: string;
|
|
refresh_token: string;
|
|
};
|
|
```
|
|
|
|
### Notas
|
|
|
|
- el refresh token se rota
|
|
- el cliente debe reemplazar ambos tokens por los nuevos
|
|
- no debe llevar `X-Company-Id`
|
|
|
|
## POST `/identity/auth/logout`
|
|
|
|
### Headers
|
|
|
|
```http
|
|
Authorization: Bearer <access_token>
|
|
```
|
|
|
|
### Request
|
|
|
|
```ts
|
|
export type LogoutRequestDTO = {
|
|
refresh_token?: string;
|
|
all_sessions?: boolean;
|
|
};
|
|
```
|
|
|
|
### Response
|
|
|
|
```ts
|
|
export type LogoutResponseDTO = {
|
|
success: true;
|
|
};
|
|
```
|
|
|
|
### Reglas
|
|
|
|
- no debe llevar `X-Company-Id`
|
|
- para logout normal, enviar el `refresh_token` actual
|
|
- si logout falla por expiración de token, el frontend debe limpiar sesión igualmente
|
|
|
|
## GET `/identity/account`
|
|
|
|
### Headers
|
|
|
|
```http
|
|
Authorization: Bearer <access_token>
|
|
```
|
|
|
|
### Response
|
|
|
|
```ts
|
|
export type GetAccountProfileResponseDTO = {
|
|
id: string;
|
|
email: string;
|
|
name: string;
|
|
avatar_url: string | null;
|
|
language_code: string;
|
|
status: "active" | "disabled" | "pending_verification";
|
|
};
|
|
```
|
|
|
|
### Notas
|
|
|
|
- no debe llevar `X-Company-Id`
|
|
- representa la identidad global del usuario autenticado
|
|
- no depende de company activa
|
|
|
|
## PATCH `/identity/account`
|
|
|
|
### Headers
|
|
|
|
```http
|
|
Authorization: Bearer <access_token>
|
|
```
|
|
|
|
### Request
|
|
|
|
```ts
|
|
export type UpdateAccountProfileRequestDTO = {
|
|
email?: string;
|
|
name?: string;
|
|
avatar_url?: string | null;
|
|
language_code?: string;
|
|
};
|
|
```
|
|
|
|
### Response
|
|
|
|
```ts
|
|
export type UpdateAccountProfileResponseDTO = {
|
|
id: string;
|
|
email: string;
|
|
name: string;
|
|
avatar_url: string | null;
|
|
language_code: string;
|
|
status: "active" | "disabled" | "pending_verification";
|
|
};
|
|
```
|
|
|
|
### Reglas
|
|
|
|
- no debe llevar `X-Company-Id`
|
|
- PATCH real: campo omitido no modifica
|
|
- `avatar_url: null` limpia el avatar
|
|
- el cambio de email en V1 es inmediato y no requiere verificación adicional
|
|
- el backend valida unicidad de email
|
|
- `avatar_url` sigue siendo solo una referencia externa; no existe upload en `identity`
|
|
|
|
## POST `/identity/account/change-password`
|
|
|
|
### Headers
|
|
|
|
```http
|
|
Authorization: Bearer <access_token>
|
|
```
|
|
|
|
### Request
|
|
|
|
```ts
|
|
export type ChangeAccountPasswordRequestDTO = {
|
|
current_password: string;
|
|
new_password: string;
|
|
};
|
|
```
|
|
|
|
### Response
|
|
|
|
```ts
|
|
export type ChangeAccountPasswordResponseDTO = {
|
|
success: true;
|
|
};
|
|
```
|
|
|
|
### Reglas
|
|
|
|
- no debe llevar `X-Company-Id`
|
|
- exige `current_password`
|
|
- usa el hasher actual de `identity`
|
|
- revoca todos los refresh tokens persistidos de la cuenta
|
|
- no invalida de forma inmediata access tokens ya emitidos, porque hoy son stateless y no existe un subsistema de revocación inmediata de access tokens
|
|
|
|
## GET `/identity/auth/session`
|
|
|
|
### Headers
|
|
|
|
```http
|
|
Authorization: Bearer <access_token>
|
|
```
|
|
|
|
### Response
|
|
|
|
```ts
|
|
export type CurrentSessionResponseDTO = {
|
|
account: AuthenticatedAccountDTO;
|
|
};
|
|
```
|
|
|
|
### Notas
|
|
|
|
- no debe llevar `X-Company-Id`
|
|
|
|
## GET `/companies/available`
|
|
|
|
### Headers
|
|
|
|
```http
|
|
Authorization: Bearer <access_token>
|
|
```
|
|
|
|
### Response
|
|
|
|
```ts
|
|
export type AvailableCompaniesResponseDTO = {
|
|
companies: AvailableCompanyDTO[];
|
|
};
|
|
|
|
export type AvailableCompanyDTO = {
|
|
id: string;
|
|
legal_name: string;
|
|
trade_name: string | null;
|
|
tin: string | null;
|
|
slug: string;
|
|
email: string | null;
|
|
phone: string | null;
|
|
website: string | null;
|
|
status: "active";
|
|
};
|
|
```
|
|
|
|
### Notas
|
|
|
|
- usa autenticación, no tenant context
|
|
- no requiere `X-Company-Id`
|
|
- usa `requireIdentityAuthenticated(params)`
|
|
- devuelve solo companies activas accesibles para la cuenta autenticada
|
|
- no modifica sesión ni access token
|
|
|
|
## Errores esperados
|
|
|
|
```txt
|
|
400 -> request inválida o UUID de X-Company-Id mal formado
|
|
401 -> access token ausente/inválido/expirado o credenciales inválidas
|
|
401 -> cuenta no autenticable (`disabled` o `pending_verification`)
|
|
403 -> contexto tenant inválido, company no accesible o company no activa
|
|
409 -> conflicto de unicidad, por ejemplo email ya existente
|
|
500 -> error inesperado
|
|
```
|
|
|
|
## Administración global de cuentas
|
|
|
|
El dominio ya soporta enable/disable global de `Account`, pero no se documentan todavía endpoints HTTP administrativos operativos porque el runtime nuevo no dispone aún de un mecanismo inequívoco y cableado de autorización de administrador global.
|
|
|
|
Pendiente explícito:
|
|
|
|
- definir y cablear la autorización global real
|
|
- entonces exponer enable/disable por HTTP
|