Passa al contenuto principale

Change user status (Admin only)

POST 

/company/users/status/:id

Cambia lo stato di un utente (attivare/disattivare) tramite il campo status. Solo gli amministratori possono cambiare lo stato degli utenti.

Obiettivo

Consentire agli amministratori di controllare l'accesso degli utenti alla piattaforma mediante attivazione/disattivazione degli account.

Casi d'Uso

  • Disattivare temporaneamente un utente
  • Attivare un utente che era disattivato
  • Sospendere l'accesso per motivi di sicurezza
  • Bloccare un utente per mancato pagamento o inadempienza

Autenticazione & Autorizzazione

  • Richiede JWT valido (middleware m.isLoged)
  • Richiede ruolo admin o dev (middleware m.isAdmin)

Comportamento

  • reason = NONE: Attiva utente (status = true), pulisce reason, reasonDate, reasonMessage
  • reason ≠ NONE: Disattiva utente (status = false), imposta reason e reasonMessage
  • Valida la ragione con model.isValidReason()
  • Aggiorna reasonDate se valida (formato ISO8601)

Ragioni Valide

  • NONE: Utente normale attivo senza problemi (attiva utente)
  • BAD_USER: Bloccato per comportamento scorretto (segnalazioni, frode)
  • PENDING: Registrazione completata, in attesa di attivazione
  • ACTIVE: Utente verificato e operativo
  • BLOCKED: Bloccato amministrativamente (mancato pagamento, sicurezza)

Flusso di Validazione

flowchart TD
A[Ricevi POST /status/:id] --> B\{Utente Admin?\}
B -->|No| C[403 Forbidden]
B -->|Sì| D\{Utente Esiste?\}
D -->|No| E[404 Not Found]
D -->|Sì| F\{Reason === 'NONE'?\}
F -->|Sì| G[Attiva Utente]
G --> H[status = true]
H --> I[reason = NONE]
I --> J[Pulisci

<Heading
id={"request"}
as={"h2"}
className={"openapi-tabs__heading"}
children={"Request"}
>
</Heading>

<ParamsDetails
parameters={[{"name":"id","in":"path","required":true,"description":"ID dell'utente a cui verrà modificato lo stato","schema":{"type":"string","pattern":"^[a-f0-9]{24}$","example":"63d7907cbe76403b35da63df"}}]}
>

</ParamsDetails>

<RequestSchema
title={"Body"}
body={{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string","enum":["NONE","BAD_USER","PENDING","ACTIVE","BLOCKED"],"description":"Motivo del cambio di stato. Se è NONE, l'utente viene attivato.\nQualsiasi altro valore disattiva l'utente.","example":"NONE"},"reasonDate":{"type":"string","format":"date-time","description":"Data/ora del cambio di stato (opzionale). Se non fornita,\nviene utilizzata la data corrente. Formato ISO8601.","example":"2025-02-12T14:30:00.000Z","nullable":true},"reasonMessage":{"type":"string","maxLength":500,"description":"Messaggio esplicativo del cambio di stato (opzionale).\nVisibile per l'utente e gli amministratori.","example":"Usuario bloqueado temporalmente por verificación de documentación","nullable":true}}},"example":{"reason":"NONE","reasonDate":"2025-02-12T14:30:00.000Z","reasonMessage":"Usuario reactivado tras completar verificación"}}}}}
>

</RequestSchema>

<StatusCodes
id={undefined}
label={undefined}
responses={{"200":{"description":"Stato utente modificato con successo.","content":{"application/json":{"schema":{"type":"object","description":"Rappresenta un utente aziendale (company_user) con accesso alla piattaforma Cargoffer.\n**Funzionalità**: - Utente dipendente di un'azienda di trasporto che gestisce aste, consegne e documentazione - Autenticazione tramite JWT (token con scadenza configurabile in base a refresh_time) - Sistema di ruoli gerarchico: dev > admin > gestore (permessi discendenti) - Associato a un'azienda (l'array company.users contiene riferimenti a _id degli utenti)\n**Modello**: `src/features/models/company_user.model.js`\n**Controller**: - `src/features/company/users/company_user.account.controller.js` (CRUD, password) - `src/features/company/users/company_user.profile.controller.js` (profilo, preferenze) - `src/features/company/auth/auth.account.controller.js` (login, token)\n**Middleware**: `src/features/common/middleware/company.middleware.js` - `m.isLoged` - Verifica JWT valido - `m.isGestor` - Richiede ruolo 'gestore' o superiore - `m.isAdmin` - Richiede ruolo 'admin' o 'dev'","properties":{"_id":{"type":"string","description":"Identificatore unico MongoDB dell'utente (24 caratteri esadecimali). Generato automaticamente alla registrazione. Referenziato in: company.users[], auction.user, delivery.user, notifications.user. Incluso nel payload JWT come claim '_id'.","pattern":"^[a-f0-9]{24}$","example":"63d7907cbe76403b35da63df"},"email":{"type":"string","format":"email","description":"Email univoco dell'utente (utilizzato per l'accesso). **Obbligatorio** - Univoco nel database (indice unique in produzione). Normalizzato automaticamente in minuscolo (hook pre-save). Utilizzato per: autenticazione, recupero password, notifiche. Convalidato con formato email standard.","example":"usuario@cargoffer.com"},"name":{"type":"string","description":"Nome dell'utente (firstName in contesto internazionale). Utilizzato in: interfaccia, firma documenti CMR, identificazione nelle notifiche. Minimo 2 caratteri (validazione frontend).","minLength":2,"maxLength":50,"example":"Juan"},"lastname":{"type":"string","description":"Cognome dell'utente (lastName in API, lastname nel modello). Utilizzato insieme a 'nome' per l'identificazione completa nei documenti ufficiali. Concatenato in: contratti, CMR, fatture.","minLength":2,"maxLength":100,"example":"García López"},"role":{"type":"string","enum":["dev","admin","gestor"],"description":"Ruolo dell'utente che definisce i permessi nella piattaforma. \n**dev**: Accesso totale + debug + gestione di tutte le aziende (superadmin) \n**admin**: Gestione completa della propria azienda (creare utenti, visualizzare fatturazione, modificare dati) \n**gestor**: Operazioni giornaliere (creare aste/consegne, visualizzare dashboard, modificare il proprio profilo) \n\n**Middleware checks**: \n- m.isGestor accetta: ['gestor', 'admin', 'dev'] \n- m.isAdmin accetta: ['admin', 'dev'] \n\nMemorizzato nel payload JWT (utilizzato nella validazione dei permessi).","default":"gestor","example":"admin"},"status":{"type":"boolean","description":"Stato attivo/inattivo dell'utente. **true**: L'utente può effettuare il login e operare normalmente. **false**: Utente bloccato (non può effettuare il login, JWT non validi). \nUtilizzato in: il middleware m.isLoged verifica status=true prima di consentire l'accesso. Modificato tramite: POST /company/users/status/:id (solo admin). Diverso da 'deleted' (soft delete) – questo è un blocco reversibile.","default":true,"example":true},"reason":{"type":"string","enum":["NONE","BAD_USER","PENDING","ACTIVE","BLOCKED"],"description":"Codice motivo dello stato dell'utente. **NONE**: Utente normale attivo senza problemi **PENDING**: Registrazione completata, in attesa di attivazione via email **ACTIVE**: Utente verificato e operativo **BAD_USER**: Bloccato per comportamento scorretto (segnalazioni, frode) **BLOCKED**: Bloccato amministrativamente (mancato pagamento, sicurezza)\nUtilizzato insieme a 'status' e 'reasonMessage' per audit. Memorizzato con 'reasonDate' (timestamp della modifica).","default":"NONE","example":"ACTIVE"},"reasonMessage":{"type":"string","description":"Messaggio descrittivo della ragione del blocco/stato attuale. Opzionale - Compilato dall'amministratore quando cambia lo stato in false. Visibile a: amministratori nel pannello utenti, utente bloccato nel messaggio di errore di accesso. Esempio: Account sospeso per mancato pagamento, Utente segnalato per pratiche scorrette.","example":"Usuario bloqueado temporalmente por verificación de documentación"},"reasonDate":{"type":"string","format":"date-time","description":"Timestamp dell'ultima modifica del campo 'reason'. Automatico - Impostato nell'hook pre-save al rilevare una modifica in 'reason'. Utilizzato in: audit, calcolo durata blocco, cronologia modifiche.","example":"2025-01-15T14:30:00.000Z"},"i18n":{"type":"string","enum":["es","en","fr","de"],"description":"Codice lingua preferita dell'utente (internazionalizzazione). **es**: Spagnolo (predefinito per la Spagna) **en**: Inglese (predefinito internazionale)\nUtilizzato in: email automatiche, interfaccia utente, messaggi di errore, documenti CMR. Memorizzato nel payload JWT per la personalizzazione dal backend. Modificato tramite: POST /company/users/lang","default":"es","example":"en"},"birthDate":{"type":"string","format":"date-time","description":"Data di nascita dell'utente (opzionale). Utilizzato per: validazioni dell'età minima (18 anni per i conducenti), statistiche demografiche. Formato ISO 8601. Nullable.","nullable":true,"example":"1990-05-15T00:00:00.000Z"},"emailVerified":{"type":"boolean","description":"Indica se l'utente ha verificato la propria email. **false**: Utente registrato ma non ha cliccato sul link di attivazione **true**: Email confermata tramite token di attivazione\nFlusso: register → email con token → GET /company/auth/activate/:token → emailVerified=true\nUtenti con emailVerified=false possono avere funzionalità limitate (dipende dalla configurazione).","default":false,"example":true},"emailVerifiedDate":{"type":"string","format":"date-time","description":"Timestamp di quando l'email è stata verificata (null se emailVerified=false). Impostato automaticamente alla conferma del token di attivazione. Utilizzato in: audit, calcolo del tempo trascorso dalla verifica, requisiti di ri-verifica.","nullable":true,"example":"2025-01-10T09:20:30.000Z"},"phone":{"type":"string","description":"Numero di telefono dell'utente (opzionale ma consigliato). Formato: preferibilmente internazionale (+prefisso paese), minimo 9 cifre, massimo 15. Utilizzato per: coordinamento logistico, avvisi SMS, contatto di emergenza. Validazione: `minlength: 9, maxlength: 15` nel modello.","pattern":"^\\+?[0-9]{9,15}$","example":"+34612345678"},"lastSignInAt":{"type":"string","format":"date-time","description":"Timestamp dell'ultimo accesso riuscito dell'utente. Aggiornato automaticamente nel login controller (POST /company/auth/login). Utilizzato in: dashboard attività, rilevamento account inattivi, audit di sicurezza.","example":"2025-10-23T08:15:45.000Z"},"lastSignInIp":{"type":"string","description":"Indirizzo IP da cui è stato effettuato l'ultimo accesso. Estratto da req.ip o req.headers['x-forwarded-for']. Utilizzato per: rilevamento di accessi sospetti, log di sicurezza, geolocalizzazione degli accessi.","format":"ipv4","example":"192.168.1.100"},"country":{"type":"string","description":"Codice paese ISO 3166-1 alpha-3 dell'utente (3 lettere minuscole). Utilizzato in: filtri del fuso orario, formati di data, impostazioni locali, validazioni del TaxID. Predefinito: esp (Spagna). Deve esistere nella collection 'countries'.","pattern":"^[a-z]{3}$","default":"esp","example":"esp"},"timezone":{"type":"string","description":"Fuso orario dell'utente in formato IANA Time Zone Database. Utilizzato per: conversione di timestamp UTC in locale, visualizzazione di date, calcolo degli orari di caricamento/scaricamento. Deve corrispondere a zone valide della libreria moment-timezone. Predefinito: Europe/Madrid","default":"Europe/Madrid","example":"Europe/Madrid"},"taxid":{"type":"string","description":"Numero di identificazione fiscale personale (NIF, DNI, NIE, ecc.). **Unico in produzione** (indice unique). Minimo 6 caratteri, massimo 9. Normalizzato automaticamente in maiuscolo (uppercase: true nel modello). Utilizzato in: fatturazione, contratti, documentazione legale. Default temporaneo: '---------' (9 trattini) per consentire la creazione senza dato.","minLength":6,"maxLength":9,"example":"12345678A"},"img":{"type":"string","format":"uri","description":"URL dell'immagine del profilo dell'utente (archiviata in AWS S3). Opzionale - Caricata tramite endpoint documenti con multerS3. Utilizzata in: avatar nell'interfaccia, firma visiva sui documenti. Formato: URL completo del bucket S3.","nullable":true,"example":"https://cargoffer-storage.s3.amazonaws.com/users/63d7907cbe76403b35da63df.jpg"},"recovery_token":{"type":"string","description":"Token temporaneo per recupero password (hash). Generato in: POST /company/auth/recovery (richiesta di reset) Utilizzato in: GET /company/auth/recovery/:token (validare il token) Cancellato dopo: cambio password riuscito o scadenza (48h) Default: '' (stringa vuota quando non c'è un processo di recovery attivo)","example":"a7f5e8d3c2b9..."},"refresh_time":{"type":"integer","enum":[1,3,5,10],"description":"Tempo di scadenza del JWT in giorni. Utilizzato in: generazione del token (claim exp = iat + refresh_time * 24h). **1**: Massima sicurezza (re-login giornaliero) - Per ruoli sensibili **3**: Default bilanciamento sicurezza/comodità **5**: Uso frequente **10**: Applicazioni mobili con funzionalità offline.\nMemorizzato nel payload JWT, validato nel middleware m.isLoged.","default":3,"example":3},"is_bot":{"type":"boolean","description":"Indica se l'utente è un bot automatizzato (per integrazioni API). **true**: Utente creato per integrazione automatica (webhook, script) **false**: Utente umano reale\nUtilizzato in: statistiche, audit, escludere i bot dalle metriche di attività umana. I bot possono avere permessi speciali e limiti di frequenza diversi.","default":false,"example":false},"deleted":{"type":"boolean","description":"Flag per soft delete (plugin mongoose-delete). **false**: Utente attivo **true**: Utente eliminato (non appare nelle query normali). \nLe query includono automaticamente deleted:false (plugin con overrideMethods:true). Recuperabile tramite: POST /company/users/disabled/reactivate/:id. Correlato al timestamp 'deletedAt'.","default":false,"example":false},"deletedAt":{"type":"string","format":"date-time","description":"Timestamp di quando l'utente è stato eliminato (soft delete). Null se deleted=false. Impostato automaticamente dal plugin mongoose-delete. Utilizzato in: audit delle eliminazioni, recupero utenti, conformità GDPR.","nullable":true,"example":"2025-10-01T12:00:00.000Z"},"createdAt":{"type":"string","format":"date-time","description":"Timestamp di creazione dell'utente (automatico tramite mongoose timestamps). Immutabile - Non può essere modificato dopo la creazione. Utilizzato per: ordinamento, statistiche di crescita, audit.","example":"2024-12-01T10:30:00.000Z"},"updatedAt":{"type":"string","format":"date-time","description":"Timestamp dell'ultima modifica dell'utente (automatico da mongoose timestamps). Aggiornato ad ogni save() - Riflette l'ultima modifica di qualsiasi campo. Utilizzato per: sincronizzazione, invalidazione della cache, rilevamento delle modifiche.","example":"2025-10-20T15:45:30.000Z"},"lastAccess":{"type":"string","format":"date-time","description":"Timestamp dell'ultimo accesso registrato a qualsiasi endpoint autenticato. Aggiornato da: middleware m.getAction ad ogni richiesta autenticata. Diverso da lastSignInAt (quest'ultimo si aggiorna ad ogni richiesta, non solo al login). Utilizzato in: rilevamento inattività, metriche di engagement.","example":"2025-10-23T10:22:15.000Z"}},"title":"User"},"example":{"_id":"63d7907cbe76403b35da63df","email":"usuario@empresa.com","name":"Juan","lastname":"Pérez García","status":true,"reason":"NONE","reasonDate":null,"reasonMessage":null,"updatedAt":"2025-02-12T14:30:00.000Z"}}}},"400":{"description":"Richiesta non valida. Possibili cause:\n- Motivo non valido\n- Errore durante il salvataggio\n","content":{"application/json":{"schema":{"type":"object","required":["status","message"],"properties":{"status":{"type":"integer","description":"Codice di stato HTTP","minimum":400,"maximum":599,"example":400},"message":{"type":"string","description":"Codice di errore del sistema.\n\nCodici di errore comuni (vedi listado_errores_http.txt per la lista completa):\n- NO_TOKEN (401): Token JWT non fornito\n- TOKEN_NOT_VALID (401): Token JWT non valido o scaduto\n- NO_ADMIN_ROLE (401): L'utente non dispone dei privilegi di amministratore\n- INVALID_PARAMETERS (400): Parametri della richiesta non validi\n- NOT_FOUND (404): Risorsa richiesta non trovata\n- ALREADY_EXIST (401): Risorsa con lo stesso identificatore già esistente\n- UTC_VALIDATION_FAILED (400): Validazione del timestamp UTC fallita\n- INTERNAL_ERROR (500): Si è verificato un errore imprevisto del server\n\nIl messaggio è risolto da `handlerError.getErrorMessage(error)`.","example":"INVALID_PARAMETERS"}},"description":"Formato standard di risposta per errori utilizzato in tutti gli endpoint API.\n\nTutti gli errori seguono lo schema `{status: number, message: string}`.\nIl codice di stato è ripetuto sia nella risposta HTTP che nel corpo.\n\nI messaggi di errore sono costanti definite nel codice e devono essere\ngestiti lato client con messaggi appropriati rivolti all'utente.","example":{"status":400,"message":"INVALID_PARAMETERS"},"title":"ErrorResponse"},"example":{"message":"FORM_DATA_NOT_VALID"}}}},"401":{"description":"Non autorizzato (è richiesto il ruolo di admin o dev)","content":{"application/json":{"schema":{"type":"object","required":["status","message"],"properties":{"status":{"type":"integer","description":"Codice di stato HTTP","minimum":400,"maximum":599,"example":400},"message":{"type":"string","description":"Codice di errore del sistema.\n\nCodici di errore comuni (vedi listado_errores_http.txt per la lista completa):\n- NO_TOKEN (401): Token JWT non fornito\n- TOKEN_NOT_VALID (401): Token JWT non valido o scaduto\n- NO_ADMIN_ROLE (401): L'utente non dispone dei privilegi di amministratore\n- INVALID_PARAMETERS (400): Parametri della richiesta non validi\n- NOT_FOUND (404): Risorsa richiesta non trovata\n- ALREADY_EXIST (401): Risorsa con lo stesso identificatore già esistente\n- UTC_VALIDATION_FAILED (400): Validazione del timestamp UTC fallita\n- INTERNAL_ERROR (500): Si è verificato un errore imprevisto del server\n\nIl messaggio è risolto da `handlerError.getErrorMessage(error)`.","example":"INVALID_PARAMETERS"}},"description":"Formato standard di risposta per errori utilizzato in tutti gli endpoint API.\n\nTutti gli errori seguono lo schema `{status: number, message: string}`.\nIl codice di stato è ripetuto sia nella risposta HTTP che nel corpo.\n\nI messaggi di errore sono costanti definite nel codice e devono essere\ngestiti lato client con messaggi appropriati rivolti all'utente.","example":{"status":400,"message":"INVALID_PARAMETERS"},"title":"ErrorResponse"},"example":{"message":"NO_TOKEN"}}}},"403":{"description":"Vietato (l'utente non è amministratore)","content":{"application/json":{"schema":{"type":"object","required":["status","message"],"properties":{"status":{"type":"integer","description":"Codice di stato HTTP","minimum":400,"maximum":599,"example":400},"message":{"type":"string","description":"Codice di errore del sistema.\n\nCodici di errore comuni (vedi listado_errores_http.txt per la lista completa):\n- NO_TOKEN (401): Token JWT non fornito\n- TOKEN_NOT_VALID (401): Token JWT non valido o scaduto\n- NO_ADMIN_ROLE (401): L'utente non dispone dei privilegi di amministratore\n- INVALID_PARAMETERS (400): Parametri della richiesta non validi\n- NOT_FOUND (404): Risorsa richiesta non trovata\n- ALREADY_EXIST (401): Risorsa con lo stesso identificatore già esistente\n- UTC_VALIDATION_FAILED (400): Validazione del timestamp UTC fallita\n- INTERNAL_ERROR (500): Si è verificato un errore imprevisto del server\n\nIl messaggio è risolto da `handlerError.getErrorMessage(error)`.","example":"INVALID_PARAMETERS"}},"description":"Formato standard di risposta per errori utilizzato in tutti gli endpoint API.\n\nTutti gli errori seguono lo schema `{status: number, message: string}`.\nIl codice di stato è ripetuto sia nella risposta HTTP che nel corpo.\n\nI messaggi di errore sono costanti definite nel codice e devono essere\ngestiti lato client con messaggi appropriati rivolti all'utente.","example":{"status":400,"message":"INVALID_PARAMETERS"},"title":"ErrorResponse"},"example":{"message":"USER_NOT_ALLOWED"}}}},"404":{"description":"Utente non trovato","content":{"application/json":{"schema":{"type":"object","required":["status","message"],"properties":{"status":{"type":"integer","description":"Codice di stato HTTP","minimum":400,"maximum":599,"example":400},"message":{"type":"string","description":"Codice di errore del sistema.\n\nCodici di errore comuni (vedi listado_errores_http.txt per la lista completa):\n- NO_TOKEN (401): Token JWT non fornito\n- TOKEN_NOT_VALID (401): Token JWT non valido o scaduto\n- NO_ADMIN_ROLE (401): L'utente non dispone dei privilegi di amministratore\n- INVALID_PARAMETERS (400): Parametri della richiesta non validi\n- NOT_FOUND (404): Risorsa richiesta non trovata\n- ALREADY_EXIST (401): Risorsa con lo stesso identificatore già esistente\n- UTC_VALIDATION_FAILED (400): Validazione del timestamp UTC fallita\n- INTERNAL_ERROR (500): Si è verificato un errore imprevisto del server\n\nIl messaggio è risolto da `handlerError.getErrorMessage(error)`.","example":"INVALID_PARAMETERS"}},"description":"Formato standard di risposta per errori utilizzato in tutti gli endpoint API.\n\nTutti gli errori seguono lo schema `{status: number, message: string}`.\nIl codice di stato è ripetuto sia nella risposta HTTP che nel corpo.\n\nI messaggi di errore sono costanti definite nel codice e devono essere\ngestiti lato client con messaggi appropriati rivolti all'utente.","example":{"status":400,"message":"INVALID_PARAMETERS"},"title":"ErrorResponse"},"example":{"message":"USER_NOT_FOUND"}}}}}}
>

</StatusCodes>