namespace SQLInsight.Core.Configuration; /// /// Which databases on an instance are monitored, as chosen in SQLInsight Web (Opsætning → Overvågede servere). The /// system databases (master, model, msdb, tempdb) are always monitored: backups of master and msdb and the state of /// tempdb concern the whole instance. A database nobody has decided on yet (new since the last discovery) follows /// . /// public sealed class DatabaseSelection { private static readonly HashSet SystemDatabases = new(["master", "model", "msdb", "tempdb"], StringComparer.OrdinalIgnoreCase); private readonly HashSet _monitored; private readonly HashSet _notMonitored; private readonly HashSet _dynamicsAxToHub; /// Every database, and no Dynamics AX findings to the hub: what 1.2 and earlier did. public static readonly DatabaseSelection All = new(true, [], [], []); public DatabaseSelection(bool monitorNew, IEnumerable monitored, IEnumerable notMonitored, IEnumerable dynamicsAxToHub) { ArgumentNullException.ThrowIfNull(monitored); ArgumentNullException.ThrowIfNull(notMonitored); ArgumentNullException.ThrowIfNull(dynamicsAxToHub); MonitorNew = monitorNew; _monitored = new HashSet(monitored, StringComparer.OrdinalIgnoreCase); _notMonitored = new HashSet(notMonitored, StringComparer.OrdinalIgnoreCase); _notMonitored.ExceptWith(_monitored); _dynamicsAxToHub = new HashSet(dynamicsAxToHub, StringComparer.OrdinalIgnoreCase); } /// Databases not yet decided on (new on the instance) are monitored. public bool MonitorNew { get; } /// Nothing is left out: every database is monitored. public bool IsEverything => MonitorNew && _notMonitored.Count == 0; public static bool IsSystemDatabase(string database) => SystemDatabases.Contains(database); /// Whether the database-specific checks run in . public bool Includes(string database) { ArgumentNullException.ThrowIfNull(database); if (IsSystemDatabase(database) || _monitored.Contains(database)) { return true; } return !_notMonitored.Contains(database) && MonitorNew; } /// /// Whether findings about Dynamics AX in may be sent to SQLInsight Hub. Off unless the /// customer turned it on for that database. /// public bool SendsDynamicsAxToHub(string? database) => database is not null && _dynamicsAxToHub.Contains(database) && Includes(database); /// At least one database sends Dynamics AX findings to the hub. public bool AnyDynamicsAxToHub => _dynamicsAxToHub.Any(Includes); /// Keeps the databases in that are monitored. public List Filter(IEnumerable names) => names.Where(Includes).ToList(); } /// /// Dynamics AX findings and SQLInsight Hub: they stay in the customer's network unless sending is turned on for the /// database (default off). /// public static class DynamicsAxFindings { /// The community AX rules (rules/community/dynamics-ax.json). public const string RulePrefix = "COM-AX-"; /// The built-in AX rules (1.4: batch jobs, number sequences, RecId, AX users behind blocking). public const string BuiltInRulePrefix = "SQLI-AX-"; private const string DatabaseSubject = "database: "; /// Separates the database from the rest of an AX finding's subject: database: AX30 · batch: 4711. public const string SubjectSeparator = " · "; public static bool IsDynamicsAxRule(string ruleId) => ruleId?.StartsWith(RulePrefix, StringComparison.OrdinalIgnoreCase) == true || ruleId?.StartsWith(BuiltInRulePrefix, StringComparison.OrdinalIgnoreCase) == true; /// The subject of an AX finding about in . public static string Subject(string database, string? detail = null) => detail is null ? DatabaseSubject + database : DatabaseSubject + database + SubjectSeparator + detail; /// The database a finding is about, from its subject (database: AX30 or database: AX30 · …), or null. public static string? DatabaseOf(string? subject) { if (subject is null || !subject.StartsWith(DatabaseSubject, StringComparison.OrdinalIgnoreCase) || subject.Length <= DatabaseSubject.Length) { return null; } var rest = subject[DatabaseSubject.Length..]; var separator = rest.IndexOf(SubjectSeparator, StringComparison.Ordinal); return separator > 0 ? rest[..separator] : rest; } }