Operaciones Globales de Usuarios

Los endpoints globales de usuario proporcionan capacidades de gestión de usuarios a nivel del sistema. Estos endpoints requieren una Clave API Global y pueden acceder a usuarios de todos los tenants.

Autenticación

Todos los endpoints en esta página requieren una Clave API Global. Las claves API con ámbito de tenant recibirán un error 401 Unauthorized.


Listar Todos los Usuarios

GET /api/user

Recupera una lista paginada de todos los usuarios en todos los tenants.

Parámetros de Consulta

Parámetro Tipo Predeterminado Descripción
page entero 1 Número de página para paginación
pageSize entero 50 Número de ítems por página (máx: 1000)
includeDisabled booleano false Incluir usuarios deshabilitados
role cadena null Filtrar por nombre de rol
search cadena null Buscar por correo o nombre para mostrar

Respuesta (200 OK)

{
  "users": [
    {
      "userId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "email": "john.smith@example.com",
      "displayName": "John Smith",
      "firstName": "John",
      "lastName": "Smith",
      "roleName": "Analyst",
      "disabled": false,
      "isServiceAccount": false,
      "homeTenantId": null,
      "homeTenantName": null,
      "lastLogin": "2024-01-15T10:30:00Z",
      "tenantCount": 2,
      "tenantNames": "acme-corp, globex-inc",
      "dateCreated": "2024-01-01T00:00:00Z"
    }
  ],
  "totalCount": 150,
  "page": 1,
  "pageSize": 50
}

Campos del Objeto Usuario

Campo Tipo Descripción
userId GUID Identificador único del usuario
email cadena Dirección de correo del usuario (única)
displayName cadena Nombre para mostrar del usuario
firstName cadena Nombre del usuario
lastName cadena Apellido del usuario
roleName cadena Rol del usuario (Administrator, TenantAdmin, Analyst, etc.)
disabled booleano Indica si la cuenta está deshabilitada
isServiceAccount booleano Indica si es una cuenta de servicio
homeTenantId GUID Tenant principal para cuentas de servicio
homeTenantName cadena Nombre del tenant principal para cuentas de servicio
lastLogin fecha y hora Último acceso
tenantCount entero Número de tenants asignados
tenantNames cadena Lista separada por comas de nombres de tenants
dateCreated fecha y hora Fecha de creación de la cuenta

Respuestas de Error

No autorizado (401):

{
  "error": "This endpoint requires a Global API key. Tenant-specific API keys cannot list all users.",
  "hint": "Use /api/tenant/{tenantId}/user to list users for a specific tenant, or create a Global API key at /admin/global-api-keys"
}

Crear Usuario

POST /api/user

Crea un nuevo usuario en el sistema. Esto NO asigna al usuario a ningún tenant.

Cuerpo de la Solicitud

{
  "email": "john.smith@example.com",
  "displayName": "John Smith",
  "firstName": "John",
  "lastName": "Smith",
  "roleName": "Analyst"
}

Campos de la Solicitud

Campo Tipo Obligatorio Descripción
email cadena Correo del usuario (debe ser único)
displayName cadena Nombre para mostrar (2-100 caracteres)
firstName cadena No Nombre (máx. 50 caracteres)
lastName cadena No Apellido (máx. 50 caracteres)
roleName cadena Nombre del rol (ver Roles y Permisos)

Respuesta (201 Creado)

{
  "userId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "email": "john.smith@example.com",
  "displayName": "John Smith",
  "message": "User created successfully"
}

Respuestas de Error

Conflicto (409):

{
  "error": "A user with email 'john.smith@example.com' already exists"
}

Obtener Usuario por ID

GET /api/user/{userId}

Recupera información detallada de un usuario específico.

Parámetros de Ruta

Parámetro Tipo Descripción
userId GUID Identificador del usuario

Respuesta (200 OK)

Devuelve un objeto completo del usuario con sus asignaciones a tenants.

Respuestas de Error

No encontrado (404):

{
  "error": "User not found with ID 'a1b2c3d4-e5f6-7890-abcd-ef1234567890'",
  "userId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}

Actualizar Usuario

PUT /api/user/{userId}

Actualiza las propiedades del usuario. Solo se actualizarán los campos proporcionados.

Parámetros de Ruta

Parámetro Tipo Descripción
userId GUID Identificador del usuario

Cuerpo de la Solicitud

{
  "displayName": "Jane Smith",
  "roleName": "TenantAdmin",
  "disabled": false,
  "isServiceAccount": true,
  "homeTenantId": "12345678-1234-1234-1234-123456789012"
}

Campos de la Solicitud

Campo Tipo Obligatorio Descripción
displayName cadena No Nuevo nombre para mostrar
roleName cadena No Nuevo nombre del rol
disabled booleano No Habilitar/deshabilitar cuenta
isServiceAccount booleano No Indicador de cuenta de servicio
homeTenantId GUID Condicional Requerido si se convierte en cuenta de servicio

Reglas para Cuentas de Servicio

  • Solo los roles Administrator y TenantAdmin pueden ser cuentas de servicio
  • Al promover a cuenta de servicio, homeTenantId es requerido
  • Al degradar de cuenta de servicio, homeTenantId se borra automáticamente

Respuesta (200 OK)

{
  "message": "User updated successfully"
}

Obtener Usuario por Correo

GET /api/user/by-email/{email}

Recupera un usuario por su dirección de correo electrónico.

Parámetros de Ruta

Parámetro Tipo Descripción
email cadena Dirección de correo del usuario (codificada en URL)

Respuesta (200 OK)

Devuelve un objeto completo del usuario.


Obtener Tenants del Usuario

GET /api/user/{userId}/tenants

Recupera todas las asignaciones de tenant para un usuario.

Parámetros de Ruta

Parámetro Tipo Descripción
userId GUID Identificador del usuario

Respuesta (200 OK)

{
  "userId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "email": "john.smith@example.com",
  "displayName": "John Smith",
  "tenants": [
    {
      "tenantId": "12345678-1234-1234-1234-123456789012",
      "tenantName": "acme-corp",
      "displayName": "Acme Corporation",
      "dateAssigned": "2024-01-15T10:30:00Z"
    }
  ]
}

Ejemplos de Implementación

cURL

# Listar todos los usuarios (Se requiere clave API global)
curl -X GET "https://your-mindzie-instance.com/api/user?page=1&pageSize=50" \
  -H "Authorization: Bearer YOUR_GLOBAL_API_KEY"

# Buscar usuarios por nombre
curl -X GET "https://your-mindzie-instance.com/api/user?search=john" \
  -H "Authorization: Bearer YOUR_GLOBAL_API_KEY"

# Filtrar por rol
curl -X GET "https://your-mindzie-instance.com/api/user?role=Analyst" \
  -H "Authorization: Bearer YOUR_GLOBAL_API_KEY"

# Crear un nuevo usuario
curl -X POST "https://your-mindzie-instance.com/api/user" \
  -H "Authorization: Bearer YOUR_GLOBAL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "john.smith@example.com",
    "displayName": "John Smith",
    "roleName": "Analyst"
  }'

# Obtener usuario por ID
curl -X GET "https://your-mindzie-instance.com/api/user/a1b2c3d4-e5f6-7890-abcd-ef1234567890" \
  -H "Authorization: Bearer YOUR_GLOBAL_API_KEY"

# Obtener usuario por correo electrónico
curl -X GET "https://your-mindzie-instance.com/api/user/by-email/john.smith%40example.com" \
  -H "Authorization: Bearer YOUR_GLOBAL_API_KEY"

# Obtener tenants del usuario
curl -X GET "https://your-mindzie-instance.com/api/user/a1b2c3d4-e5f6-7890-abcd-ef1234567890/tenants" \
  -H "Authorization: Bearer YOUR_GLOBAL_API_KEY"

Python

import requests

BASE_URL = 'https://your-mindzie-instance.com'

class GlobalUserManager:
    def __init__(self, global_api_key):
        """Inicializar con una clave API GLOBAL (no específica de tenant)."""
        self.headers = {
            'Authorization': f'Bearer {global_api_key}',
            'Content-Type': 'application/json'
        }

    def list_users(self, page=1, page_size=50, include_disabled=False,
                   role=None, search=None):
        """Listar todos los usuarios en todos los tenants."""
        url = f'{BASE_URL}/api/user'
        params = {
            'page': page,
            'pageSize': page_size,
            'includeDisabled': include_disabled
        }
        if role:
            params['role'] = role
        if search:
            params['search'] = search

        response = requests.get(url, headers=self.headers, params=params)
        response.raise_for_status()
        return response.json()

    def create_user(self, email, display_name, role_name,
                    first_name=None, last_name=None):
        """Crear un nuevo usuario (no asignado a ningún tenant)."""
        url = f'{BASE_URL}/api/user'
        payload = {
            'email': email,
            'displayName': display_name,
            'roleName': role_name
        }
        if first_name:
            payload['firstName'] = first_name
        if last_name:
            payload['lastName'] = last_name

        response = requests.post(url, json=payload, headers=self.headers)
        response.raise_for_status()
        return response.json()

    def get_user(self, user_id):
        """Obtener usuario por ID."""
        url = f'{BASE_URL}/api/user/{user_id}'
        response = requests.get(url, headers=self.headers)
        response.raise_for_status()
        return response.json()

    def get_user_by_email(self, email):
        """Obtener usuario por correo electrónico."""
        from urllib.parse import quote
        url = f'{BASE_URL}/api/user/by-email/{quote(email, safe="")}'
        response = requests.get(url, headers=self.headers)
        response.raise_for_status()
        return response.json()

    def update_user(self, user_id, display_name=None, role_name=None,
                    disabled=None, is_service_account=None, home_tenant_id=None):
        """Actualizar propiedades del usuario."""
        url = f'{BASE_URL}/api/user/{user_id}'
        payload = {}
        if display_name is not None:
            payload['displayName'] = display_name
        if role_name is not None:
            payload['roleName'] = role_name
        if disabled is not None:
            payload['disabled'] = disabled
        if is_service_account is not None:
            payload['isServiceAccount'] = is_service_account
        if home_tenant_id is not None:
            payload['homeTenantId'] = home_tenant_id

        response = requests.put(url, json=payload, headers=self.headers)
        response.raise_for_status()
        return response.json()

    def get_user_tenants(self, user_id):
        """Obtener todas las asignaciones de tenant para un usuario."""
        url = f'{BASE_URL}/api/user/{user_id}/tenants'
        response = requests.get(url, headers=self.headers)
        response.raise_for_status()
        return response.json()

# Uso
manager = GlobalUserManager('your-global-api-key')

# Listar todos los analistas
analysts = manager.list_users(role='Analyst')
print(f"Total de analistas: {analysts['totalCount']}")

# Crear un nuevo usuario
new_user = manager.create_user(
    email='new.analyst@example.com',
    display_name='New Analyst',
    role_name='Analyst',
    first_name='New',
    last_name='Analyst'
)
print(f"Usuario creado: {new_user['userId']}")

# Obtener asignaciones de tenant del usuario
user_id = new_user['userId']
tenants = manager.get_user_tenants(user_id)
print(f"El usuario está asignado a {len(tenants['tenants'])} tenants")

JavaScript/Node.js

const BASE_URL = 'https://your-mindzie-instance.com';

class GlobalUserManager {
  constructor(globalApiKey) {
    this.headers = {
      'Authorization': `Bearer ${globalApiKey}`,
      'Content-Type': 'application/json'
    };
  }

  async listUsers(options = {}) {
    const params = new URLSearchParams({
      page: options.page || 1,
      pageSize: options.pageSize || 50,
      includeDisabled: options.includeDisabled || false
    });
    if (options.role) params.append('role', options.role);
    if (options.search) params.append('search', options.search);

    const url = `${BASE_URL}/api/user?${params}`;
    const response = await fetch(url, { headers: this.headers });
    if (!response.ok) throw new Error(`Failed: ${response.status}`);
    return await response.json();
  }

  async createUser(email, displayName, roleName) {
    const url = `${BASE_URL}/api/user`;
    const response = await fetch(url, {
      method: 'POST',
      headers: this.headers,
      body: JSON.stringify({ email, displayName, roleName })
    });
    if (!response.ok) throw new Error(`Failed: ${response.status}`);
    return await response.json();
  }

  async getUser(userId) {
    const url = `${BASE_URL}/api/user/${userId}`;
    const response = await fetch(url, { headers: this.headers });
    if (!response.ok) throw new Error(`Failed: ${response.status}`);
    return await response.json();
  }

  async getUserTenants(userId) {
    const url = `${BASE_URL}/api/user/${userId}/tenants`;
    const response = await fetch(url, { headers: this.headers });
    if (!response.ok) throw new Error(`Failed: ${response.status}`);
    return await response.json();
  }
}

// Uso
const manager = new GlobalUserManager('your-global-api-key');

// Listar todos los usuarios
const users = await manager.listUsers();
console.log(`Total de usuarios: ${users.totalCount}`);

// Crear y verificar asignaciones de tenant
const newUser = await manager.createUser(
  'new@example.com',
  'New User',
  'Analyst'
);
const tenants = await manager.getUserTenants(newUser.userId);
console.log(`Asignado a ${tenants.tenants.length} tenants`);