publicUserIdentity
Overview
services/api/src/utils/publicUserIdentity.js centraliza la lógica de identidad pública para usuarios anonimizados. Su objetivo es devolver una versión segura de un User cuando la cuenta está en un estado que ya no debe mostrarse con identidad real.
Este módulo existe para evitar duplicar la misma regla en varios lugares del backend. El comentario del archivo indica que se reutiliza en cualquier endpoint que serialice un User poblado dentro de otro documento, como comentarios de listings o eventos de actividad.
[!IMPORTANT]
accountStatusse usa solo para decidir si se enmascara la identidad. El campo no se expone en la salida.
How it works
El módulo trabaja con dos decisiones simples:
- Detecta si el estado de la cuenta pertenece a la lista de estados anonimizados.
- Si corresponde, devuelve una identidad pública enmascarada.
- Si no corresponde, devuelve los campos públicos del usuario, sin
accountStatus.
La función principal también acepta forceMask. Ese parámetro permite enmascarar aunque el User no exista en el populate, o aunque el estado final todavía no esté reflejado en el documento fuente.
flowchart TD
A[User document] --> B{forceMask}
B -->|true| C[Masked identity]
B -->|false| D{Has userDoc}
D -->|no| E[null]
D -->|yes| F[Read accountStatus]
F --> G{Anonymized status}
G -->|yes| C
G -->|no| H[Public fields without accountStatus]
Key components
{
"title": "ANONYMIZED_ACCOUNT_STATUSES",
"content": "Set con los estados de cuenta que activan el enmascarado de identidad. Incluye \"anonymized_pending_purge\" y \"purged\".",
"type": "function",
"filePath": "services/api/src/utils/publicUserIdentity.js",
"badges": [
"public"
]
}
{
"title": "MASKED_IDENTITY",
"content": "Objeto inmutable con la identidad p\u00fablica est\u00e1ndar para usuarios anonimizados. Define los valores que se devuelven cuando la cuenta debe ocultarse.",
"type": "function",
"filePath": "services/api/src/utils/publicUserIdentity.js",
"badges": [
"public"
]
}
{
"title": "isAnonymizedAccountStatus",
"content": "Funci\u00f3n p\u00fablica que comprueba si un estado de cuenta pertenece al conjunto de estados anonimizados. Devuelve un booleano.",
"type": "function",
"filePath": "services/api/src/utils/publicUserIdentity.js",
"badges": [
"public"
]
}
{
"title": "maskAnonymizedUserIdentity",
"content": "Funci\u00f3n p\u00fablica que devuelve una versi\u00f3n segura del usuario. Enmascara la identidad cuando `forceMask` es verdadero o cuando `accountStatus` indica un usuario anonimizado.",
"type": "function",
"filePath": "services/api/src/utils/publicUserIdentity.js",
"badges": [
"public"
]
}
Data & fields
[
{
"name": "ANONYMIZED_ACCOUNT_STATUSES",
"type": "Set<string>",
"required": true,
"description": "Conjunto de estados de cuenta que activan el enmascarado.",
"children": [
{
"name": "anonymized_pending_purge",
"type": "string",
"required": true,
"description": "Estado intermedio de una cuenta que ya debe mostrarse como anonimizada."
},
{
"name": "purged",
"type": "string",
"required": true,
"description": "Estado final de una cuenta eliminada o purgada."
}
]
},
{
"name": "MASKED_IDENTITY",
"type": "object",
"required": true,
"description": "Plantilla de identidad pública usada cuando la cuenta debe ocultarse.",
"children": [
{
"name": "_id",
"type": "null",
"required": true,
"description": "Identificador vacío para evitar exponer el ID real."
},
{
"name": "name",
"type": "string",
"required": true,
"description": "Nombre visible para usuarios anonimizados."
},
{
"name": "username",
"type": "null",
"required": true,
"description": "Nombre de usuario oculto."
},
{
"name": "photo",
"type": "string",
"required": true,
"description": "Foto vacía en la identidad enmascarada."
},
{
"name": "isAnonymized",
"type": "boolean",
"required": true,
"description": "Marca explícita de que la identidad fue anonimizada."
}
]
}
]
MASKED_IDENTITY shape
El objeto enmascarado tiene una forma fija y predecible. El módulo lo crea con Object.freeze, así que no puede modificarse accidentalmente en tiempo de ejecución.
{
"_id": null,
"name": "Usuario anonimizado",
"username": null,
"photo": "",
"isAnonymized": true
}
Behaviors
isAnonymizedAccountStatus(accountStatus)— devuelvetruecuandoaccountStatuspertenece aANONYMIZED_ACCOUNT_STATUSES.maskAnonymizedUserIdentity(userDoc, { forceMask = false } = {})— devuelveMASKED_IDENTITY,nullo los campos públicos del usuario, según el estado recibido.
isAnonymizedAccountStatus
Esta función consulta el Set definido en el módulo. Su salida es determinista y solo depende del valor recibido.
maskAnonymizedUserIdentity
Esta función implementa la serialización pública del usuario. Su flujo es el siguiente:
- Si
forceMaskestrue, devuelve una copia deMASKED_IDENTITY. - Si
userDocno existe, devuelvenull. - Si
accountStatuses un estado anonimizado, devuelve una copia deMASKED_IDENTITY. - En cualquier otro caso, devuelve los campos públicos del usuario sin
accountStatus.
[!NOTE] La función espera un
userDocresultado de unpopulate()en modo lean. El comentario del archivo indica que ese documento debe incluiraccountStatusen la selección.
Workflows
- Recibir usuario poblado | El código recibe un
userDocya serializable desde unpopulate(). - Evaluar forzado | Si
forceMaskestá activo, la función enmascara de inmediato. - Revisar estado | Si existe
userDoc, se evalúaaccountStatus. - Decidir salida | La función devuelve la identidad enmascarada,
nullo los campos públicos.
Gotchas & edge cases
[!WARNING] Si el
populate()no incluyeaccountStatus, la decisión de anonimización no puede detectarse desde este módulo. El comentario del archivo indica que ese campo debe venir seleccionado.
[!CAUTION] Cuando
forceMaskestrue, la función devuelve identidad enmascarada incluso si el usuario no llegó en el documento o si el estado todavía no está sincronizado con el estado final.
[!NOTE] La salida pública nunca conserva
accountStatus. Si el usuario no está anoninimizado, el módulo devuelve el resto de campos públicos tal como vienen enuserDoc.
Related
Este utilitario está pensado para cualquier ruta o serializador del backend que inserte un User dentro de otro documento. El propio archivo cita comentarios de listings y eventos de actividad como ejemplos de uso.
Su papel es coherente con una capa de serialización determinista: la decisión de ocultar identidad se toma aquí, no en cada módulo consumidor.