diff --git a/Docs/Reading Encrypted Settings.md b/Docs/Reading Encrypted Settings.md index f7db67e..66e5f73 100644 --- a/Docs/Reading Encrypted Settings.md +++ b/Docs/Reading Encrypted Settings.md @@ -8,6 +8,6 @@ If you ever find yourself in need of reading the encrypted settings, open up `Py from resources.config import settings_core settings = settings_core() # Read encrypted setting -decrypted_setting = settings.read_encrypted_setting("CATEGORY","SETTING") +decrypted_setting = settings.get_setting_value("CATEGORY","SETTING") print(decrypted_setting) ``` diff --git a/resources/accounts.py b/resources/accounts.py index a644561..f0b5387 100755 --- a/resources/accounts.py +++ b/resources/accounts.py @@ -68,7 +68,7 @@ def load_data(self): data_loaded = False ## Load Account Data from Settings - accounts = string_to_list_of_dictionaries(settings.read_encrypted_setting("accounts", "media_accounts")) + accounts = string_to_list_of_dictionaries(settings.get_setting_value("accounts", "media_accounts")) for account in accounts: if account["name"] == self.data['name']: diff --git a/resources/config.py b/resources/config.py index 1d0f94b..36cead0 100755 --- a/resources/config.py +++ b/resources/config.py @@ -42,7 +42,6 @@ - # _____ _ # / __ \ | # | / \/ | __ _ ___ ___ ___ ___ @@ -83,7 +82,7 @@ def __init__(self): ##### ENCRYPTION - self.key_location = cfg.get("encryption","key_location") + self.key_location = cfg.get("encryption","hidden_key_location") self.crypt = None ## Has encryption been setup? @@ -113,19 +112,23 @@ def __init__(self): ##### ACCOUNTS media_accounts_temp = cfg.get("accounts","media_accounts") if media_accounts_temp != "None": - self.media_accounts = string_to_list_of_dictionaries(self.read_encrypted_setting("accounts", "media_accounts")) + self.media_accounts = string_to_list_of_dictionaries(self.get_setting_value("accounts", "media_accounts")) else: self.media_accounts = None ##### S3 CREDENTIALS - self.s3_access = self.read_encrypted_setting("accounts", "s3_access") - self.s3_secret = self.read_encrypted_setting("accounts", "s3_secret") - self.s3_endpoint = self.read_encrypted_setting("accounts", "s3_endpoint") - self.s3_bucket = self.read_encrypted_setting("accounts", "s3_bucket") + self.s3_access = self.get_setting_value("accounts", "hidden_s3_access") + self.s3_secret = self.get_setting_value("accounts", "hidden_s3_secret") + self.s3_endpoint = self.get_setting_value("accounts", "hidden_s3_endpoint") + self.s3_bucket = self.get_setting_value("accounts", "hidden_s3_bucket") self.storage = Storage(self.s3_access, self.s3_secret, self.s3_endpoint, self.s3_bucket) + + ##### Global Mention IDs + self.global_mention_ids = self.get_setting_value("posting", "global_mention_ids") + else: self.media_accounts = None self.storage = None @@ -137,6 +140,7 @@ def __init__(self): self.no_posts_title = cfg.get("app","no_posts_title") self.no_posts_description = cfg.get("app","no_posts_description") self.post_not_scheduled_for_reason_time_in_past = cfg.get("app","post_not_scheduled_for_reason_time_in_past") + self.value_redaction_message = cfg.get("app", "value_redaction_message") ##### PERFORMANCE @@ -158,11 +162,9 @@ def reload_config(self): cfg.read(configpath) - def read_encrypted_setting(self, category, setting): + def read_encrypted_setting(self, setting_value): try: - encrypted_setting = self.get_setting_value(category, setting) - setting = self.crypt.decrypt(encrypted_setting.encode()).decode() - return setting + return self.crypt.decrypt(setting_value.encode()).decode() except Exception as e: print(e) return None @@ -190,7 +192,14 @@ def get_all_settings_in_category(self,category): ##### GET SETTING VALUE def get_setting_value(self,category,setting): - return cfg.get(category,setting) + + value = cfg.get(category,setting) + + ## Decrypt if encrypted + if list(value)[-1] == "=": + value = self.read_encrypted_setting(value) + + return value ##### SET SETTING VALUE @@ -201,6 +210,7 @@ def set_setting_value(self,category,setting,value): self.reload_config() + ##### CREATE NEW SETTING def create_new_setting(self,category,setting,value): cfg.add_section(category) diff --git a/settings_template.cfg b/settings_template.cfg index e9a7f05..08fb4d4 100644 --- a/settings_template.cfg +++ b/settings_template.cfg @@ -1,38 +1,100 @@ +########## APPLICATION +##### [accounts] +## Display Names +display_name_media_accounts = Media Accounts +display_name_supported_media_platforms = Supported Platforms +display_name_hidden_s3_access = Access +display_name_hidden_s3_secret = Secret +display_name_hidden_s3_endpoint = Endpoint +display_name_hidden_s3_bucket = Bucket + +## Values media_accounts = None supported_media_platforms = Discord,Twitter,Reddit,Facebook,Instagram,Telegram,Signal,RSS -s3_access = None -s3_secret = None -s3_endpoint = None -s3_bucket = None +hidden_s3_access = None +hidden_s3_secret = None +hidden_s3_endpoint = None +hidden_s3_bucket = None [posting] +## Display Names +display_name_local_mention_tag_start = Local Mention Tag Start +display_name_local_mention_tag_end = Local Mention Tag End +display_name_global_mention_ids = Global Mention IDs +display_name_utc_timezones = UTC Timezones +display_name_default_timezone = Default Timezone + +## Values +local_mention_tag_start = None +local_mention_tag_end = None +global_mention_ids = None utc_timezones = +1400,+1300,+1200,+1100,+1000,+0900,+0800,+0700,+0600,+0500,+0400,+0300,+0200,+0100,+0000,-0100,-0200,-0300,-0400,-0500,-0600,-0700,-0800,-0900,-1000,-1100,-1200 default_timezone = +0000 [encryption] -key_location = /path/to/key.pem +## Display Names +display_name_hidden_key_location = Key Location +display_name_block_size = Block Size + +## Values +hidden_key_location = /path/to/key.pem block_size = None [app] +## Display Names +display_name_no_posts_title = Warning | Title - No Posts Found +display_name_no_posts_description = Warning | Description - No Posts Found +display_name_post_not_scheduled_for_reason_time_in_past = Warning | Attempt to Schedule Post in the Past +display_name_value_redaction_message = Info | Hidden Value Redacted Message + +## Values no_posts_title = No Pending Posts no_posts_description = No posts here yet! post_not_scheduled_for_reason_time_in_past = WARNING. Your post could not be scheduled. Please pick a date in the future above. +value_redaction_message = REDACTED [storage] +## Display Names +display_name_posts_file = Posts File Name +display_name_scheduled_posts_file = Scheduled Posts File Name +display_name_uploaded_media_dir = Uploaded Media Directory + +## Values posts_file = published_posts.dat scheduled_posts_file = scheduled_posts.dat uploaded_media_dir = uploaded_media [media] +## Display Names +display_name_supported_image_types = Supported Image Types +display_name_supported_video_types = Supported Video Types +display_name_supported_audio_types = Supported Audio Types + +## Values supported_image_types = jpg,jpeg,png,gif supported_video_types = mp4,mov,avi,wmv,flv,mpg,mpeg supported_audio_types = mp3,wav,ogg [performance] +## Display Names +display_name_posts_cache_time = Posts Cache Time +display_name_page_cache_time = Page Cache time + +## Values posts_cache_time = 3600 page_cache_time = 3600 -# Server settings need to be set on the device running the server. Changing them here will not affect the server unless you're running it locally. + +########## SERVER +##### + +## Server settings need to be set on the device running the server. +## Changing them here will not affect the server unless you're running it locally. + [server] +## Display Names +display_name_processing_delay_in_seconds = Processing Delay in Seconds + +## Values processing_delay_in_seconds = 60 \ No newline at end of file diff --git a/widgets/settings_form.py b/widgets/settings_form.py index 86544c8..63b1e53 100755 --- a/widgets/settings_form.py +++ b/widgets/settings_form.py @@ -6,47 +6,66 @@ settings = settings_core() +# ___ _ _ _ _ +# / _ \ | (_) | | (_) +# / /_\ \_ __ _ __ | |_ ___ __ _| |_ _ ___ _ __ +# | _ | '_ \| '_ \| | |/ __/ _` | __| |/ _ \| '_ \ +# | | | | |_) | |_) | | | (_| (_| | |_| | (_) | | | | +# \_| |_/ .__/| .__/|_|_|\___\__,_|\__|_|\___/|_| |_| +# | | | | +# |_| |_| +# ----------------------------------------------------------------------- + +# Settings Form Widget + + +########## APPLICATION +##### def app(): - ##### LOAD SETTINGS FILE AND FIND SECTIONS - settings_file = open(settings.current_path + "settings.cfg", "r") + ## Initialize sections = settings.get_all_setting_categories() setting_buttons_dict = {} new_account = {} + setting_display_names = {} - ##### SETTINGS FORM + ## Main Settings Form with st.form("Settings"): - ##### SECTIONS + ## Create Sections from Categories for section in sections: - - - ##### TITLE if not section == "server": + + ## Create Section st.markdown("#### " + section.capitalize()) - settings_in_category = settings.get_all_settings_in_category(section) + ## Log Settings + settings_in_category = settings.get_all_settings_in_category(section) - ##### SETTINGS BUTTONS + ## Create Settings Buttons for setting in settings_in_category: - ##### REGULAR SETTINGS + ########## DISPLAY NAMES + ##### + if setting.lower().startswith("display_name_"): - if setting != "media_accounts" and setting != "s3_access" and setting != "s3_secret" and setting != "s3_endpoint" and setting != "s3_bucket": ## this is getting ridiculous need a better solution. - ## Create a button for each setting and add it to a dictionairy - setting_buttons_dict[setting] = st.text_input(setting, settings.get_setting_value(section, setting)) + ## Get Associated Setting + setting_name = setting.replace("display_name_", "") + ## Log Display Name + setting_display_names[setting_name] = [settings.get_setting_value(section, setting), section] - ##### MEDIA ACCOUNTS - elif setting == "media_accounts": - media_accounts = settings.media_accounts #settings.get_setting_value(section, setting) - media_account_button_list = [] + ########## MEDIA ACCOUNTS + ##### + elif setting == "media_accounts": + + ## Initialize + media_accounts = settings.media_accounts + media_account_button_list = [] if media_accounts != None: - - st.markdown("**Media accounts**") @@ -82,16 +101,15 @@ def app(): if str(platform) == str(media_account_media_platform): media_selected_index = index - # create 3 options in a select box + ## Create 3 options in a select box media_account_button_dict['media_platform'] = st.selectbox("Media platform", media_platforms_df,index = media_selected_index, key=media_account["name"]) media_account_button_dict['name'] = media_account_name media_account_button_list.append(media_account_button_dict) - else: st.text("No media accounts added") - ##### ADD NEW MEDIA ACCOUNT + ## Add New Media Account with st.expander("Register New Account"): new_account["name"] = st.text_input("Unique name", placeholder="unique-name", key="new_account_name") new_account["display_name"] = st.text_input("Display name", placeholder="Display Name | Work",key="new_account_display_name") @@ -109,86 +127,123 @@ def app(): # create 3 options in a select box new_account['media_platform'] = st.selectbox("Media platform", media_platforms_df,index = media_selected_index, key=new_account["name"]) - - ##### S3 CREDENTIALS - elif setting == "s3_access": - s3_access = st.text_input(f"Access", value=settings.s3_access, key='s3_access_setting', type='password') - elif setting == "s3_secret": - s3_secret = st.text_input(f"Secret", value=settings.s3_secret, key='s3_secret_setting', type='password') - elif setting == "s3_endpoint": - s3_endpoint = st.text_input(f"Endpoint", value=settings.s3_endpoint, key='s3_endpoint_setting', type='password') - elif setting == "s3_bucket": - s3_bucket = st.text_input(f"Bucket", value=settings.s3_bucket, key='s3_bucket_setting', type='password') + + + # ########## GLOBAL MENTION IDs + # ##### + # elif setting == "global_mention_ids": + + # ## Needs to be a dropdown similar to accounts. The dropdown will have the global user friendly name (the one used in posts & such) + # ## Below it will have a list of inputs. Platform Name | Platform ID + + # setting_buttons_dict[setting] = [st.text_input(f"Global Mention IDs", value=settings.global_mention_ids, key='global_mention_ids', type='password')] + + + + ########## REGULAR SETTINGS + ##### + else: - + ## Define Setting Type (Default/Hidden) + setting_type = "password" if setting.lower().startswith("hidden_") else "default" + + ## Retrieve Display Name + display_name = setting_display_names[setting][0] if setting in setting_display_names.keys() else setting + + ## Retrieve Value + value = settings.get_setting_value(section, setting) + + ## Create a button & log it + the section + setting_buttons_dict[setting] = [st.text_input(label=display_name, value=value, key=setting, type=setting_type), section] + - ##### SUBMIT BUTTON + ########## SUBMIT BUTTON + ##### submitted = st.form_submit_button("Submit", section) + if submitted: - - if submitted: # if the user has submitted the form, then the settings.cfg file is updated with the new values. + ## Section Title with st.expander("Settings Saved"): - for section2 in sections: - for setting in setting_buttons_dict: + ########## UPDATE SETTINGS + ##### + for section2 in sections: - ##### CHECK IF THE SETTING IS MOST CURRENT - try: - if setting_buttons_dict[setting] != settings.get_setting_value(section2, setting): - ## Create a notice of changes - st.markdown(setting + ": " + f"`{setting_buttons_dict[setting]}`") + ####### INITIALIZE + ## Get Settings of Category + settings_in_category = settings.get_all_settings_in_category(section2) + for setting in settings_in_category: + ## Ignorees + if setting.lower().startswith("display_name_") or str(setting) == "media_accounts": + continue - ##### UPDATE THE SETTING - if str(setting) != "media_accounts": - settings.set_setting_value(section2, setting, setting_buttons_dict[setting]) + ## Initialize Valid Settings + if setting in setting_buttons_dict: + + setting_ref = setting_buttons_dict[setting] + setting_button = setting_ref[0] + setting_details = setting_ref[1] + setting_category = setting_details[0] + ## Look for changes + if str(setting_button) != str(settings.get_setting_value(section2, setting)): + + ## Redact Hidden Setting Values before showing them to user. + setting_response = settings.value_redaction_message if setting.startswith("hidden_") else setting_button - except Exception as e: - pass + ## Notify User through of changes + st.markdown(setting + ": " + f"`{setting_response}`") + + ## Update Setting Value + settings.set_setting_value(section2, setting, setting_button) - ##### UPDATE ACCOUNTS + ########## UPDATE EXISTING ACCOUNTS + ##### try: + + ## Format Button Data for button in media_account_button_list: - button_data = { - "display_name": button["display_name"], - "name": button["name"], - "key": button["key"], - "secret": button["secret"], - "access_key": button["access_key"], - "access_secret": button["access_secret"], - "media_platform": button["media_platform"], - "posting_locations": button["posting_locations"] - } + ## Initialize Button Data + button_data = {"display_name": button["display_name"],"name": button["name"],"key": button["key"],"secret": button["secret"],"access_key": button["access_key"],"access_secret": button["access_secret"],"media_platform": button["media_platform"],"posting_locations": button["posting_locations"]} - new_posting_locations = button["new_posting_locations"] - ## Take care of empty button - if len(new_posting_locations)==1 and new_posting_locations[0] == "": - new_posting_locations = [] + ########## REQUEST REMOVE ACCOUNT + ## Get Reference of Request Removal Button button_request_removal = button["request_removal"] + ## Remove Account if Requested + if button_request_removal==True: - found_difference = False + ## Create Account Object + account_to_update = Account(name=button_data["name"]) + + ## Remove Account + account_to_update.remove() + ## Logß + st.success(f"Account {button_data['name']} removed.") + ## Register Changed Settings + found_difference = False for account in settings.media_accounts: if account['name'] == button["name"]: # compare all data and break if there is a difference for key in button_data: - if button_data[key] != account[key]: + if str(button_data[key]) != str(account[key]): found_difference = True st.markdown(button['name'] + ": " + f"`Setting {key} has changed`") + ## Get Reference of New Post Location + new_posting_locations = button["new_posting_locations"] - if button_request_removal==True: - account_to_update = Account(name=button_data["name"]) - account_to_update.remove() - st.success(f"Account {button_data['name']} removed.") + ## Take care of empty button + if len(new_posting_locations)==1 and new_posting_locations[0] == "": + new_posting_locations = [] ## Look for changes in account details, update the settings file if found @@ -212,6 +267,9 @@ def app(): except Exception as e: pass + + ########## CREATE NEW ACCOUNT + ##### try: if new_account['name'] != "": account_to_add = Account(name=new_account['name'])