Commit nach git-Error
Reichlich Zusatzfunktionen Homepage API Aufrufe Passwort Hashing
This commit is contained in:
parent
085b0f1129
commit
7fe82c1767
34
admin.py
34
admin.py
@ -16,19 +16,19 @@ import locale
|
||||
def page_admin():
|
||||
ui.page_title(f"{app_title} {app_version}")
|
||||
data = load_adminsettings()
|
||||
active_login = cookie_hash(data["admin_user"], data["admin_password"])
|
||||
|
||||
try:
|
||||
browser_cookie = app.storage.user['secret']
|
||||
browser_cookie = app.storage.user['admin_authenticated']
|
||||
except:
|
||||
browser_cookie = ""
|
||||
browser_cookie = False
|
||||
|
||||
# Adminseite
|
||||
if browser_cookie == active_login:
|
||||
if browser_cookie:
|
||||
pageheader("Administration")
|
||||
|
||||
def admin_logout():
|
||||
app.storage.user['secret'] = ""
|
||||
ui.navigate.to("/login")
|
||||
app.storage.user.pop("admin_authenticated", None)
|
||||
ui.navigate.to("/")
|
||||
|
||||
ui.button("Logout", on_click=admin_logout)
|
||||
|
||||
@ -455,7 +455,12 @@ Dies kann nicht rückgägig gemacht werden!''')
|
||||
def save_admin_settings():
|
||||
output_dict = { }
|
||||
output_dict["admin_user"] = admin_user.value
|
||||
output_dict["admin_password"] = admin_password.value
|
||||
print(admin_password.value)
|
||||
if admin_password.value != "":
|
||||
print("Passwort neu gesetzt")
|
||||
output_dict["admin_password"] = hash_password(admin_password.value)
|
||||
else:
|
||||
output_dict["admin_password"] = data["admin_password"]
|
||||
output_dict["port"] = port.value
|
||||
output_dict["secret"] = secret
|
||||
json_dict = json.dumps(output_dict, indent=4)
|
||||
@ -473,9 +478,8 @@ Dies kann nicht rückgägig gemacht werden!''')
|
||||
ui.markdown("Benutzername des Adminstrators")
|
||||
admin_user = ui.input()
|
||||
admin_user.value = data["admin_user"]
|
||||
ui.markdown("Passwort des Adminsistrators")
|
||||
ui.markdown("Passwort des Administrators")
|
||||
admin_password = ui.input(password=True)
|
||||
admin_password.value = data["admin_password"]
|
||||
|
||||
secret = data["secret"]
|
||||
|
||||
@ -503,7 +507,7 @@ Dies kann nicht rückgägig gemacht werden!''')
|
||||
current_user = user(user_selection.value)
|
||||
username_input.value = current_user.username
|
||||
fullname_input.value = current_user.fullname
|
||||
password_input.value = current_user.password
|
||||
#password_input.value = current_user.password
|
||||
usersettingscard.visible = True
|
||||
|
||||
workhours_select.clear()
|
||||
@ -519,7 +523,6 @@ Dies kann nicht rückgägig gemacht werden!''')
|
||||
user_photo.set_visibility(os.path.exists(current_user.photofile))
|
||||
delete_button.set_visibility(os.path.exists(current_user.photofile))
|
||||
|
||||
|
||||
except:
|
||||
pass
|
||||
|
||||
@ -544,8 +547,9 @@ Dies kann nicht rückgägig gemacht werden!''')
|
||||
current_user = user(user_selection.value)
|
||||
current_user.username = username_input.value
|
||||
current_user.fullname = fullname_input.value
|
||||
current_user.password = password_input.value
|
||||
current_user.password = hash_password(password_input.value)
|
||||
current_user.write_settings()
|
||||
password_input.value = ""
|
||||
userlist = list_users()
|
||||
userlist.sort()
|
||||
user_selection.clear()
|
||||
@ -594,7 +598,7 @@ Dies kann nicht rückgägig gemacht werden!''')
|
||||
if i < 7:
|
||||
construct_dict[i+1] = days[i].value
|
||||
elif i == 7:
|
||||
conctruct_dict[0] = days[i].value
|
||||
construct_dict[0] = days[i].value
|
||||
|
||||
construct_dict["vacation"] = vacation_input.value
|
||||
current_user.workhours[workhours_select.value] = construct_dict
|
||||
@ -652,6 +656,7 @@ Dies kann nicht rückgägig gemacht werden!''')
|
||||
fullname_input = ui.input()
|
||||
ui.markdown("Passwort")
|
||||
password_input = ui.input(password=True)
|
||||
password_input.value = ""
|
||||
|
||||
with ui.grid(columns=2):
|
||||
ui.button("Speichern", on_click=save_user_settings)
|
||||
@ -751,4 +756,5 @@ Dies kann nicht rückgägig gemacht werden!''')
|
||||
|
||||
# Alternativ zur Loginseite navigieren
|
||||
else:
|
||||
ui.navigate.to("/login")
|
||||
login = login_mask()
|
||||
#ui.navigate.to("/login")
|
192
api.py
192
api.py
@ -1,8 +1,8 @@
|
||||
import sys
|
||||
from calendar import month_name
|
||||
from logging import exception
|
||||
|
||||
from nicegui import *
|
||||
from samba.graph import pad_char
|
||||
|
||||
import ui
|
||||
from definitions import *
|
||||
@ -14,7 +14,7 @@ import calendar
|
||||
|
||||
|
||||
# Überblicksseite zum Ausdrucken oder als PDF speichern
|
||||
@ui.page('/api/overview/month/{username}/{year}-{month}')
|
||||
@ui.page('/api/month/{username}/{year}-{month}')
|
||||
def page_overview_month(username: str, year: int, month: int):
|
||||
|
||||
try:
|
||||
@ -94,7 +94,6 @@ def page_overview_month(username: str, year: int, month: int):
|
||||
except:
|
||||
if len(timestamps_dict[day]) % 2 != 0:
|
||||
booking_text += datetime.fromtimestamp(int(timestamps_dict[day][i])).strftime('%H:%M')
|
||||
print(booking_text)
|
||||
|
||||
booking_text_element = ui.markdown(booking_text).classes(f'border px-{pad_x} py-{pad_y} bg-{booking_color} text-{booking_text_color}')
|
||||
|
||||
@ -183,6 +182,7 @@ def page_overview_month(username: str, year: int, month: int):
|
||||
ui.markdown("Überstunden diesen Monat:").classes(f'col-span-4 text-right border px-{pad_x} py-{pad_y}')
|
||||
ui.markdown(f"{convert_seconds_to_hours(general_saldo)} h").classes(f'text-right border px-{pad_x} py-{pad_y}')
|
||||
ui.markdown("**Überstunden Gesamt:**").classes(f'col-span-4 text-right border px-{pad_x} py-{pad_y}')
|
||||
global overtime_overall
|
||||
overtime_overall = last_months_overtime + general_saldo
|
||||
ui.markdown(f"**{convert_seconds_to_hours(overtime_overall)} h**").classes(f'text-right border px-{pad_x} py-{pad_y}')
|
||||
|
||||
@ -215,6 +215,39 @@ def page_overview_month(username: str, year: int, month: int):
|
||||
|
||||
absence_table()
|
||||
|
||||
def archive():
|
||||
current_year = datetime.now().year
|
||||
current_month = datetime.now().month
|
||||
archivable = False
|
||||
|
||||
if current_year > year:
|
||||
if current_user.get_archive_status(year, month) == False:
|
||||
archivable = True
|
||||
if current_year == year:
|
||||
if current_month > month:
|
||||
if current_user.get_archive_status(year, month) == False:
|
||||
archivable = True
|
||||
|
||||
def archive_dialog():
|
||||
def do_archiving():
|
||||
global overtime_overall
|
||||
current_user.archive_hours(year, month, overtime_overall)
|
||||
dialog.close()
|
||||
ui.navigate.to(f'/api/month/{username}/{year}-{month}')
|
||||
|
||||
with ui.dialog() as dialog, ui.card():
|
||||
with ui.grid(columns='1fr 1fr'):
|
||||
ui.markdown("Hiermit bestätigen Sie, dass die Zeitbuchungen im Montagsjournal korrekt sind.<br>Sollte dies nicht der Fall sein, wenden Sie sich für eine Korrektur an den Administrator.").classes('col-span-2')
|
||||
ui.button("Archivieren", on_click=do_archiving)
|
||||
ui.button("Abbrechen", on_click=dialog.close)
|
||||
|
||||
dialog.open()
|
||||
|
||||
if archivable == True:
|
||||
ui.button("Archivieren", on_click=archive_dialog)
|
||||
|
||||
archive()
|
||||
|
||||
except Exception as e:
|
||||
print(str(type(e).__name__) + " " + str(e))
|
||||
if type(e) == UnboundLocalError:
|
||||
@ -225,45 +258,126 @@ def page_overview_month(username: str, year: int, month: int):
|
||||
ui.markdown(str(type(e)))
|
||||
ui.markdown(str(e))
|
||||
|
||||
@ui.page('/api/overview/vacation/{username}/{year}-{month}-{day}')
|
||||
def page_overview_vacation(username: str, year: int, month: int, day: int):
|
||||
try:
|
||||
current_user = user(username)
|
||||
@ui.page('/api/vacation/{username}/{year}')
|
||||
def page_overview_vacation(username: str, year: int):
|
||||
|
||||
ui.page_title(f"Urlaubsanspruch für {current_user.fullname} für {year}")
|
||||
if login_is_valid(username):
|
||||
|
||||
try:
|
||||
current_user = user(username)
|
||||
|
||||
month = datetime.now().month
|
||||
day = datetime.now().day
|
||||
|
||||
ui.page_title(f"Urlaubsanspruch für {current_user.fullname} für {year}")
|
||||
ui.label(datetime.now().strftime('%d.%m.%Y')).classes('absolute top-5 right-5')
|
||||
ui.space()
|
||||
ui.markdown(f'#Urlaubsanspruch für {current_user.fullname} für {year}')
|
||||
|
||||
pad_x = 4
|
||||
pad_y = 0
|
||||
|
||||
vacationclaim = int(current_user.get_vacation_claim(year, month, day))
|
||||
if vacationclaim == -1:
|
||||
ui.markdown(f"###Kein Urlaubsanspruch für {year}")
|
||||
else:
|
||||
|
||||
with ui.grid(columns='auto auto').classes(f'gap-0 border px-0 py-0'):
|
||||
ui.markdown(f"Urlaubsanspruch für {year}:").classes(f'border px-{pad_x} py-{pad_y}')
|
||||
ui.markdown(f"{vacationclaim} Tage").classes(f'text-right border px-{pad_x} py-{pad_y}')
|
||||
ui.markdown("Registrierte Urlaubstage").classes(f'border px-{pad_x} py-{pad_y} col-span-2')
|
||||
vacation_counter = 0
|
||||
try:
|
||||
for i in range(1, 13):
|
||||
absence_entries = current_user.get_absence(year, i)
|
||||
for day, absence_type in absence_entries.items():
|
||||
# print(day + "." + str(i) + " " + absence_type)
|
||||
if absence_type == "U":
|
||||
day_in_list = datetime(int(year), int(i), int(day)).strftime("%d.%m.%Y")
|
||||
ui.markdown(day_in_list).classes(f'border px-{pad_x} py-{pad_y}')
|
||||
ui.markdown("-1 Tag").classes(f'border px-{pad_x} py-{pad_y} text-center')
|
||||
vacation_counter += 1
|
||||
except Exception as e:
|
||||
print(str(type(e).__name__) + " " + str(e))
|
||||
ui.markdown("**Resturlaub:**").classes(f'border px-{pad_x} py-{pad_y}')
|
||||
ui.markdown(f'**{str(vacationclaim - vacation_counter)} Tage**').classes(f'border px-{pad_x} py-{pad_y} text-center')
|
||||
|
||||
|
||||
except Exception as e:
|
||||
print(str(type(e).__name__) + " " + str(e))
|
||||
if type(e) == UnboundLocalError:
|
||||
ui.markdown('#Fehler')
|
||||
ui.markdown('Benutzer existiert nicht')
|
||||
else:
|
||||
ui.markdown('#Fehler')
|
||||
ui.markdown(str(type(e)))
|
||||
ui.markdown(str(e))
|
||||
else:
|
||||
login = login_mask(target=f'/api/vacation/{username}/{year}')
|
||||
|
||||
@ui.page('/api/absence/{username}/{year}')
|
||||
def page_overview_absence(username: str, year: int):
|
||||
|
||||
if login_is_valid(username):
|
||||
current_user = user(username)
|
||||
ui.page_title(f"Abwesenheitsübersicht für {current_user.fullname} für {year}")
|
||||
ui.label(datetime.now().strftime('%d.%m.%Y')).classes('absolute top-5 right-5')
|
||||
ui.space()
|
||||
ui.markdown(f'#Urlaubsanspruch für {current_user.fullname} für {year}')
|
||||
pageheader(f"Abwesenheitsübersicht für {current_user.fullname} für {year}")
|
||||
|
||||
pad_x = 4
|
||||
pad_x = 2
|
||||
pad_y = 0
|
||||
|
||||
with ui.grid(columns='auto auto').classes(f'gap-0 border px-0 py-0'):
|
||||
ui.markdown(f"Urlaubsübersicht für {year}:").classes(f'border px-{pad_x} py-{pad_y}')
|
||||
vacationclaim = int(current_user.get_vacation_claim(year, month, day))
|
||||
ui.markdown(f"{vacationclaim} Tage").classes(f'text-right border px-{pad_x} py-{pad_y}')
|
||||
ui.markdown("Registrierte Urlaubstage").classes(f'border px-{pad_x} py-{pad_y} col-span-2')
|
||||
vacation_counter = 0
|
||||
try:
|
||||
for i in range(1, 13):
|
||||
absence_entries = current_user.get_absence(year, i)
|
||||
for day, absence_type in absence_entries.items():
|
||||
print(day + "." + str(i) + " " + absence_type)
|
||||
if absence_type == "U":
|
||||
day_in_list = datetime(int(year), int(i), int(day)).strftime("%d.%m.%Y")
|
||||
ui.markdown(day_in_list).classes(f'border px-{pad_x} py-{pad_y}')
|
||||
ui.markdown("-1 Tag").classes(f'border px-{pad_x} py-{pad_y} text-center')
|
||||
vacation_counter += 1
|
||||
except Exception as e:
|
||||
print(str(type(e).__name__) + " " + str(e))
|
||||
ui.markdown("**Resturlaub:**").classes(f'border px-{pad_x} py-{pad_y}')
|
||||
ui.markdown(f'**{str(vacationclaim - vacation_counter)} Tage**').classes(f'border px-{pad_x} py-{pad_y} text-center')
|
||||
except Exception as e:
|
||||
print(str(type(e).__name__) + " " + str(e))
|
||||
if type(e) == UnboundLocalError:
|
||||
ui.markdown('#Fehler')
|
||||
ui.markdown('Benutzer existiert nicht')
|
||||
else:
|
||||
ui.markdown('#Fehler')
|
||||
ui.markdown(str(type(e)))
|
||||
ui.markdown(str(e))
|
||||
def absence_calender():
|
||||
|
||||
column_constructor = 'auto '
|
||||
for j in range(1, 31):
|
||||
column_constructor += "1fr "
|
||||
column_constructor += 'auto'
|
||||
|
||||
with ui.grid(columns=column_constructor).classes(f'gap-0 border px-0 py-0') as calendar_grid:
|
||||
# Erste Zeile
|
||||
ui.space()
|
||||
for i in range(1, 32):
|
||||
ui.markdown(str(i)).classes(f'border px-{pad_x} py-{pad_y} text-center')
|
||||
# Monate durchgehen
|
||||
for month in range(1, 13):
|
||||
for column in range(0, 32):
|
||||
if column == 0:
|
||||
ui.markdown(month_name[month]).classes(f'border px-{pad_x} py-{pad_y} text.center')
|
||||
else:
|
||||
absences = current_user.get_absence(year, month)
|
||||
if str(column) in list(absences):
|
||||
bg_color = absence_entries[absences[str(column)]]['color']
|
||||
text_color = absence_entries[absences[str(column)]]['text-color']
|
||||
ui.markdown(absences[str(column)]).classes(f'border px-{pad_x} py-{pad_y} bg-{bg_color} text-{text_color} text-center')
|
||||
else:
|
||||
if column > monthrange(year, month)[1]:
|
||||
bg_color = 'gray-500'
|
||||
elif int(current_user.get_day_workhours(year, month, column)) == 0:
|
||||
bg_color = 'gray-300'
|
||||
elif int(current_user.get_day_workhours(year, month, column)) == -1:
|
||||
bg_color = 'gray-400'
|
||||
else:
|
||||
bg_color = 'inherit'
|
||||
ui.space().classes(f'border px-{pad_x} py-{pad_y} bg-{bg_color}')
|
||||
|
||||
absence_calender()
|
||||
|
||||
def absence_table():
|
||||
|
||||
with ui.grid(columns='auto auto').classes(f'gap-0 px-0 py-0'):
|
||||
ui.markdown('**Summen**').classes('col-span-2 px-2')
|
||||
for type in list(absence_entries):
|
||||
number_of_days = 0
|
||||
ui.markdown(absence_entries[type]["name"]).classes(f'border px-{pad_x} py-{pad_y}')
|
||||
for month in range(1, 13):
|
||||
absences_of_month = current_user.get_absence(year, month)
|
||||
for i in list(absences_of_month):
|
||||
if absences_of_month[i] == type:
|
||||
number_of_days += 1
|
||||
ui.markdown(str(number_of_days)).classes(f'border px-{pad_x} py-{pad_y} text-center')
|
||||
absence_table()
|
||||
|
||||
else:
|
||||
login = login_mask(target=f'/api/absence/{username}/{year}')
|
126
homepage.py
Normal file
126
homepage.py
Normal file
@ -0,0 +1,126 @@
|
||||
# Zeiterfassung
|
||||
import datetime
|
||||
|
||||
from nicegui import ui, app
|
||||
|
||||
from users import *
|
||||
from definitions import *
|
||||
from calendar import monthrange, month_name
|
||||
|
||||
import hashlib
|
||||
import calendar
|
||||
import locale
|
||||
|
||||
from web_ui import *
|
||||
|
||||
@ui.page('/')
|
||||
def homepage():
|
||||
if login_is_valid():
|
||||
|
||||
ui.page_title("Zeiterfassung")
|
||||
current_user = user(app.storage.user["active_user"])
|
||||
pageheader(f"Willkommen, {current_user.fullname}")
|
||||
|
||||
today = datetime.datetime.now()
|
||||
|
||||
@ui.refreshable
|
||||
def stamp_interface():
|
||||
|
||||
time_so_far = current_user.get_worked_time(today.year, today.month, today.day)[0]
|
||||
|
||||
def stamp_and_refresh():
|
||||
current_user.timestamp()
|
||||
stamp_interface.refresh()
|
||||
|
||||
with ui.grid(columns='20% auto 20%').classes('w-full justify-center'):
|
||||
ui.space()
|
||||
with ui.grid(columns='1fr 1fr'):
|
||||
if current_user.stamp_status() == status_in:
|
||||
bg_color = 'green'
|
||||
else:
|
||||
bg_color = 'red'
|
||||
working_hours = ui.markdown(convert_seconds_to_hours(time_so_far)).classes(f'col-span-2 rounded-3xl text-center text-white text-bold text-2xl border-4 border-gray-600 bg-{bg_color}')
|
||||
in_button = ui.button("Einstempeln", on_click=stamp_and_refresh).classes('bg-green')
|
||||
out_button = ui.button("Ausstempeln", on_click=stamp_and_refresh).classes('bg-red')
|
||||
|
||||
def update_timer():
|
||||
time_in_total = time_so_far + int((datetime.datetime.now().timestamp() - current_user.get_worked_time(today.year, today.month, today.day)[1]))
|
||||
print(time_in_total)
|
||||
working_hours.set_content(convert_seconds_to_hours(time_in_total))
|
||||
|
||||
working_timer = ui.timer(1.0, update_timer)
|
||||
working_timer.active = False
|
||||
|
||||
if current_user.stamp_status() == status_in:
|
||||
in_button.set_enabled(False)
|
||||
out_button.set_enabled(True)
|
||||
working_timer.active = True
|
||||
|
||||
else:
|
||||
in_button.set_enabled(True)
|
||||
out_button.set_enabled(False)
|
||||
working_timer.active = False
|
||||
|
||||
stamp_interface()
|
||||
|
||||
available_years = current_user.get_years()
|
||||
|
||||
|
||||
available_months = [ ]
|
||||
binder_month_button = ValueBinder()
|
||||
binder_month_button.value = False
|
||||
|
||||
binder_available_years = ValueBinder()
|
||||
|
||||
binder_vacation = ValueBinder
|
||||
binder_vacation.value = False
|
||||
|
||||
binder_absence = ValueBinder
|
||||
binder_absence.value = False
|
||||
|
||||
def enable_month():
|
||||
binder_month_button.value = True
|
||||
|
||||
def update_month():
|
||||
month_dict = { }
|
||||
for i in current_user.get_months(month_year_select.value):
|
||||
month_dict[i] = month_name[i]
|
||||
|
||||
month_month_select.set_options(month_dict)
|
||||
month_month_select.enable()
|
||||
|
||||
ui.separator()
|
||||
|
||||
with ui.grid(columns='1fr auto 1fr').classes('w-full justify-center'):
|
||||
ui.space()
|
||||
|
||||
def activate_vacation():
|
||||
binder_vacation.value = True
|
||||
|
||||
with ui.grid(columns='1fr 1fr'):
|
||||
|
||||
ui.markdown("**Monatsübersicht:**").classes('col-span-2')
|
||||
|
||||
month_year_select = ui.select(list(reversed(available_years)), label="Jahr", on_change=update_month).bind_value_to(binder_available_years, 'value')
|
||||
month_month_select = ui.select(available_months, label="Monat", on_change=enable_month)
|
||||
month_month_select.disable()
|
||||
|
||||
ui.space()
|
||||
month_button = ui.button("Anzeigen", on_click=lambda: ui.navigate.to(f"/api/overview/month/{current_user.username}/{month_year_select.value}-{month_month_select.value}", new_tab=True)).bind_enabled_from(binder_month_button, 'value')
|
||||
ui.markdown("**Urlaubsanspruch**").classes('col-span-2')
|
||||
vacation_select = ui.select(list(reversed(available_years)), on_change=activate_vacation)
|
||||
vacation_button = ui.button("Anzeigen", on_click=lambda: ui.navigate.to(f"/api/overview/vacation/{current_user.username}/{vacation_select.value}", new_tab=True)).bind_enabled_from(binder_vacation, 'value')
|
||||
ui.markdown("**Fehlzeitenübersicht**").classes('col-span-2')
|
||||
absences_select = ui.select(list(reversed(available_years)))
|
||||
absences_button = ui.button("Anzeigen").bind_enabled_from(binder_absence, 'value')
|
||||
ui.separator().classes('col-span-2')
|
||||
|
||||
def logout():
|
||||
app.storage.user.pop("active_user", None)
|
||||
ui.navigate.to("/")
|
||||
|
||||
ui.button("Logout", on_click=logout).classes('col-span-2')
|
||||
ui.space()
|
||||
|
||||
else:
|
||||
login_mask()
|
6
login.py
6
login.py
@ -21,9 +21,9 @@ def page_login():
|
||||
nonlocal data
|
||||
|
||||
if username.value == data["admin_user"]:
|
||||
if password.value == data["admin_password"]:
|
||||
active_login = cookie_hash(data["admin_user"], data["admin_password"])
|
||||
app.storage.user['secret'] = active_login
|
||||
print(f"Input Hash: {hash_password(password.value)} gespeichert: {data['admin_password']}")
|
||||
if hash_password(password.value) == data["admin_password"]:
|
||||
app.storage.user['authenticated'] = True
|
||||
ui.navigate.to("/admin")
|
||||
else:
|
||||
ui.notify("Login fehlgeschlagen")
|
||||
|
3
main.py
3
main.py
@ -7,6 +7,7 @@ from users import *
|
||||
from touchscreen import *
|
||||
from definitions import *
|
||||
from api import *
|
||||
from homepage import *
|
||||
|
||||
import json
|
||||
|
||||
@ -19,6 +20,8 @@ def main():
|
||||
port = int(data["port"])
|
||||
secret = data["secret"]
|
||||
|
||||
homepage()
|
||||
|
||||
ui.run(port=port, storage_secret=secret, language='de-DE')
|
||||
|
||||
if __name__ in ("__main__", "__mp_main__"):
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"admin_user": "admin",
|
||||
"admin_password": "123456",
|
||||
"admin_password": "8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92",
|
||||
"port": "8090",
|
||||
"secret": "ftgzuhjikg,mt5jn46uzer8sfi9okrmtzjhndfierko5zltjhdgise"
|
||||
}
|
52
users.py
52
users.py
@ -85,7 +85,7 @@ class user:
|
||||
lines = file.readlines()
|
||||
file.close()
|
||||
except FileNotFoundError:
|
||||
print(f"Die Datei {filename} wurde nicht gefunden.")
|
||||
print(f"Die Datei {file} wurde nicht gefunden.")
|
||||
if len(lines)== 0:
|
||||
print(f"Keine Einträge")
|
||||
elif len(lines) % 2 == 0:
|
||||
@ -207,8 +207,26 @@ class user:
|
||||
with open(f"{self.userfolder}/{year}-{month}.txt", "w") as file:
|
||||
file.write(''.join(timestamps))
|
||||
|
||||
def archive_hours(self, year, month):
|
||||
pass
|
||||
def get_archive_status(self, year, month):
|
||||
try:
|
||||
with open(f"{self.userfolder}/{year}-{month}.json", 'r') as json_file:
|
||||
data = json.load(json_file)
|
||||
return (data["archived"])
|
||||
except:
|
||||
return(-1)
|
||||
|
||||
def archive_hours(self, year, month, overtime: int):
|
||||
|
||||
filename = f"{self.userfolder}/{year}-{month}.json"
|
||||
with open(filename, 'r') as json_file:
|
||||
data = json.load(json_file)
|
||||
data["archived"] = 1
|
||||
data["overtime"] = overtime
|
||||
|
||||
json_dict = json.dumps(data)
|
||||
|
||||
with open(filename, "w") as outputfile:
|
||||
outputfile.write(json_dict)
|
||||
|
||||
def get_last_months_overtime(self, year, month):
|
||||
try:
|
||||
@ -309,6 +327,34 @@ class user:
|
||||
def delete_photo(self):
|
||||
os.remove(self.photofile)
|
||||
|
||||
def get_worked_time(self, year, month, day):
|
||||
timestamps = self.get_timestamps(year, month)
|
||||
check_day_dt = datetime.datetime(year, month, day)
|
||||
todays_timestamps = [ ]
|
||||
|
||||
for i in timestamps:
|
||||
i_dt = datetime.datetime.fromtimestamp(int(i))
|
||||
if i_dt.date() == check_day_dt.date():
|
||||
todays_timestamps.append(int(i))
|
||||
|
||||
todays_timestamps.sort()
|
||||
if len(todays_timestamps) % 2 == 0:
|
||||
workrange = len(todays_timestamps)
|
||||
in_time_stamp = -1
|
||||
else:
|
||||
workrange = len(todays_timestamps) - 1
|
||||
in_time_stamp = int(todays_timestamps[-1])
|
||||
total_time = 0
|
||||
|
||||
for i in range(0, workrange, 2):
|
||||
time_worked = todays_timestamps[i + 1] - todays_timestamps[i]
|
||||
total_time += time_worked
|
||||
|
||||
print(total_time)
|
||||
print(in_time_stamp)
|
||||
|
||||
return([total_time, in_time_stamp])
|
||||
|
||||
# Benutzer auflisten
|
||||
def list_users():
|
||||
users = [d for d in os.listdir(userfolder) if os.path.isdir(os.path.join(userfolder, d))]
|
||||
|
@ -7,29 +7,21 @@
|
||||
"3": "EZ",
|
||||
"4": "EZ",
|
||||
"5": "EZ",
|
||||
"6": "EZ",
|
||||
"7": "EZ",
|
||||
"8": "EZ",
|
||||
"9": "EZ",
|
||||
"10": "EZ",
|
||||
"11": "EZ",
|
||||
"12": "EZ",
|
||||
"13": "EZ",
|
||||
"14": "EZ",
|
||||
"15": "EZ",
|
||||
"16": "EZ",
|
||||
"17": "EZ",
|
||||
"18": "EZ",
|
||||
"19": "EZ",
|
||||
"20": "EZ",
|
||||
"21": "EZ",
|
||||
"22": "EZ",
|
||||
"23": "EZ",
|
||||
"24": "EZ",
|
||||
"25": "EZ",
|
||||
"26": "EZ",
|
||||
"27": "EZ",
|
||||
"28": "EZ",
|
||||
"29": "EZ",
|
||||
"30": "EZ",
|
||||
"31": "EZ"
|
||||
|
@ -1,4 +1 @@
|
||||
{
|
||||
"archived": 1,
|
||||
"overtime": 3950
|
||||
}
|
||||
{"archived": 1, "overtime": -528928}
|
@ -20,3 +20,15 @@
|
||||
1745390894
|
||||
1745390894
|
||||
1745391029
|
||||
1746006467
|
||||
1746006593
|
||||
1746006933
|
||||
1746006937
|
||||
1746007004
|
||||
1746007012
|
||||
1746007119
|
||||
1746007383
|
||||
1746010855
|
||||
1746010861
|
||||
1746011089
|
||||
1746011092
|
||||
|
@ -1,17 +1,17 @@
|
||||
{
|
||||
"username": "testuser1",
|
||||
"fullname": "Pia Paulina",
|
||||
"password": "123456789",
|
||||
"password": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
|
||||
"workhours": {
|
||||
"2025-05-13": {
|
||||
"1": "0",
|
||||
"2": "0",
|
||||
"3": "0",
|
||||
"4": "0",
|
||||
"5": "0",
|
||||
"1": "4",
|
||||
"2": "5",
|
||||
"3": "6",
|
||||
"4": "7",
|
||||
"5": "8",
|
||||
"6": "0",
|
||||
"7": "0",
|
||||
"vacation": "0"
|
||||
"vacation": "30"
|
||||
},
|
||||
"2025-04-22": {
|
||||
"1": "1",
|
||||
@ -21,7 +21,7 @@
|
||||
"5": "5",
|
||||
"6": "6",
|
||||
"7": "7",
|
||||
"vacation": "0"
|
||||
"vacation": "30"
|
||||
},
|
||||
"2025-03-01": {
|
||||
"1": "4",
|
||||
|
76
web_ui.py
76
web_ui.py
@ -26,6 +26,9 @@ class ValueBinder:
|
||||
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()
|
||||
|
||||
def load_adminsettings():
|
||||
# Settingsdatei einlesen
|
||||
try:
|
||||
@ -36,6 +39,50 @@ def load_adminsettings():
|
||||
except:
|
||||
return(-1)
|
||||
|
||||
class login_mask:
|
||||
def __init__(self, target="/"):
|
||||
data = load_adminsettings()
|
||||
self.target = target
|
||||
|
||||
def login():
|
||||
nonlocal data
|
||||
|
||||
if username.value == data["admin_user"]:
|
||||
if hash_password(password.value) == data["admin_password"]:
|
||||
app.storage.user['admin_authenticated'] = True
|
||||
ui.navigate.to("/admin")
|
||||
else:
|
||||
ui.notify("Login fehlgeschlagen")
|
||||
else:
|
||||
userlist = list_users()
|
||||
|
||||
if username.value in userlist:
|
||||
current_user = user(username.value)
|
||||
|
||||
if hash_password(password.value) == current_user.password:
|
||||
app.storage.user['active_user'] = current_user.username
|
||||
ui.navigate.to(self.target)
|
||||
else:
|
||||
ui.notify("Login fehlgeschlagen")
|
||||
else:
|
||||
ui.notify("Login fehlgeschlagen")
|
||||
|
||||
# ui.markdown(f"## {app_title} {app_version}")
|
||||
# ui.markdown("Bitte einloggen")
|
||||
|
||||
pageheader("Bitte einloggen:")
|
||||
|
||||
with ui.grid(columns='20% auto 20%').classes('w-full justify-center'):
|
||||
|
||||
ui.space()
|
||||
with ui.grid(columns=2):
|
||||
ui.markdown("Benutzer:")
|
||||
username = ui.input('Benutzername')
|
||||
ui.markdown("Passwort:")
|
||||
password = ui.input('Passwort', password=True)
|
||||
ui.button(text="Login", on_click=lambda: login())
|
||||
ui.space()
|
||||
|
||||
def convert_seconds_to_hours(seconds):
|
||||
if seconds < 0:
|
||||
sign = "-"
|
||||
@ -62,19 +109,20 @@ def convert_seconds_to_hours(seconds):
|
||||
else:
|
||||
return(f"{hours}:{minutes}")
|
||||
|
||||
@ui.page('/userlist')
|
||||
def page_userlist():
|
||||
|
||||
def click_button(button):
|
||||
ui.notify(button)
|
||||
|
||||
ui.markdown(f"#{app_title} {app_version}")
|
||||
|
||||
userlist = list_users()
|
||||
buttons = { }
|
||||
|
||||
for name in userlist:
|
||||
button = ui.button(text=name, on_click=lambda name=name:click_button(name) )
|
||||
buttons[name] = button
|
||||
def login_is_valid(user = -1):
|
||||
|
||||
if user == -1:
|
||||
try:
|
||||
app.storage.user['active_user']
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
else:
|
||||
try:
|
||||
if app.storage.user['active_user'] == user:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
except:
|
||||
return False
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user