Eliminación de Inquilino
Elimina de forma permanente un inquilino y todos los datos relacionados. Esta operación requiere una triple verificación para garantizar la seguridad.
IMPORTANTE: Todos los endpoints en esta página requieren una Clave API Global. Esta es una operación peligrosa que no puede deshacerse.
Eliminar Inquilino
DELETE /api/tenant
Elimina de forma permanente un inquilino y todos los datos relacionados. Requiere triple verificación para garantizar la seguridad.
ADVERTENCIA
Esta operación es IRREVERSIBLE. Todos los datos del inquilino serán eliminados permanentemente, incluyendo:
- Todos los proyectos y sus conjuntos de datos
- Todas las investigaciones, cuadernos y paneles
- Contenedor y archivos de almacenamiento de blobs
- Registros y configuraciones de la base de datos
- Asignaciones de usuarios al inquilino (los usuarios mismos no son eliminados)
Siempre exporte los datos importantes antes de eliminar un inquilino.
Cuerpo de la Solicitud
{
"tenantId": "12345678-1234-1234-1234-123456789012",
"name": "acme-corp",
"displayName": "Acme Corporation"
}
Triple Verificación
Los tres identificadores deben coincidir exactamente para que la eliminación proceda:
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
tenantId |
GUID | Sí | ID del inquilino a eliminar |
name |
string | Sí | Nombre del inquilino (debe coincidir exactamente) |
displayName |
string | Sí | Nombre para mostrar (debe coincidir exactamente) |
Esta triple verificación previene eliminaciones accidentales al requerir que conozca y confirme los tres identificadores.
Respuesta (200 OK)
{
"message": "Tenant 'Acme Corporation' deleted successfully",
"tenantName": "acme-corp",
"tenantDisplayName": "Acme Corporation",
"storageContainerDeleted": true
}
Campos de la Respuesta
| Campo | Tipo | Descripción |
|---|---|---|
message |
string | Mensaje de confirmación de éxito |
tenantName |
string | Nombre del sistema del inquilino eliminado |
tenantDisplayName |
string | Nombre para mostrar del inquilino eliminado |
storageContainerDeleted |
boolean | Indica si el almacenamiento de blobs fue eliminado |
Respuestas de Error
No Encontrado (404)
{
"error": "Tenant not found with ID '12345678-1234-1234-1234-123456789012'"
}
Verificación Fallida (400)
Cuando el nombre del inquilino no coincide:
{
"error": "Tenant name 'wrong-name' does not match the tenant with ID '12345678-1234-1234-1234-123456789012'. Expected 'acme-corp'.",
"hint": "All three identifiers (ID, name, display name) must match exactly for safety"
}
Cuando el nombre para mostrar no coincide:
{
"error": "Display name 'Wrong Name' does not match the tenant with ID '12345678-1234-1234-1234-123456789012'. Expected 'Acme Corporation'.",
"hint": "All three identifiers (ID, name, display name) must match exactly for safety"
}
No Autorizado (401)
{
"error": "This endpoint requires a Global API key.",
"hint": "Global API keys can be created at /admin/global-api-keys"
}
Ejemplos de Implementación
cURL
# Eliminar inquilino (requiere triple verificación)
curl -X DELETE "https://your-mindzie-instance.com/api/tenant" \
-H "Authorization: Bearer YOUR_GLOBAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"tenantId": "12345678-1234-1234-1234-123456789012",
"name": "test-tenant",
"displayName": "Test Tenant"
}'
Python
import requests
BASE_URL = 'https://your-mindzie-instance.com'
class TenantDeleter:
def __init__(self, global_api_key):
"""Inicializa con una clave API GLOBAL (no específica de inquilino)."""
self.headers = {
'Authorization': f'Bearer {global_api_key}',
'Content-Type': 'application/json'
}
def get_tenant(self, tenant_id):
"""Obtiene detalles del inquilino para verificación."""
url = f'{BASE_URL}/api/tenant/{tenant_id}'
response = requests.get(url, headers=self.headers)
response.raise_for_status()
return response.json()
def delete_tenant(self, tenant_id, name, display_name, confirm=False):
"""
Elimina un inquilino con triple verificación.
Args:
tenant_id: El GUID del inquilino
name: Nombre del sistema del inquilino (debe coincidir exactamente)
display_name: Nombre para mostrar del inquilino (debe coincidir exactamente)
confirm: Establecer en True para realizar la eliminación
"""
if not confirm:
# Modo de verificación - comprobar que los valores coinciden
tenant = self.get_tenant(tenant_id)
errors = []
if tenant['name'] != name:
errors.append(f"Diferencia en el nombre: se esperaba '{tenant['name']}', se obtuvo '{name}'")
if tenant['displayName'] != display_name:
errors.append(f"Diferencia en el nombre para mostrar: se esperaba '{tenant['displayName']}', se obtuvo '{display_name}'")
if errors:
raise ValueError("Verificación fallida:\n" + "\n".join(errors))
print(f"Verificación aprobada para inquilino '{display_name}' ({name})")
print(f" - ID: {tenant_id}")
print(f" - Usuarios: {tenant.get('userCount', 'N/D')}")
print(f" - Casos: {tenant.get('caseCount', 'N/D')}")
print("\nLlame con confirm=True para proceder con la eliminación.")
return None
# Realiza la eliminación
url = f'{BASE_URL}/api/tenant'
payload = {
'tenantId': tenant_id,
'name': name,
'displayName': display_name
}
response = requests.delete(url, json=payload, headers=self.headers)
if response.ok:
return response.json()
elif response.status_code == 404:
raise Exception(f'Inquilino no encontrado: {tenant_id}')
elif response.status_code == 400:
error = response.json()
raise Exception(f"Verificación fallida: {error.get('error', 'Error desconocido')}")
else:
raise Exception(f'Error al eliminar el inquilino: {response.text}')
# Uso - Flujo seguro de eliminación
deleter = TenantDeleter('your-global-api-key')
tenant_id = '12345678-1234-1234-1234-123456789012'
tenant_name = 'test-tenant'
display_name = 'Test Tenant'
# Paso 1: Verificar (no se elimina)
try:
deleter.delete_tenant(tenant_id, tenant_name, display_name, confirm=False)
except ValueError as e:
print(f"Verificación fallida: {e}")
exit(1)
# Paso 2: Confirmar eliminación (descomente cuando esté listo)
# result = deleter.delete_tenant(tenant_id, tenant_name, display_name, confirm=True)
# print(f"Eliminado: {result['message']}")
JavaScript
const BASE_URL = 'https://your-mindzie-instance.com';
class TenantDeleter {
constructor(globalApiKey) {
this.headers = {
'Authorization': `Bearer ${globalApiKey}`,
'Content-Type': 'application/json'
};
}
async getTenant(tenantId) {
const url = `${BASE_URL}/api/tenant/${tenantId}`;
const response = await fetch(url, { headers: this.headers });
if (!response.ok) throw new Error(`Error al obtener el inquilino: ${response.status}`);
return await response.json();
}
async deleteTenant(tenantId, name, displayName, confirm = false) {
if (!confirm) {
// Modo verificación
const tenant = await this.getTenant(tenantId);
const errors = [];
if (tenant.name !== name) {
errors.push(`Diferencia en el nombre: se esperaba '${tenant.name}', se obtuvo '${name}'`);
}
if (tenant.displayName !== displayName) {
errors.push(`Diferencia en el nombre para mostrar: se esperaba '${tenant.displayName}', se obtuvo '${displayName}'`);
}
if (errors.length > 0) {
throw new Error('Verificación fallida:\n' + errors.join('\n'));
}
console.log(`Verificación aprobada para inquilino '${displayName}' (${name})`);
console.log(` - ID: ${tenantId}`);
console.log(` - Usuarios: ${tenant.userCount || 'N/D'}`);
console.log('\nLlame con confirm=true para proceder con la eliminación.');
return null;
}
// Realiza la eliminación
const url = `${BASE_URL}/api/tenant`;
const response = await fetch(url, {
method: 'DELETE',
headers: this.headers,
body: JSON.stringify({ tenantId, name, displayName })
});
if (response.ok) {
return await response.json();
}
const error = await response.json();
throw new Error(error.error || `Error al eliminar: ${response.status}`);
}
}
// Uso - Flujo seguro de eliminación
const deleter = new TenantDeleter('your-global-api-key');
const tenantId = '12345678-1234-1234-1234-123456789012';
const tenantName = 'test-tenant';
const displayName = 'Test Tenant';
// Paso 1: Verificar (no se elimina)
try {
await deleter.deleteTenant(tenantId, tenantName, displayName, false);
} catch (e) {
console.error(`Verificación fallida: ${e.message}`);
process.exit(1);
}
// Paso 2: Confirmar eliminación (descomente cuando esté listo)
// const result = await deleter.deleteTenant(tenantId, tenantName, displayName, true);
// console.log(`Eliminado: ${result.message}`);
Mejores Prácticas de Seguridad
Antes de la Eliminación
- Exporte Todos los Datos: Use la API de Proyectos para exportar todos los proyectos como archivos .mpz
- Verifique los Usuarios: Revise qué usuarios están asignados y notifíquelos
- Documente: Registre qué se está eliminando y por qué, para fines de auditoría
- Verifique Dos Veces: Asegúrese de que el ID, nombre y nombre para mostrar del inquilino sean correctos
Durante la Eliminación
- Use el Patrón de Verificación: Llame al endpoint de eliminación en modo solo verificación primero
- Verifique la Respuesta: Asegúrese de que la respuesta muestre la información correcta del inquilino
- Confirme Deliberadamente: Solo pase
confirm=Truetras una verificación manual
Después de la Eliminación
- Verifique la Eliminación: Confirme que el inquilino ya no aparece en la lista de inquilinos
- Revise los Usuarios: Verifique que los usuarios afectados ya no puedan acceder al inquilino eliminado
- Actualice la Documentación: Registre la eliminación en la documentación de su sistema
Alternativa: Deshabilitar en Lugar de Eliminar
Considere deshabilitar un inquilino en lugar de eliminarlo para preservar los datos mientras se evita el acceso:
# Deshabilitar inquilino (preserva datos)
curl -X PUT "https://your-mindzie-instance.com/api/tenant" \
-H "Authorization: Bearer YOUR_GLOBAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"tenantId": "12345678-1234-1234-1234-123456789012",
"isDisabled": true
}'
Inquilinos deshabilitados:
- Los usuarios no pueden iniciar sesión en el inquilino
- Se conservan todos los datos
- Pueden habilitarse de nuevo configurando
isDisabled: false - Aparecen en la lista de inquilinos con
isDisabled: true
Esta suele ser una opción más segura que la eliminación permanente.