Moderadores de cuenta
Los propietarios de cuentas pueden delegar permisos delimitados a usuarios de confianza ("moderadores") para que esos moderadores puedan publicar, crear clips, transmitir en vivo, crear chats y enviar mensajes en nombre de la cuenta del propietario.
Otorgar o cambiar estos permisos requiere que el propietario tenga habilitada la autenticación de dos factores — una cuenta secuestrada no se puede usar para otorgar silenciosamente acceso completo a un atacante. Revocar a un moderador siempre está permitido (no se necesita 2FA), de modo que un propietario que perdió su autenticador aún pueda cortar el acceso.
- Agregar un moderador (buscar un usuario, otorgar permisos)
- Interruptores por permiso: Publicar, Clips, Transmitir en vivo, Publicar historias, Crear chats, Enviar mensajes, Comentar, Reaccionar, Administrar comentarios
- Bloqueo por 2FA al agregar/actualizar (se bloquea con un llamado a la acción para habilitar el 2FA cuando está desactivado)
- Reautenticación reforzada: agregar/actualizar moderadores también le pide al propietario que vuelva a ingresar su contraseña si no se ha autenticado recientemente
- Eliminar un moderador (no se requiere 2FA)
- Lista "Accounts I moderate" para el moderador
- Aplicación en el servidor de cada permiso al actuar en nombre de un propietario
- Selector "Publicar como" en el compositor de publicaciones para moderadores
- Selector "Comentar como" en el cuadro de comentarios para moderadores
- Interfaz "Actuar como" en los compositores de transmisiones en vivo, chats nuevos y mensajes (
GoLiveModal,ConversationListyChatViewahora ofrecen el mismo selector que ya tenían el compositor de publicaciones y el cuadro de comentarios; esta página antes decía que solo estaban conectados publicaciones/clips y comentarios — corregido)
Modelo de permisos
| Permiso | Acción controlada | Aplicado en |
|---|---|---|
canPost | Crear una publicación normal | createPost |
canClip | Crear un clip (video único) | createPost (detectado como clip) |
canLive | Iniciar una transmisión en vivo | createLiveStream |
canStory | Publicar una historia | createStory |
canCreateChats | Crear una conversación | createConversation |
canSendMessages | Enviar un mensaje | sendMessage |
canComment | Comentar/responder en publicaciones | createComment |
canReact | Reaccionar/dar me gusta a una publicación | likePost |
canManageComments | Moderar (eliminar) comentarios en las publicaciones del propietario | deleteComment |
Lo que intencionalmente nunca se delega (exclusivo del propietario, pase lo que pase): contraseña, correo electrónico, teléfono, 2FA, agregar/editar otros moderadores, retiros/gasto de monedas, configuración de privacidad, bloqueo de usuarios y eliminación/desactivación de la cuenta. La delegación cubre el contenido y la interacción, no el control de la cuenta ni el dinero.
Cómo funciona "actuar como"
Cada una de las mutaciones de creación/envío — más likePost y deleteComment — acepta un actAsUserId opcional. El resolver llama a accountModeratorManager.resolveActingUser(callerId, actAsUserId, action):
- Si
actAsUserIdno está definido o es igual al llamador → el llamador actúa como sí mismo. - Si está definido y el llamador es un moderador autorizado de ese propietario → el propietario se convierte en el autor efectivo (publicación
userId, transmisión en vivouserId, conversacióncreator_id, mensajesenderId). - De lo contrario → la mutación lanza
moderators.not_permitted.
Para los mensajes, la verificación de acceso ("es un participante") se ejecuta contra el remitente efectivo (el propietario), por lo que el propietario debe estar en la conversación.
Modelo de datos
Tabla account_moderator:
| Columna | Significado |
|---|---|
owner_id | La cuenta que está siendo moderada |
moderator_user_id | El usuario delegado |
can_post, can_clip, can_live, can_story, can_create_chats, can_send_messages, can_comment, can_react, can_manage_comments | Indicadores de permisos |
Único en (owner_id, moderator_user_id).
Registro de auditoría (quién hizo qué)
Cada acción que un moderador realiza en nombre del propietario se registra en la tabla account_moderator_action (owner_id, moderator_user_id, action, acted_as, target_type, target_id, metadata, created_at). El propietario lee su propio feed a través de la query moderatorActivity(limit, offset, action, moderatorUserId) (tipo ModeratorAction), que se muestra de más reciente a más antiguo en Settings → Moderadores como "Actividad de moderadores". Las acciones realizadas bajo la identidad propia del moderador no se registran como acciones del propietario. El registro es de mejor esfuerzo: un fallo en el registro nunca bloquea la acción subyacente.
Atribución de mensajes (quién lo envió realmente)
Cuando un moderador envía un mensaje como el propietario, el remitente real se registra en metadata.viaModeratorId del mensaje. El campo Message.viaModerator: User resuelve eso de vuelta al moderador, pero solo para el propietario (el remitente efectivo) — los demás participantes simplemente ven el mensaje como proveniente del propietario. Esto le permite al propietario rastrear siempre qué moderador envió un mensaje determinado bajo su nombre.
Comentar como uno mismo o como el propietario
PostCommentCreateInput incorpora actAsUserId. Un moderador con canComment puede comentar ya sea bajo su propio nombre (predeterminado) o como el propietario (actAsUserId = ownerId). En la interfaz web (PostModal), un moderador del autor de la publicación ve un selector "Comentar como: [Yo] / [@owner]" encima del cuadro de comentarios. Comentar como el propietario queda registrado en el registro de auditoría.
GraphQL
- Queries:
myModerators,accountsIModerate,moderatorActivity(feed de auditoría del propietario). - Mutations:
addModerator(userId, permissions),updateModeratorPermissions(userId, permissions)(ambas con bloqueo por 2FA),removeModerator(userId),verifyPasswordForModerators(password)(reautenticación reforzada para las dos mutaciones anteriores bloqueadas por 2FA). - Los inputs de creación/envío incorporan
actAsUserId;likePostydeleteCommentlo reciben como un argumento simple en su lugar.
Archivos clave
- Backend:
database/models/AccountModerator.js,data-access-services/moderator/account-moderator.access-service.js,managers/user-managers/account-moderator.manager.js,graphql/types/account-moderator.type.js,graphql/resolvers/account-moderator.resolver.js; conexión deactAsUserIdenpost.resolver.js(createPost,createStory),post-interaction.resolver.js(likePost),live-stream.resolver.js,conversation.resolver.js,message.resolver.js,post-comment.resolver.js(createComment,deleteComment). - Frontend:
page-components/settings/ModeratorsPage.tsx(interruptores de permisos ampliados + feed de actividad), "Publicar como" encomponents/CreatePostModal.tsx, selector "Comentar como" encomponents/PostModal.tsx, selector "actuar como" encomponents/live/GoLiveModal.tsx,components/chat/ConversationList.tsxycomponents/chat/ChatView.tsx. - Auditoría/atribución:
database/models/AccountModeratorAction.js,data-access-services/moderator/account-moderator-action.access-service.js;logAction/getModeratorActivityenaccount-moderator.manager.js;Message.viaModeratorenmessage.type.js/message.resolver.js.
Configuración
Ejecuta las migraciones 20260721130000-create-account-moderator y 20260721150000-expand-account-moderator y reinicia el backend. No hay variables de entorno nuevas. El propietario debe habilitar el 2FA (Settings → Security) antes de agregar moderadores; los cambios sensibles de moderadores también requieren un reingreso reciente de la contraseña (reautenticación reforzada).