diff --git a/Data_Coupler/Pages/DataCoupler.razor.cs b/Data_Coupler/Pages/DataCoupler.razor.cs index 0cc8ad4..6588f73 100644 --- a/Data_Coupler/Pages/DataCoupler.razor.cs +++ b/Data_Coupler/Pages/DataCoupler.razor.cs @@ -662,11 +662,18 @@ public partial class DataCoupler : ComponentBase // Clear mappings when changing sheet ClearAllMappings(); - // For file sources, always require manual key selection + // For file sources, try auto-selection and then require manual key selection if not found sourceKeyField = ""; suggestedPrimaryKey = ""; requiresManualKeySelection = true; + // AUTO-SELECT della chiave per i file + if (fileSheets.ContainsKey(sheetName)) + { + var columns = fileSheets[sheetName].ToList(); + TryAutoSelectKeyForFile(columns); + } + StateHasChanged(); } @@ -968,26 +975,33 @@ public partial class DataCoupler : ComponentBase if (!string.IsNullOrEmpty(primaryKey)) { suggestedPrimaryKey = primaryKey; - // Suggest the primary key but don't auto-select it - Logger.LogInformation("Primary key detected for table {TableName}: {PrimaryKey}", tableName, primaryKey); + + // AUTO-SELECT: Imposta automaticamente il campo chiave se rilevato + sourceKeyField = primaryKey; + requiresManualKeySelection = false; + + Logger.LogInformation("Chiave primaria rilevata e auto-selezionata per la tabella {TableName}: {PrimaryKey}", tableName, primaryKey); } else { // No primary key found, require manual selection requiresManualKeySelection = true; - Logger.LogInformation("No primary key found for table {TableName}, manual selection required", tableName); + sourceKeyField = ""; + Logger.LogInformation("Nessuna chiave primaria trovata per la tabella {TableName}, selezione manuale richiesta", tableName); } } catch (Exception ex) { - Logger.LogError(ex, "Error detecting primary key for table {TableName}", tableName); + Logger.LogError(ex, "Errore nel rilevamento della chiave primaria per la tabella {TableName}", tableName); requiresManualKeySelection = true; + sourceKeyField = ""; } } else { // For non-database sources, always require manual selection requiresManualKeySelection = true; + sourceKeyField = ""; } StateHasChanged(); @@ -2008,7 +2022,38 @@ public partial class DataCoupler : ComponentBase return false; var trimmedQuery = query.Trim(); - return trimmedQuery.StartsWith("SELECT", StringComparison.OrdinalIgnoreCase); + + // Deve iniziare con SELECT + if (!trimmedQuery.StartsWith("SELECT", StringComparison.OrdinalIgnoreCase)) + return false; + + // Lista di parole chiave vietate per sicurezza + var forbiddenKeywords = new[] + { + "INSERT", "UPDATE", "DELETE", "DROP", "CREATE", "ALTER", "TRUNCATE", + "EXEC", "EXECUTE", "sp_", "xp_", "BULK", "OPENROWSET", "OPENDATASOURCE" + }; + + var upperQuery = trimmedQuery.ToUpperInvariant(); + + // Verifica che non contenga parole chiave vietate + foreach (var keyword in forbiddenKeywords) + { + if (upperQuery.Contains(keyword)) + { + Logger.LogWarning("Query rifiutata: contiene parola chiave vietata '{Keyword}'", keyword); + return false; + } + } + + // Verifica che non contenga commenti SQL potenzialmente pericolosi + if (upperQuery.Contains("--") || upperQuery.Contains("/*")) + { + Logger.LogWarning("Query rifiutata: contiene commenti SQL non consentiti"); + return false; + } + + return true; } /// @@ -2027,6 +2072,12 @@ public partial class DataCoupler : ComponentBase { cleanQuery = cleanQuery.Substring(0, cleanQuery.Length - 1).Trim(); } + + // Rimuove caratteri di controllo pericolosi + cleanQuery = System.Text.RegularExpressions.Regex.Replace(cleanQuery, @"[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]", ""); + + // Normalizza spazi multipli + cleanQuery = System.Text.RegularExpressions.Regex.Replace(cleanQuery, @"\s+", " "); return cleanQuery; } @@ -2112,6 +2163,9 @@ public partial class DataCoupler : ComponentBase // Clear mappings quando cambia la query ClearAllMappings(); + // AUTO-SELECT della chiave per query custom + TryAutoSelectKeyForQuery(queryColumns); + Logger.LogInformation("Query validata con successo: {ColumnCount} colonne", queryColumns.Count); } else @@ -2706,6 +2760,157 @@ public partial class DataCoupler : ComponentBase } } + /// + /// Tenta di auto-selezionare una chiave per le query custom + /// + private void TryAutoSelectKeyForQuery(List columns) + { + try + { + // Reset stato chiave + sourceKeyField = ""; + suggestedPrimaryKey = ""; + requiresManualKeySelection = true; + + // Pattern comuni per identificare possibili chiavi primarie + var keyPatterns = new[] + { + "id", "ID", "Id", + "_id", "_ID", "_Id", + "key", "KEY", "Key", + "code", "CODE", "Code", + "number", "NUMBER", "Number" + }; + + // Cerca colonne che potrebbero essere chiavi primarie + string? detectedKey = null; + + // 1. Cerca esattamente "id", "ID", "Id" + detectedKey = columns.FirstOrDefault(c => + c.Equals("id", StringComparison.OrdinalIgnoreCase) || + c.Equals("ID", StringComparison.Ordinal) || + c.Equals("Id", StringComparison.Ordinal)); + + // 2. Se non trovato, cerca colonne che terminano con "id", "ID", "Id" + if (detectedKey == null) + { + detectedKey = columns.FirstOrDefault(c => + c.EndsWith("id", StringComparison.OrdinalIgnoreCase) || + c.EndsWith("ID", StringComparison.Ordinal) || + c.EndsWith("Id", StringComparison.Ordinal)); + } + + // 3. Se non trovato, cerca colonne che contengono pattern di chiave + if (detectedKey == null) + { + foreach (var pattern in keyPatterns) + { + detectedKey = columns.FirstOrDefault(c => + c.Contains(pattern, StringComparison.OrdinalIgnoreCase)); + if (detectedKey != null) break; + } + } + + // 4. Auto-seleziona se trovato + if (!string.IsNullOrEmpty(detectedKey)) + { + sourceKeyField = detectedKey; + suggestedPrimaryKey = detectedKey; + requiresManualKeySelection = false; + + Logger.LogInformation("Chiave auto-selezionata per query custom: {KeyField}", detectedKey); + } + else + { + Logger.LogInformation("Nessuna chiave rilevabile automaticamente per query custom, selezione manuale richiesta"); + } + } + catch (Exception ex) + { + Logger.LogError(ex, "Errore nell'auto-selezione della chiave per query custom"); + sourceKeyField = ""; + suggestedPrimaryKey = ""; + requiresManualKeySelection = true; + } + } + + /// + /// Tenta di auto-selezionare una chiave per i file (Excel/CSV) + /// + private void TryAutoSelectKeyForFile(List columns) + { + try + { + // Reset stato chiave + sourceKeyField = ""; + suggestedPrimaryKey = ""; + requiresManualKeySelection = true; + + // Pattern comuni per identificare possibili chiavi primarie nei file + var keyPatterns = new[] + { + "id", "ID", "Id", + "_id", "_ID", "_Id", + "key", "KEY", "Key", + "code", "CODE", "Code", "codice", "CODICE", "Codice", + "number", "NUMBER", "Number", "numero", "NUMERO", "Numero", + "index", "INDEX", "Index", "indice", "INDICE", "Indice" + }; + + // Cerca colonne che potrebbero essere chiavi primarie + string? detectedKey = null; + + // 1. Cerca esattamente "id", "ID", "Id" + detectedKey = columns.FirstOrDefault(c => + c.Equals("id", StringComparison.OrdinalIgnoreCase) || + c.Equals("ID", StringComparison.Ordinal) || + c.Equals("Id", StringComparison.Ordinal) || + c.Equals("codice", StringComparison.OrdinalIgnoreCase)); + + // 2. Se non trovato, cerca colonne che terminano con pattern comuni + if (detectedKey == null) + { + foreach (var pattern in keyPatterns.Take(6)) // Solo i primi pattern più comuni + { + detectedKey = columns.FirstOrDefault(c => + c.EndsWith(pattern, StringComparison.OrdinalIgnoreCase)); + if (detectedKey != null) break; + } + } + + // 3. Se non trovato, cerca colonne che contengono pattern di chiave + if (detectedKey == null) + { + foreach (var pattern in keyPatterns) + { + detectedKey = columns.FirstOrDefault(c => + c.Contains(pattern, StringComparison.OrdinalIgnoreCase)); + if (detectedKey != null) break; + } + } + + // 4. Auto-seleziona se trovato + if (!string.IsNullOrEmpty(detectedKey)) + { + sourceKeyField = detectedKey; + suggestedPrimaryKey = detectedKey; + requiresManualKeySelection = false; + + Logger.LogInformation("Chiave auto-selezionata per file: {KeyField}", detectedKey); + } + else + { + Logger.LogInformation("Nessuna chiave rilevabile automaticamente per file, selezione manuale richiesta"); + } + } + catch (Exception ex) + { + Logger.LogError(ex, "Errore nell'auto-selezione della chiave per file"); + sourceKeyField = ""; + suggestedPrimaryKey = ""; + requiresManualKeySelection = true; + } + } }