From 5d684ee9ef521ea5ac9e8229043d7a514ac402d7 Mon Sep 17 00:00:00 2001 From: Alexander Malzkuhn Date: Mon, 5 May 2025 13:32:04 +0200 Subject: [PATCH 1/3] =?UTF-8?q?Behandlungroutinen=20f=C3=BCr=20leeres=20Be?= =?UTF-8?q?nutzerverzeichnis=20und=20fehlende=20settings.json=20begonnen.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- admin.py | 3 ++- homepage.py | 6 +++++- main.py | 6 +++--- users.py | 13 ++++++++----- 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/admin.py b/admin.py index b3dc822..69d6925 100644 --- a/admin.py +++ b/admin.py @@ -82,8 +82,9 @@ def page_admin(): userlist = list_users() ui.markdown("Benutzer:") - time_user = ui.select(options=userlist, value=userlist[0], on_change=update_user) + time_user = ui.select(options=userlist, on_change=update_user) + time_user.value = userlist[0] user_to_select_for_start = userlist[0] current_year = datetime.datetime.now().year diff --git a/homepage.py b/homepage.py index 2aa6540..75e866e 100644 --- a/homepage.py +++ b/homepage.py @@ -18,7 +18,11 @@ def homepage(): if login_is_valid(): ui.page_title("Zeiterfassung") - current_user = user(app.storage.user["active_user"]) + try: + current_user = user(app.storage.user["active_user"]) + except: + del(app.storage.user["active_user"]) + ui.navigate.to('/') pageheader(f"Willkommen, {current_user.fullname}") today = datetime.datetime.now() diff --git a/main.py b/main.py index 1b73ccf..937b047 100644 --- a/main.py +++ b/main.py @@ -14,12 +14,12 @@ import json def main(): # Einstellungen einlesen - with open(f"{scriptpath}/settings.json") as json_file: - data = json.load(json_file) - + data = load_adminsettings() port = int(data["port"]) secret = data["secret"] + list_users() + homepage() def startup_message(): diff --git a/users.py b/users.py index 34fba12..d3fa4f4 100644 --- a/users.py +++ b/users.py @@ -375,14 +375,19 @@ class user: print(total_time) print(in_time_stamp) - return([total_time, in_time_stamp]) + return [total_time, in_time_stamp] # Benutzer auflisten def list_users(): + + if not os.path.exists(userfolder): + os.makedirs(userfolder) + users = [d for d in os.listdir(userfolder) if os.path.isdir(os.path.join(userfolder, d))] users.sort() return users + # Admineinstellungen auslesen def load_adminsettings(): # Settingsdatei einlesen @@ -390,8 +395,6 @@ def load_adminsettings(): with open(f"{scriptpath}/{usersettingsfilename}") as json_file: data = json.load(json_file) json_file.close() - return(data) + return data except: - return(-1) - - + return -1 \ No newline at end of file From f15ec8e8092e4c51c99709b4156618c4a3945a29 Mon Sep 17 00:00:00 2001 From: Alexander Malzkuhn Date: Mon, 5 May 2025 17:38:58 +0200 Subject: [PATCH 2/3] =?UTF-8?q?Routinen=20f=C3=BCr=20Standardwerte=20einge?= =?UTF-8?q?f=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- admin.py | 29 ++++++++++++++++++----------- definitions.py | 18 ++++++++++++++++++ settings.json | 9 ++------- settings.json_bak | 12 ++++++++++++ users.py | 31 +++++++++++++++++++++++++++---- 5 files changed, 77 insertions(+), 22 deletions(-) create mode 100644 settings.json_bak diff --git a/admin.py b/admin.py index 69d6925..ed59afa 100644 --- a/admin.py +++ b/admin.py @@ -68,21 +68,24 @@ def page_admin(): def update_user(): current_user = user(time_user.value) available_years = current_user.get_years() - select_year.clear() - select_year.set_options(available_years) try: - select_year.value = str(datetime.datetime.now().year) - except: - select_year.value = list(available_years)[0] - try: - select_month.value = datetime.datetime.now().month - except: - select_month.value = list(available_months)[0] + select_year.clear() + select_year.set_options(available_years) + + try: + select_year.value = str(datetime.datetime.now().year) + except: + select_year.value = list(available_years)[0] + try: + select_month.value = datetime.datetime.now().month + except: + select_month.value = list(available_months)[0] + except NameError: + pass userlist = list_users() ui.markdown("Benutzer:") - time_user = ui.select(options=userlist, on_change=update_user) time_user.value = userlist[0] user_to_select_for_start = userlist[0] @@ -148,11 +151,13 @@ def page_admin(): ui.button("Nein", on_click=dialog.close) dialog.open() - if archive_status: + if archive_status == True: with ui.row().classes('text-right col-span-6 justify-center'): ui.button("Archiviert", on_click=revoke_archive_status).classes('bg-transparent text-black') ui.separator() calendar_card.classes('bg-yellow') + else: + calendar_card.classes('bg-white') # Überschriften ui.markdown("**Datum**") ui.markdown("**Buchungen**") @@ -330,6 +335,8 @@ def page_admin(): hours_to_work = int(current_user.get_day_workhours(select_year.value, select_month.value, day)) if hours_to_work < 0: ui.space() + day_type.content="Kein Arbeitsverhältnis" + day_type.set_visibility(True) else: ui.markdown(f"{convert_seconds_to_hours(int(hours_to_work) * 3600)}").classes('text-right') if int(hours_to_work) == 0: diff --git a/definitions.py b/definitions.py index 679c89b..08f0639 100644 --- a/definitions.py +++ b/definitions.py @@ -20,6 +20,24 @@ photofilename = "photo.jpg" status_in = "eingestempelt" status_out = "ausgestempelt" +# Standardadmin Settings: + +standard_adminsettings = { "admin_user": "admin", + "admin_password": "8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918", + "port": "8090", + "secret": "ftgzuhjikg,mt5jn46uzer8sfi9okrmtzjhndfierko5zltjhdgise", + "holidays": { } + } + +# Standard User Settings: + +standard_usersettings = { + "username": "default", + "fullname": "Standardbenutzer", + "password": "37a8eec1ce19687d132fe29051dca629d164e2c4958ba141d5f4133a33f0688f", + "workhours": { } +} + # Abesenheiten absence_entries = {"U": { "name": "Urlaub", diff --git a/settings.json b/settings.json index b1a23bc..b4e0b21 100644 --- a/settings.json +++ b/settings.json @@ -1,12 +1,7 @@ { "admin_user": "admin", - "admin_password": "8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92", + "admin_password": "8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918", "port": "8090", "secret": "ftgzuhjikg,mt5jn46uzer8sfi9okrmtzjhndfierko5zltjhdgise", - "holidays": { - "2024-05-01": "Tag der Arbeit", - "2024-12-25": "1. Weihnachtsfeiertag", - "2025-01-01": "Neujahr", - "2025-05-01": "Tag der Arbeit" - } + "holidays": {} } \ No newline at end of file diff --git a/settings.json_bak b/settings.json_bak new file mode 100644 index 0000000..b1a23bc --- /dev/null +++ b/settings.json_bak @@ -0,0 +1,12 @@ +{ + "admin_user": "admin", + "admin_password": "8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92", + "port": "8090", + "secret": "ftgzuhjikg,mt5jn46uzer8sfi9okrmtzjhndfierko5zltjhdgise", + "holidays": { + "2024-05-01": "Tag der Arbeit", + "2024-12-25": "1. Weihnachtsfeiertag", + "2025-01-01": "Neujahr", + "2025-05-01": "Tag der Arbeit" + } +} \ No newline at end of file diff --git a/users.py b/users.py index d3fa4f4..41327b5 100644 --- a/users.py +++ b/users.py @@ -9,7 +9,7 @@ import json import shutil import re -from definitions import userfolder, scriptpath, usersettingsfilename, photofilename, status_in, status_out +from definitions import userfolder, scriptpath, usersettingsfilename, photofilename, status_in, status_out, standard_adminsettings, standard_usersettings # Benutzerklasse @@ -384,17 +384,40 @@ def list_users(): os.makedirs(userfolder) users = [d for d in os.listdir(userfolder) if os.path.isdir(os.path.join(userfolder, d))] + if len(users) == 0: + new_user("default") + users = [d for d in os.listdir(userfolder) if os.path.isdir(os.path.join(userfolder, d))] + users.sort() return users +def new_user(username): + if not os.path.exists(userfolder): + os.makedirs(userfolder) + if not os.path.exists(f"{userfolder}/{username}"): + os.makedirs(f"{userfolder}/{username}") + start_date_dt = datetime.datetime.now() + start_date = start_date_dt.strftime("%Y-%m-%d") + settings_to_write = standard_usersettings + settings_to_write["workhours"][start_date] = { } + for i in range(1, 8): + settings_to_write["workhours"][start_date][str(i)] = 0 + settings_to_write["workhours"][start_date]["vacation"] = 0 + with open(f"{userfolder}/{username}/{usersettingsfilename}", 'w') as json_file: + json_dict = json.dumps(standard_usersettings, indent=4) + json_file.write(json_dict) # Admineinstellungen auslesen def load_adminsettings(): # Settingsdatei einlesen + settings_filename = f"{scriptpath}/{usersettingsfilename}" + if not os.path.exists(settings_filename): + with open(settings_filename, 'w') as json_file: + json_dict = json.dumps(standard_adminsettings, indent=4) + json_file.write(json_dict) try: - with open(f"{scriptpath}/{usersettingsfilename}") as json_file: + with open(settings_filename) as json_file: data = json.load(json_file) - json_file.close() return data except: - return -1 \ No newline at end of file + return -1 From 30e06cbe86e928abe355f72c537d8a7bab7d5573 Mon Sep 17 00:00:00 2001 From: Alexander Malzkuhn Date: Tue, 6 May 2025 12:51:14 +0200 Subject: [PATCH 3/3] =?UTF-8?q?Neuanlage=20Benutzer=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- admin.py | 48 +++++++++++++++++++++++++++++++++++++----------- users.py | 34 ++++++++++++++++++++-------------- web_ui.py | 7 ++----- 3 files changed, 59 insertions(+), 30 deletions(-) diff --git a/admin.py b/admin.py index ed59afa..b733fe2 100644 --- a/admin.py +++ b/admin.py @@ -741,8 +741,6 @@ def page_admin(): with ui.tab_panel(users): ui.markdown("###Benutzerverwaltung") - userlist = list_users() - userlist.sort() workhours = [ ] with ui.row(): @@ -819,11 +817,12 @@ def page_admin(): def del_definitely(): current_user.del_user() - userlist = list_users() - userlist.sort() - user_selection.clear() - user_selection.set_options(userlist) - user_selection.value = userlist[0] + #userlist = list_users() + #userlist.sort() + #user_selection.clear() + #user_selection.set_options(userlist) + #user_selection.value = userlist[0] + user_ui.refresh() dialog.close() ui.notify("Benutzer gelöscht") @@ -886,10 +885,37 @@ def page_admin(): ui.button("OK", on_click=dialog.close) dialog.open() - with ui.column(): - user_selection = ui.select(options=userlist, with_input=True, on_change=user_selection_changed) - user_selection.value = userlist[0] - ui.button("Neu") + def dialog_new_user(): + def create_new_user(): + if user_name_input.validate(): + print(user_name_input.value) + new_user(user_name_input.value) + userlist = list_users() + user_ui.refresh() + dialog.close() + else: + ui.notify("Ungültiger Benutzername") + + with ui.dialog() as dialog, ui.card(): + ui.markdown("Geben Sie den Benutzernamen für das neue Konto an:") + user_name_input = ui.input(label="Benutzername", validation={'Leerer Benutzername nicht erlaubt': lambda value: len(value) != 0, + 'Leerzeichen im Benutzername nicht erlaubt': lambda value: " " not in value}) + with ui.row(): + ui.button("OK", on_click=create_new_user) + ui.button("Abbrechen", on_click=dialog.close) + dialog.open() + + @ui.refreshable + def user_ui(): + userlist = list_users() + userlist.sort() + + with ui.column(): + global user_selection + user_selection = ui.select(options=userlist, with_input=True, on_change=user_selection_changed) + user_selection.value = userlist[0] + ui.button("Neu", on_click=dialog_new_user) + user_ui() with ui.column(): with ui.card() as usersettingscard: diff --git a/users.py b/users.py index 41327b5..163a1d9 100644 --- a/users.py +++ b/users.py @@ -64,8 +64,8 @@ class user: self.timestamp() # Nach zugehörigem JSON-File suchen und bei Bedarf anlegen + json_filename = f"{self.get_stamp_file()}.json" try: - json_filename = f"{self.get_stamp_file()}.json" with open(json_filename, 'r') as json_file: pass except: @@ -94,9 +94,9 @@ class user: if len(lines)== 0: print(f"Keine Einträge") elif len(lines) % 2 == 0: - return (status_out) + return status_out else: - return (status_in) + return status_in def last_2_timestmaps(self): @@ -107,8 +107,8 @@ class user: if len(lines) > 2: second_last_line = int(lines[-2]) last_line = int(lines[-1]) - last_2_timestmaps = [second_last_line, last_line] - return last_2_timestmaps + last_2_timestamps = [second_last_line, last_line] + return last_2_timestamps elif len(lines) == 1: return int(lines[0]) @@ -117,10 +117,10 @@ class user: def write_settings(self): dict = { } - dict["username"] = (self.username) - dict["fullname"] = (self.fullname) - dict["password"] = (self.password) - dict["workhours"] = (self.workhours) + dict["username"] = self.username + dict["fullname"] = self.fullname + dict["password"] = self.password + dict["workhours"] = self.workhours json_dict = json.dumps(dict, indent=4) @@ -143,7 +143,7 @@ class user: month = str(starting_date[0])[5:7] day = str(starting_date[0])[8:10] - return (year, month, day) + return [year, month, day] def get_years(self): years = [ ] @@ -196,7 +196,7 @@ class user: if month not in available_months: available_months.append(month) available_months.sort() - return(available_months) + return available_months def get_timestamps(self, year, month): try: @@ -216,9 +216,9 @@ class user: try: with open(f"{self.userfolder}/{year}-{month}.json", 'r') as json_file: data = json.load(json_file) - return (data["archived"]) + return data["archived"] except: - return(-1) + return -1 def archive_hours(self, year, month, overtime: int): @@ -291,6 +291,7 @@ class user: json_file.write(json_dict) def get_day_workhours(self, year, month, day): + global hours_to_work workhour_entries = list(self.workhours) workhour_entries.sort() day_to_check = datetime.datetime(int(year), int(month), int(day)) @@ -381,17 +382,19 @@ class user: def list_users(): if not os.path.exists(userfolder): + print("Kein Benutzerverzeichnis gefunden. Lege es an.") os.makedirs(userfolder) users = [d for d in os.listdir(userfolder) if os.path.isdir(os.path.join(userfolder, d))] if len(users) == 0: + print("Keine Benutzer gefunden. Lege Standardbenutzer an.") new_user("default") users = [d for d in os.listdir(userfolder) if os.path.isdir(os.path.join(userfolder, d))] users.sort() return users -def new_user(username): +def new_user(username: str): if not os.path.exists(userfolder): os.makedirs(userfolder) if not os.path.exists(f"{userfolder}/{username}"): @@ -400,6 +403,8 @@ def new_user(username): start_date = start_date_dt.strftime("%Y-%m-%d") settings_to_write = standard_usersettings settings_to_write["workhours"][start_date] = { } + settings_to_write["fullname"] = username + settings_to_write["username"] = username for i in range(1, 8): settings_to_write["workhours"][start_date][str(i)] = 0 settings_to_write["workhours"][start_date]["vacation"] = 0 @@ -412,6 +417,7 @@ def load_adminsettings(): # Settingsdatei einlesen settings_filename = f"{scriptpath}/{usersettingsfilename}" if not os.path.exists(settings_filename): + print("Keine Einstellungsdatei gefunden. Lege Standarddatei an.") with open(settings_filename, 'w') as json_file: json_dict = json.dumps(standard_adminsettings, indent=4) json_file.write(json_dict) diff --git a/web_ui.py b/web_ui.py index c1f4048..7624aa1 100644 --- a/web_ui.py +++ b/web_ui.py @@ -23,9 +23,6 @@ class ValueBinder: def __init__(self): self.value = "" -def cookie_hash(user, password): - return hashlib.sha256(b"{user}{app.storage.user['id']}{password}").hexdigest() - def hash_password(password): return hashlib.sha256(bytes(password, 'utf-8')).hexdigest() @@ -98,9 +95,9 @@ def convert_seconds_to_hours(seconds): minutes = str(minutes) if sign == "-": - return(f"-{hours}:{minutes}") + return f"-{hours}:{minutes}" else: - return(f"{hours}:{minutes}") + return f"{hours}:{minutes}" def login_is_valid(user = -1):