diff --git a/roles/database/files/sql/idempotent/fworch-texts.sql b/roles/database/files/sql/idempotent/fworch-texts.sql index b40766de2..a08b6c213 100644 --- a/roles/database/files/sql/idempotent/fworch-texts.sql +++ b/roles/database/files/sql/idempotent/fworch-texts.sql @@ -2666,6 +2666,16 @@ INSERT INTO txt VALUES ('edit_notification', 'German', 'Benachrichtigung bea INSERT INTO txt VALUES ('edit_notification', 'English', 'Edit Notification'); INSERT INTO txt VALUES ('delete_notification', 'German', 'Benachrichtigung löschen'); INSERT INTO txt VALUES ('delete_notification', 'English', 'Delete Notification'); +INSERT INTO txt VALUES ('color_scheme', 'German', 'Farbschema'); +INSERT INTO txt VALUES ('color_scheme', 'English', 'Color Scheme'); +INSERT INTO txt VALUES ('color_scheme_blue', 'German', 'Blaues Farbschema'); +INSERT INTO txt VALUES ('color_scheme_blue', 'English', 'Blue Color Scheme'); +INSERT INTO txt VALUES ('color_scheme_green', 'German', 'Grünes Farbschema'); +INSERT INTO txt VALUES ('color_scheme_green', 'English', 'Green Color Scheme'); +INSERT INTO txt VALUES ('color_scheme_red', 'German', 'Rotes Farbschema'); +INSERT INTO txt VALUES ('color_scheme_red', 'English', 'Red Color Scheme'); +INSERT INTO txt VALUES ('color_scheme_purple', 'German', 'Violettes Farbschema'); +INSERT INTO txt VALUES ('color_scheme_purple', 'English', 'Purple Color Scheme'); -- monitoring INSERT INTO txt VALUES ('open_alerts', 'German', 'Offene Alarme'); diff --git a/roles/importer/files/importer/model_controllers/fwconfig_import_rule.py b/roles/importer/files/importer/model_controllers/fwconfig_import_rule.py index 3c2cd41d5..346185377 100644 --- a/roles/importer/files/importer/model_controllers/fwconfig_import_rule.py +++ b/roles/importer/files/importer/model_controllers/fwconfig_import_rule.py @@ -2,6 +2,8 @@ import traceback from difflib import ndiff import json +from typing import Any +from typing_extensions import Literal import fwo_globals import fwo_const @@ -36,7 +38,7 @@ class RefType(Enum): # this class is used for importing rules and rule refs into the FWO API class FwConfigImportRule(): - _changed_rule_id_map: dict + _changed_rule_id_map: dict[str, list[int]] uid2id_mapper: Uid2IdMapper group_flats_mapper: GroupFlatsMapper prev_group_flats_mapper: GroupFlatsMapper @@ -55,16 +57,16 @@ def __init__(self): self.prev_group_flats_mapper = service_provider.get_service(Services.PREV_GROUP_FLATS_MAPPER, self.import_details.ImportId) self.rule_order_service = service_provider.get_service(Services.RULE_ORDER_SERVICE, self.import_details.ImportId) - def updateRulebaseDiffs(self, prevConfig: FwConfigNormalized): + def updateRulebaseDiffs(self, prevConfig: FwConfigNormalized) -> list[int]: logger = getFwoLogger(debug_level=self.import_details.DebugLevel) # calculate rule diffs - changedRuleUids = {} - ruleUidsInBoth = {} - previousRulebaseUids = [] - currentRulebaseUids = [] - new_hit_information = [] + changedRuleUids: dict[str, list[str]] = {} + ruleUidsInBoth: dict[str, list[str]] = {} + previousRulebaseUids: list[str] = [] + currentRulebaseUids: list[str] = [] + new_hit_information: list[dict[str, Any]] = [] rule_order_diffs: dict[str, dict[str, list[str]]] = self.rule_order_service.update_rule_order_diffs(self.import_details.DebugLevel) @@ -103,7 +105,7 @@ def updateRulebaseDiffs(self, prevConfig: FwConfigNormalized): newRulebases = self.getRules(rule_order_diffs["new_rule_uids"]) # update rule_metadata before adding rules - num_added_metadata_rules, new_rule_metadata_ids = self.addNewRuleMetadata(newRulebases) + _, _ = self.addNewRuleMetadata(newRulebases) _, _ = self.update_rule_metadata_last_hit(new_hit_information) # # now update the database with all rule diffs @@ -113,10 +115,10 @@ def updateRulebaseDiffs(self, prevConfig: FwConfigNormalized): num_changed_rules, old_rule_ids, updated_rule_ids = self.create_new_rule_version(changedRuleUids) self.uid2id_mapper.add_rule_mappings(new_rule_ids + updated_rule_ids) - num_new_refs = self.add_new_refs(prevConfig) + _ = self.add_new_refs(prevConfig) num_deleted_rules, removed_rule_ids = self.markRulesRemoved(rule_order_diffs["deleted_rule_uids"], changedRuleUids) - num_removed_refs = self.remove_outdated_refs(prevConfig) + _ = self.remove_outdated_refs(prevConfig) _, num_moved_rules, _ = self.verify_rules_moved(changedRuleUids) @@ -147,7 +149,7 @@ def _create_removed_rules_map(self, removed_rule_ids: list[int]): - def _collect_uncaught_moves(self, movedRuleUids, changedRuleUids): + def _collect_uncaught_moves(self, movedRuleUids: dict[str, list[str]], changedRuleUids: dict[str, list[str]]): for rulebaseId in movedRuleUids: for ruleUid in movedRuleUids[rulebaseId]: if ruleUid not in changedRuleUids.get(rulebaseId, []): @@ -155,19 +157,19 @@ def _collect_uncaught_moves(self, movedRuleUids, changedRuleUids): changedRuleUids[rulebaseId] = [] changedRuleUids[rulebaseId].append(ruleUid) - def collect_last_hit_changes(self, rule_uid, current_rulebase, previous_rulebase, new_hit_information): + def collect_last_hit_changes(self, rule_uid: str, current_rulebase: Rulebase, previous_rulebase: Rulebase, new_hit_information: list[dict[str, Any]]): if self.last_hit_changed(current_rulebase.Rules[rule_uid], previous_rulebase.Rules[rule_uid]): self.append_rule_metadata_last_hit(new_hit_information, current_rulebase.Rules[rule_uid], self.import_details.MgmDetails.CurrentMgmId) @staticmethod - def collect_changed_rules(rule_uid, current_rulebase, previous_rulebase, rulebase_id, changed_rule_uids): + def collect_changed_rules(rule_uid: str, current_rulebase: Rulebase, previous_rulebase: Rulebase, rulebase_id: str, changed_rule_uids: dict[str, list[str]]): if current_rulebase.Rules[rule_uid] != previous_rulebase.Rules[rule_uid]: changed_rule_uids[rulebase_id].append(rule_uid) @staticmethod - def preserve_rule_num_numeric(current_rulebase, previous_rulebase, rule_uid): + def preserve_rule_num_numeric(current_rulebase: Rulebase, previous_rulebase: Rulebase, rule_uid: str): if current_rulebase.Rules[rule_uid].rule_num_numeric == 0: current_rulebase.Rules[rule_uid].rule_num_numeric = previous_rulebase.Rules[rule_uid].rule_num_numeric @@ -459,8 +461,8 @@ def getRulesByIdWithRefUids(self, ruleIds: list[int]) -> tuple[int, int, list[Ru raise - def getRules(self, ruleUids) -> list[Rulebase]: - rulebases = [] + def getRules(self, ruleUids: dict[str, list[str]]) -> list[Rulebase]: + rulebases: list[Rulebase] = [] for rb in self.normalized_config.rulebases: if rb.uid in ruleUids: filtered_rules = {uid: rule for uid, rule in rb.Rules.items() if uid in ruleUids[rb.uid]} @@ -530,7 +532,7 @@ def addNewRuleMetadata(self, newRules: list[Rulebase]): } """ - addNewRuleMetadata: list[dict] = self.PrepareNewRuleMetadata(newRules) + addNewRuleMetadata: list[dict[str, Any]] = self.PrepareNewRuleMetadata(newRules) query_variables = { 'ruleMetadata': addNewRuleMetadata } if fwo_globals.debug_level>9: @@ -554,7 +556,7 @@ def addNewRuleMetadata(self, newRules: list[Rulebase]): # collect new last hit information @staticmethod - def append_rule_metadata_last_hit (new_hit_information: list[dict], rule: RuleNormalized, mgm_id: int): + def append_rule_metadata_last_hit (new_hit_information: list[dict[str, Any]], rule: RuleNormalized, mgm_id: int): if new_hit_information is None: new_hit_information = [] new_hit_information.append({ @@ -564,7 +566,7 @@ def append_rule_metadata_last_hit (new_hit_information: list[dict], rule: RuleNo # adds new rule_metadatum to the database - def update_rule_metadata_last_hit (self, new_hit_information: list[dict]): + def update_rule_metadata_last_hit (self, new_hit_information: list[dict[str, Any]]): logger = getFwoLogger() errors = 0 changes = 0 @@ -586,11 +588,10 @@ def update_rule_metadata_last_hit (self, new_hit_information: list[dict]): return errors, changes - def addRulebasesWithoutRules(self, newRules: list[Rulebase]): + def addRulebasesWithoutRules(self, newRules: list[Rulebase]) -> tuple[int, list[str]]: logger = getFwoLogger() changes = 0 - newRulebaseIds = [] - newRuleIds = [] + newRulebaseIds: list[str] = [] addRulebasesWithoutRulesMutation = """mutation upsertRulebaseWithoutRules($rulebases: [rulebase_insert_input!]!) { insert_rulebase( @@ -632,10 +633,10 @@ def addRulebasesWithoutRules(self, newRules: list[Rulebase]): # as we cannot add the rules for all rulebases in one go (using a constraint from the rule table), # we need to add them per rulebase separately - def addRulesWithinRulebases(self, newRules: list[Rulebase]): + def addRulesWithinRulebases(self, newRules: list[Rulebase]) -> tuple[Any | Literal[0], list[str]]: logger = getFwoLogger() changes = 0 - newRuleIds = [] + newRuleIds: list[str] = [] # TODO: need to update the RulebaseMap here?! newRulesForImport: list[RulebaseForImport] = self.PrepareNewRulebases(newRules) @@ -666,15 +667,15 @@ def addRulesWithinRulebases(self, newRules: list[Rulebase]): # adds only new rules to the database # unchanged or deleted rules are not touched here - def addNewRules(self, newRulebases: list[Rulebase]): - changes1, newRulebaseIds = self.addRulebasesWithoutRules(newRulebases) + def addNewRules(self, newRulebases: list[Rulebase]) -> tuple[int, list[dict[str, Any]]]: + changes1, _ = self.addRulebasesWithoutRules(newRulebases) changes2, newRuleIds = self.addRulesWithinRulebases(newRulebases) return changes1+changes2, newRuleIds - def PrepareNewRuleMetadata(self, newRules: list[Rulebase]) -> list[dict]: - newRuleMetadata: list[dict] = [] + def PrepareNewRuleMetadata(self, newRules: list[Rulebase]) -> list[dict[str, Any]]: + newRuleMetadata: list[dict[str, Any]] = [] now = datetime.now().strftime("%Y-%m-%d %H:%M:%S") for rulebase in newRules: @@ -710,10 +711,10 @@ def PrepareNewRulebases(self, newRules: list[Rulebase], includeRules: bool = Tru # add rules for each rulebase return newRulesForImport - def markRulesRemoved(self, removedRuleUids, changedRuleUids): + def markRulesRemoved(self, removedRuleUids: dict[str, list[str]], changedRuleUids: dict[str, list[str]]) -> tuple[int, list[int]]: logger = getFwoLogger() changes = 0 - collectedRemovedRuleIds = [] + collectedRemovedRuleIds: list[str] = [] # TODO: make sure not to mark new (changed) rules as removed (order of calls!) @@ -728,7 +729,7 @@ def markRulesRemoved(self, removedRuleUids, changedRuleUids): } } """ - query_variables = { 'importId': self.import_details.ImportId, + query_variables: dict[str, Any] = { 'importId': self.import_details.ImportId, 'mgmId': self.import_details.MgmDetails.CurrentMgmId, 'uids': list(removedRuleUids[rbName]) } @@ -746,7 +747,7 @@ def markRulesRemoved(self, removedRuleUids, changedRuleUids): return changes, collectedRemovedRuleIds - def create_new_rule_version(self, rule_uids): + def create_new_rule_version(self, rule_uids: dict[str, list[str]]) -> tuple[int, list[int], list[dict[str, Any]]]: logger = getFwoLogger() self._changed_rule_id_map = {} @@ -793,7 +794,7 @@ def create_new_rule_version(self, rule_uids): } """ - import_rules: list = [] + import_rules: list[dict[str, Any]] = [] for rulebase_uid in list(rule_uids.keys()): @@ -924,7 +925,7 @@ def update_rule_enforced_on_gateway_after_move(self, insert_rules_return, update logger.exception(f"failed to move rules: {str(traceback.format_exc())}") return 1, 0, [] - def verify_rules_moved(self, changed_rule_uids): + def verify_rules_moved(self, changed_rule_uids: dict[str, list[str]]) -> tuple[int, int, list[str]]: error_count_move = 0 number_of_moved_rules = 0 @@ -1172,7 +1173,7 @@ def prepare_single_rule_for_import(self, rule: RuleNormalized, importDetails: Im return rule_for_import - def write_changelog_rules(self, added_rules_ids, removed_rules_ids): + def write_changelog_rules(self, added_rules_ids: list[str], removed_rules_ids: list[str]) -> int: logger = getFwoLogger() errors = 0 @@ -1197,7 +1198,7 @@ def write_changelog_rules(self, added_rules_ids, removed_rules_ids): return errors - def prepare_changelog_rules_insert_objects(self, added_rules_ids, removed_rules_ids): + def prepare_changelog_rules_insert_objects(self, added_rules_ids: list[str], removed_rules_ids: dict[str, list[str]]) -> list[dict[str, Any]]: """ Creates two lists of insert arguments for the changelog_rules db table, one for new rules, one for deleted. """ diff --git a/roles/lib/files/FWO.Config.Api/Data/ColorScheme.cs b/roles/lib/files/FWO.Config.Api/Data/ColorScheme.cs new file mode 100644 index 000000000..cfe59593b --- /dev/null +++ b/roles/lib/files/FWO.Config.Api/Data/ColorScheme.cs @@ -0,0 +1,44 @@ +using System.Text.Json.Serialization; +using Newtonsoft.Json; + +namespace FWO.Config.Api.Data +{ + /// + /// a list of all available ColorSchemes + /// + public class ColorScheme + { + [JsonProperty("name"), JsonPropertyName("name")] + public string Name { get; set; } = ""; + + [JsonProperty("isDefault"), JsonPropertyName("isDefault")] + public bool IsDefault { get; set; } = false; + + [JsonProperty("hex"), JsonPropertyName("hex")] + public string Hex { get; set; } = ""; + + [JsonProperty("hex2"), JsonPropertyName("hex2")] + public string Hex2 { get; set; } = ""; + + [JsonProperty("textHex"), JsonPropertyName("textHex")] + public string TextHex { get; set; } = ""; + + + public static List AvailableSchemes { get; } = new List + { + new ColorScheme { Name = "color_scheme_blue", IsDefault = true, Hex = "#054B8C", Hex2 = "#03335E", TextHex = "#2FA5ED" }, + new ColorScheme { Name = "color_scheme_green", Hex = "#1c8c05ff" , Hex2 = "#155e03ff", TextHex = "#b4ed2fff" }, + new ColorScheme { Name = "color_scheme_red", Hex = "#8c0505ff", Hex2 = "#5e0303ff", TextHex = "#ed2f2fff" }, + new ColorScheme { Name = "color_scheme_purple", Hex = "#5b058cff", Hex2 = "#3a035eff", TextHex = "#a12fedff" } + // Add more schemes as needed + }; + + public static ColorScheme GetSchemeByName(string name) + { + return AvailableSchemes.FirstOrDefault(s => s.Name == name) ?? AvailableSchemes.First(s => s.IsDefault); + } + } + +} + + diff --git a/roles/lib/files/FWO.Config.Api/Data/ConfigData.cs b/roles/lib/files/FWO.Config.Api/Data/ConfigData.cs index b8778f7f5..d2a4aad86 100644 --- a/roles/lib/files/FWO.Config.Api/Data/ConfigData.cs +++ b/roles/lib/files/FWO.Config.Api/Data/ConfigData.cs @@ -451,6 +451,9 @@ public class ConfigData : ICloneable [JsonProperty("debugConfig"), JsonPropertyName("debugConfig")] public string DebugConfig { get; set; } = ""; + [JsonProperty("colorScheme"), JsonPropertyName("colorScheme"), UserConfigData] + public string ColorScheme { get; set; } = "color_scheme_blue"; + [JsonProperty("autoCalculateInternetZone"), JsonPropertyName("autoCalculateInternetZone")] public bool AutoCalculateInternetZone { get; set; } = true; diff --git a/roles/ui/files/FWO.UI/Pages/Settings/SettingsDefaults.razor b/roles/ui/files/FWO.UI/Pages/Settings/SettingsDefaults.razor index b211725e3..d123fc84c 100644 --- a/roles/ui/files/FWO.UI/Pages/Settings/SettingsDefaults.razor +++ b/roles/ui/files/FWO.UI/Pages/Settings/SettingsDefaults.razor @@ -77,6 +77,16 @@ +
+ +
+ + + @(userConfig.GetText(colorScheme.Name)) + + +
+

@@ -223,6 +233,7 @@ else private ConfigData? configData; private Language selectedLanguage = new Language(); + private ColorScheme selectedColorScheme = new ColorScheme(); private DateTime autoDiscStartDate = DateTime.Today; private DateTime autoDiscStartTime = DateTime.Now.AddSeconds(-DateTime.Now.Second); private List availableModules { get; set; } = []; @@ -239,6 +250,7 @@ else configData = await globalConfig.GetEditableConfig(); selectedLanguage = globalConfig.UiLanguages.FirstOrDefault(l => l.Name == configData.DefaultLanguage) ?? new Language(); + selectedColorScheme = ColorScheme.GetSchemeByName(configData.ColorScheme); autoDiscStartDate = autoDiscStartTime = configData.AutoDiscoverStartAt; availableModules = JsonSerializer.Deserialize>(string.IsNullOrEmpty(configData.AvailableModules) ? ModuleGroups.AllModulesNumList() : configData.AvailableModules) ?? throw new JsonException("Config data could not be parsed."); modulesVisibleDict = []; @@ -261,6 +273,8 @@ else if(configData != null) { configData.DefaultLanguage = selectedLanguage.Name; + configData.ColorScheme = selectedColorScheme.Name; + StateHasChanged(); configData.AutoDiscoverStartAt = autoDiscStartDate.Date.Add(autoDiscStartTime.TimeOfDay); availableModules = []; foreach(Module module in modulesVisibleDict.Keys) diff --git a/roles/ui/files/FWO.UI/Shared/NavigationMenu.razor b/roles/ui/files/FWO.UI/Shared/NavigationMenu.razor index e81c90192..c6cd6c7d8 100644 --- a/roles/ui/files/FWO.UI/Shared/NavigationMenu.razor +++ b/roles/ui/files/FWO.UI/Shared/NavigationMenu.razor @@ -9,7 +9,9 @@ @if (InitComplete) {