chore: release v2.4

- Add theme system (Dark/Light palettes, ModernTheme, ThemeManager)
- Add InputDialog, Spinner common view
- Add DuplicatesCsvExportService
- Refresh views, dialogs, and view models across tabs
- Update localization strings (en/fr)
- Tweak services (transfer, permissions, search, user access, ownership elevation, bulk operations)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dev
2026-04-20 11:23:11 +02:00
parent 8f30a60d2a
commit 12dd1de9f2
93 changed files with 8708 additions and 1159 deletions
@@ -9,23 +9,25 @@ public interface IAppRegistrationService
{
/// <summary>
/// Returns true if the currently-authenticated user has the Global Administrator
/// directory role (checked via transitiveMemberOf for nested-group coverage).
/// Returns false on any failure, including 403, rather than throwing.
/// directory role in the target tenant (checked via transitiveMemberOf for
/// nested-group coverage). Throws on Graph/network failure so the UI can
/// distinguish a confirmed non-admin from a call that could not complete.
/// </summary>
Task<bool> IsGlobalAdminAsync(string clientId, CancellationToken ct);
Task<bool> IsGlobalAdminAsync(string clientId, string tenantUrl, CancellationToken ct);
/// <summary>
/// Creates an Azure AD Application + ServicePrincipal + OAuth2PermissionGrants
/// atomically. On any intermediate failure the Application is deleted before
/// returning a Failure result (best-effort rollback).
/// atomically in the tenant identified by <paramref name="tenantUrl"/>.
/// On any intermediate failure the Application is deleted before returning
/// a Failure result (best-effort rollback).
/// </summary>
Task<AppRegistrationResult> RegisterAsync(string clientId, string tenantDisplayName, CancellationToken ct);
Task<AppRegistrationResult> RegisterAsync(string clientId, string tenantUrl, string tenantDisplayName, CancellationToken ct);
/// <summary>
/// Deletes the registered application by its appId.
/// Deletes the registered application by its appId in the given tenant.
/// Logs a warning on failure but does not throw.
/// </summary>
Task RemoveAsync(string clientId, string appId, CancellationToken ct);
Task RemoveAsync(string clientId, string tenantUrl, string appId, CancellationToken ct);
/// <summary>
/// Clears the live SessionManager context, evicts all in-memory MSAL accounts,