c22b4a2613
NUOVE FUNZIONALITÀ: - Aggiunto modulo CredentialManager per gestione centralizzata credenziali - Implementata UI Blazor per gestione credenziali (CredentialManagement.razor) - Supporto completo per credenziali database (SQL Server, MySQL, PostgreSQL, Oracle, SQLite, DB2, SAP HANA) - Gestione unificata REST API con supporto specifico per SAP B1 Service Layer e Salesforce - Test reali di connessione per database, SAP B1 e Salesforce OAuth2 - Selezione dinamica tipo servizio REST (Generico, SAP B1, Salesforce) con campi specifici - Persistenza sicura di credenziali con crittografia password e campi sensibili COMPONENTI AGGIUNTI: - CredentialManager/Models/: CredentialEntity, CredentialModels (DatabaseCredential, RestApiCredential, SapB1ServiceLayerCredential, SalesforceCredential) - CredentialManager/Services/: CredentialService, EncryptionService, DatabaseInitializer - CredentialManager/Data/: CredentialDbContext con Entity Framework - DataConnection/CredentialManagement/: Interfacce e servizi di integrazione - Data_Coupler/Pages/CredentialManagement.razor: UI completa per gestione credenziali MIGLIORAMENTI UI: - Form dinamica per REST API con campi specifici per tipo servizio - Validazione campi obbligatori per Salesforce (ClientId, ClientSecret, SecurityToken) - Test connessione in tempo reale dalla modale di inserimento/modifica - Rimozione sezioni separate per SAP B1 e Salesforce (ora unificate in REST API) - Gestione stato loading durante operazioni async PERSISTENZA AVANZATA: - Campo RestServiceType aggiunto a CredentialEntity con migrazione automatica - Serializzazione campi specifici Salesforce/SAP B1 in AdditionalParameters JSON - Mapping bidirezionale tra entità database e modelli business - Gestione nullability e conversioni tipo sicure SICUREZZA: - Crittografia AES-256 per password e token sensibili - Gestione sicura ConnectionString database - Validazione input e sanitizzazione dati TESTING E CONNETTIVITÀ: - Test autenticazione reale SAP B1 Service Layer - Test OAuth2 Salesforce con supporto Connected App - Test connettività database multi-provider - Logging dettagliato per debugging e monitoraggio CONFIGURAZIONE: - Dependency injection per tutti i servizi - Configurazione Entity Framework con SQLite - Tasks VS Code per build e run - Gestione connection string centralizzata CORREZIONI: - Risolti errori nullability in CredentialService - Aggiunto using Microsoft.JSInterop per IJSRuntime - Fix compilazione e warning Files modificati: 35+ file tra nuovi e aggiornati
213 lines
8.3 KiB
C#
213 lines
8.3 KiB
C#
using CredentialManager.Models;
|
|
using CredentialManager.Services;
|
|
|
|
namespace CredentialManager.Integration;
|
|
|
|
/// <summary>
|
|
/// Metodi di utilità per l'integrazione con DataConnection
|
|
/// </summary>
|
|
public static class DataConnectionHelper
|
|
{
|
|
/// <summary>
|
|
/// Converte una DatabaseCredential in una stringa di connessione
|
|
/// </summary>
|
|
/// <param name="credential">La credenziale database</param>
|
|
/// <returns>Stringa di connessione pronta per l'uso</returns>
|
|
public static string ToConnectionString(this DatabaseCredential credential)
|
|
{
|
|
return ConnectionStringBuilder.BuildConnectionString(credential);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Crea le opzioni per RestServiceOptions dal progetto DataConnection
|
|
/// </summary>
|
|
/// <param name="credential">La credenziale REST API</param>
|
|
/// <returns>Oggetto con le opzioni per REST service</returns>
|
|
public static object ToRestServiceOptions(this RestApiCredential credential)
|
|
{
|
|
return new
|
|
{
|
|
BaseUrl = credential.BaseUrl,
|
|
ApiKey = credential.ApiKey,
|
|
Username = credential.Username,
|
|
Password = credential.Password,
|
|
AuthToken = credential.AuthToken,
|
|
TimeoutSeconds = credential.TimeoutSeconds,
|
|
IgnoreSslErrors = credential.IgnoreSslErrors
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// Crea le opzioni per DbManagerOptions dal progetto DataConnection
|
|
/// </summary>
|
|
/// <param name="credential">La credenziale database</param>
|
|
/// <returns>Oggetto con le opzioni per DB manager</returns>
|
|
public static object ToDbManagerOptions(this DatabaseCredential credential)
|
|
{
|
|
return new
|
|
{
|
|
ServerConnectionString = credential.ToConnectionString(),
|
|
DatabaseName = credential.DatabaseName,
|
|
DatabaseType = credential.DatabaseType.ToString(),
|
|
CommandTimeout = credential.CommandTimeout
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// Ottiene la porta predefinita per un tipo di database
|
|
/// </summary>
|
|
/// <param name="databaseType">Tipo di database</param>
|
|
/// <returns>Porta predefinita</returns>
|
|
public static int GetDefaultPort(DatabaseType databaseType)
|
|
{
|
|
return databaseType switch
|
|
{
|
|
DatabaseType.SqlServer => 1433,
|
|
DatabaseType.MySql => 3306,
|
|
DatabaseType.PostgreSql => 5432,
|
|
DatabaseType.Oracle => 1521,
|
|
DatabaseType.DB2 => 50000,
|
|
DatabaseType.SapHana => 30015,
|
|
DatabaseType.Sqlite => 0, // Non applicabile
|
|
_ => 0
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// Valida una credenziale database
|
|
/// </summary>
|
|
/// <param name="credential">La credenziale da validare</param>
|
|
/// <returns>Lista di errori di validazione (vuota se valida)</returns>
|
|
public static List<string> ValidateDatabaseCredential(DatabaseCredential credential)
|
|
{
|
|
var errors = new List<string>();
|
|
|
|
if (string.IsNullOrWhiteSpace(credential.Name))
|
|
errors.Add("Il nome della credenziale è obbligatorio");
|
|
|
|
if (string.IsNullOrWhiteSpace(credential.Host) && credential.DatabaseType != DatabaseType.Sqlite)
|
|
errors.Add("L'host è obbligatorio per questo tipo di database");
|
|
|
|
if (string.IsNullOrWhiteSpace(credential.DatabaseName))
|
|
errors.Add("Il nome del database è obbligatorio");
|
|
|
|
if (string.IsNullOrWhiteSpace(credential.Username) && credential.DatabaseType != DatabaseType.Sqlite)
|
|
errors.Add("Il nome utente è obbligatorio per questo tipo di database");
|
|
|
|
if (string.IsNullOrWhiteSpace(credential.Password) && credential.DatabaseType != DatabaseType.Sqlite)
|
|
errors.Add("La password è obbligatoria per questo tipo di database");
|
|
|
|
if (credential.Port <= 0 && credential.DatabaseType != DatabaseType.Sqlite)
|
|
{
|
|
// Assegna porta predefinita se non specificata
|
|
credential.Port = GetDefaultPort(credential.DatabaseType);
|
|
}
|
|
|
|
return errors;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Valida una credenziale REST API
|
|
/// </summary>
|
|
/// <param name="credential">La credenziale da validare</param>
|
|
/// <returns>Lista di errori di validazione (vuota se valida)</returns>
|
|
public static List<string> ValidateRestApiCredential(RestApiCredential credential)
|
|
{
|
|
var errors = new List<string>();
|
|
|
|
if (string.IsNullOrWhiteSpace(credential.Name))
|
|
errors.Add("Il nome della credenziale è obbligatorio");
|
|
|
|
if (string.IsNullOrWhiteSpace(credential.BaseUrl))
|
|
errors.Add("L'URL base è obbligatorio");
|
|
else if (!Uri.TryCreate(credential.BaseUrl, UriKind.Absolute, out _))
|
|
errors.Add("L'URL base non è valido");
|
|
|
|
// Almeno uno tra ApiKey, Username/Password, o AuthToken deve essere specificato
|
|
var hasApiKey = !string.IsNullOrWhiteSpace(credential.ApiKey);
|
|
var hasUserPass = !string.IsNullOrWhiteSpace(credential.Username) && !string.IsNullOrWhiteSpace(credential.Password);
|
|
var hasAuthToken = !string.IsNullOrWhiteSpace(credential.AuthToken);
|
|
|
|
if (!hasApiKey && !hasUserPass && !hasAuthToken)
|
|
errors.Add("Deve essere specificato almeno un metodo di autenticazione (API Key, Username/Password, o Auth Token)");
|
|
|
|
return errors;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Estensioni per la gestione asincrona delle credenziali
|
|
/// </summary>
|
|
public static class CredentialServiceExtensions
|
|
{
|
|
/// <summary>
|
|
/// Ottiene una credenziale database validata
|
|
/// </summary>
|
|
/// <param name="service">Il servizio credenziali</param>
|
|
/// <param name="name">Nome della credenziale</param>
|
|
/// <returns>Credenziale validata o null se non trovata</returns>
|
|
public static async Task<DatabaseCredential?> GetValidatedDatabaseCredentialAsync(
|
|
this ICredentialService service, string name)
|
|
{
|
|
var credential = await service.GetDatabaseCredentialAsync(name);
|
|
if (credential == null) return null;
|
|
|
|
var errors = DataConnectionHelper.ValidateDatabaseCredential(credential);
|
|
if (errors.Any())
|
|
throw new ArgumentException($"Credenziale non valida: {string.Join(", ", errors)}");
|
|
|
|
return credential;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Ottiene una credenziale REST API validata
|
|
/// </summary>
|
|
/// <param name="service">Il servizio credenziali</param>
|
|
/// <param name="name">Nome della credenziale</param>
|
|
/// <returns>Credenziale validata o null se non trovata</returns>
|
|
public static async Task<RestApiCredential?> GetValidatedRestApiCredentialAsync(
|
|
this ICredentialService service, string name)
|
|
{
|
|
var credential = await service.GetRestApiCredentialAsync(name);
|
|
if (credential == null) return null;
|
|
|
|
var errors = DataConnectionHelper.ValidateRestApiCredential(credential);
|
|
if (errors.Any())
|
|
throw new ArgumentException($"Credenziale non valida: {string.Join(", ", errors)}");
|
|
|
|
return credential;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Salva una credenziale database con validazione
|
|
/// </summary>
|
|
/// <param name="service">Il servizio credenziali</param>
|
|
/// <param name="credential">La credenziale da salvare</param>
|
|
/// <returns>ID della credenziale salvata</returns>
|
|
public static async Task<int> SaveValidatedDatabaseCredentialAsync(
|
|
this ICredentialService service, DatabaseCredential credential)
|
|
{
|
|
var errors = DataConnectionHelper.ValidateDatabaseCredential(credential);
|
|
if (errors.Any())
|
|
throw new ArgumentException($"Credenziale non valida: {string.Join(", ", errors)}");
|
|
|
|
return await service.SaveDatabaseCredentialAsync(credential);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Salva una credenziale REST API con validazione
|
|
/// </summary>
|
|
/// <param name="service">Il servizio credenziali</param>
|
|
/// <param name="credential">La credenziale da salvare</param>
|
|
/// <returns>ID della credenziale salvata</returns>
|
|
public static async Task<int> SaveValidatedRestApiCredentialAsync(
|
|
this ICredentialService service, RestApiCredential credential)
|
|
{
|
|
var errors = DataConnectionHelper.ValidateRestApiCredential(credential);
|
|
if (errors.Any())
|
|
throw new ArgumentException($"Credenziale non valida: {string.Join(", ", errors)}");
|
|
|
|
return await service.SaveRestApiCredentialAsync(credential);
|
|
}
|
|
}
|