Apps multi-tenant
Una app tuya para muchas empresas: inicio de sesión con DinaupAuthClient, un MyAppClient por usuario vinculado a su empresa y el almacén clave-valor MyAppKVClient.
Una sola app tuya puede dar servicio a muchas empresas: Dinaup pone el inicio de sesión, el aislamiento entre empresas y la base de datos, y tú la interfaz y la lógica.
Antes de empezar
- Paquete
Dinaupy tu biblioteca MyDinaup. - El
AppId(un GUID) y elAppTokende tu aplicación, registrados en Dinaup. Guárdalos en el Vault con las clavesDINAUP_APPIDyDINAUP_APPTOKEN.
Las tres piezas
| Pieza | Qué es | Ciclo de vida |
|---|---|---|
DinaupExternalAppSettings | La identidad de tu aplicación: AppId + AppToken. | Singleton |
DinaupAuthClient | Autentica usuarios por correo y contraseña y devuelve su empresa. | Singleton |
MyAppClient | El cliente de datos de un usuario, vinculado a su empresa. | Uno por sesión (Scoped) |
MyAppClient hereda de DinaupClientC: todo lo del Cliente Dinaup funciona igual, pero cada instancia solo llega a la empresa del usuario autenticado.
Montar la app
Carga la identidad de la app
var vault = new Dinaup.Vault.VaultData("VAULT_URL", "VAULT_PASSWORD");
vault.Initialize();
var appConfig = new Dinaup.Models.DinaupExternalAppSettings(vault); // lee DINAUP_APPID y DINAUP_APPTOKENSin Vault: new DinaupExternalAppSettings(appId, appToken), con appId como Guid.
Registra los servicios
builder.Services.AddSingleton<Dinaup.Models.DinaupExternalAppSettings>(appConfig);
builder.Services.AddSingleton<Dinaup.Auth.DinaupAuthClient>(new Dinaup.Auth.DinaupAuthClient());
builder.Services.AddSingleton<Dinaup.MyAppKVClient>(); // se construye con el DinaupExternalAppSettings registrado
builder.Services.AddScoped<SessionUserContext>(); // tu contexto de sesión, uno por usuario
builder.Services.AddHealthChecks().AddCheck<Dinaup.MyAppKVClient>("MyAppKVClient");El MyAppClient y cualquier servicio que lo use van en Scoped. Un singleton compartiría la sesión de una empresa con los usuarios de otra.
Autentica al usuario
LoginAsync(email, password) valida las credenciales contra auth.dinaup.com y devuelve un AuthResponse, o null si fallan. Con él construyes su MyAppClient.
var authResponse = await _authClient.LoginAsync(email, password);
if (authResponse == null) throw new Exception("Credenciales inválidas");
DinaupClient = new Dinaup.MyAppClient(_appSettings, authResponse);AuthResponse trae TenantConnectionKeyword (la empresa), UserEmail, UserId, LicId, LicSerie, ApiEndpoint, Version, Revision y TwoFactor.
Para reconstruir la sesión en otra petición, guarda la clave de conexión y el correo en MyAppKVClient y usa el tercer constructor:
await _kvClient.SetKVAsync($"session:{sessionId}", $"{authResponse.TenantConnectionKeyword}|{authResponse.UserEmail}");
// En otra petición
var partes = (await _kvClient.GetKVAsync($"session:{sessionId}")).Split('|');
DinaupClient = new Dinaup.MyAppClient(_appSettings, partes[0], partes[1]);Opera con los datos de su empresa
var rpt = new APIPaisesC();
await rpt.ExecuteQueryAsync(_session.DinaupClient, 1, 1000);Qué añade MyAppClient
| Miembro | Qué hace |
|---|---|
ExecuteReport(ReportRequestParameters, filter) | Ejecuta un informe por parámetros y devuelve un ReportResponse. |
ExecuteReport(id, QuerySearch, AdvancedFilter, ResultsPerPage, order, adminmode) | Ejecuta un informe por id con búsqueda, filtros (List<FilterCondition>), orden y modo administrador. Hay sobrecargas con variables (Dictionary<string, string>) y con LoadDataReportC. |
Email, Nombre, IsLogged | Datos de la sesión. MyAppClient implementa IUserSession y queda como DefaultSession del cliente. |
LicenseId, UserId | Devuelven Guid.Empty. Para atribuir escrituras a un usuario, usa DinaupContext.WithUser. |
Cuentas de usuario
Tu app da de alta usuarios, los activa y gestiona contraseñas sin pantallas de Dinaup. Todos los métodos reciben el userAgent y la IP del usuario final.
| Método | Qué hace |
|---|---|
Session_RegisterAccountAsync(model, userAgent, userIP) | Crea la cuenta temporal y genera el código de activación. model es un AccountCreationModel. |
Session_ConfirmAccountRegistrationAsync(model, userAgent, userIP) | Activa la cuenta usando el código recibido. model es un AccountActivationModel. |
Session_SignInAsync(email, password, userAgent, userIP, verifyPassword = true) | Inicia sesión y devuelve un SessionSignInResponse (correcta, 2FA pendiente, rechazada). |
Session_CreateLoginCodeAsync(email, userAgent, userIP) y Session_SignInWithCodeAsync(email, code, userAgent, userIP) | Acceso sin contraseña: envía un código y entra con él. |
Session_CheckTwoFactor(sessionId, code, userAgent, userIP) | Verifica el código 2FA de una sesión pendiente. sessionId es Guid. |
Session_GetDetailsAsync(sessionId, userAgent, userIP) | Detalles de una sesión activa. |
Session_SignOutAsync(sessionId, userAgent, userIP) | Cierra la sesión. |
Session_RecoverPasswordAsync(email, userAgent, userIP) | Inicia la recuperación de contraseña por correo. |
Session_CreatePasswordRecoveryCodeAsync(model, userAgent, userIP) | Genera un código de recuperación. model es un PasswordRecoveryModel. |
Session_ChangePasswordWithCodeAsync(userEmail, code, newPassword, userAgent, userIP) | Cambia la contraseña con ese código. |
Para cambiar la contraseña de un usuario, genera el código con Session_CreatePasswordRecoveryCodeAsync y cámbiala con Session_ChangePasswordWithCodeAsync. Los modelos de entrada (Dinaup.Models) validan sus campos antes de llamar al servidor.
Almacenamiento clave-valor de la app
MyAppKVClient guarda pares clave-valor de tu aplicación: configuración, indicadores y sesiones de tus usuarios.
bool guardado = await _kvClient.SetKVAsync("clave", "valor");
string valor = await _kvClient.GetKVAsync("clave"); // "" si no existe- Texto plano, hasta 10 MB por clave; por encima,
SetKVAsynclanzaInvalidOperationException. Un error HTTP lanzaHttpRequestException. - Las claves son de la aplicación, no de cada empresa: prefija lo que sea de una empresa o una sesión (
session:{id},config:{empresa}). - Como comprobación de estado (
AddCheck<MyAppKVClient>), escribe la clavemyappkvclient.healthen cada sonda y respondeUnhealthysi falla. Ver ASP.NET Core.
Los pares de una empresa van en otro almacén: Clave-valor de la empresa.