from . import APP_ADMIN, SYS_ADMIN, Application, Role, User, dbauth, Userapp from .errors import ApplicationError, AutorisationError from flask_login import current_user current_user: User session = dbauth.session def check_login(userid: str, password: str): """ Hier wird ausschließlich nur festgestellt, ob Login und Kennwort vorhanden sind bzw. übereinstimmen. alles Weitere muss in den Funktionen erfolgen, die 'check_login' aufrufen. """ user:User = User.query.filter(User.userid == userid).first() if user is None or user.password != password: return None else: return user def get_users(): """ Hier werden derzeit alle User zurückgegeben. Allerdings werden die userapps eines Users wie folgt gefiltert: Wenn es sich bei dem current_user um den SysAdmin handelt, wird nichts gefiltert Wenn es sich bei dem current_user um den AppAdmin handelt, werden nur die userapps zurückgegeben, auf die auch der current_user Zugriff hat. Außerdem wird die Rolle "SysAdmin" innerhalb der userapp.userapp-roles auch nicht mit zurückgegeben Bei allen anderen Arten von Usern werden keine userapps und somit auch keine Rollen zurückgegeben """ users = [] user: User for user in User.query.order_by(User.userid): # Wenn der current_user kein SysAdmin ist, soll diese User auch nicht sehen, dass es einen SysAdmin gibt if not current_user.is_SysAdmin() and user.is_SysAdmin(): continue # Wenn innerhalb einer For-Schleife Elemente gelöscht werden, muss auf einer Kopie der # Liste iteriert werden, da die For-Schleife sonst mit der Nummerierung durcheinanderkommt, weil während # des Durchlaufs Werte durch das remove "verschwinden" # Daher wird hier für die For-Schleife mit der Funktion list() eine neue Liste der Origonal-Liste erzeugt for userapp in list(user.userapps): # Rollen für bestimmte Application, in denen der zurückzugebende User Rollen innehat, sollen nur zurück- # gegeben werden, wenn der current_user für diese App SysAdmin oder AppAdmin ist if not current_user.has_permission(userapp.application.appid, [APP_ADMIN, SYS_ADMIN]): user.userapps.remove(userapp) # Wenn der current_user für die Application keine SysAdmin-Rolle hat, soll eine evtl. SysAdmin-Rolle auch # nicht zurückgegeben werden if not current_user.has_permission(userapp.application.appid, [SYS_ADMIN]): for role in list(userapp.userapp_roles): # s.o. wegen remove in for-loop if role.roleid == SYS_ADMIN: userapp.userapp_roles.remove(role) users.append(user) return users def changepassword(userid:str, oldpassword:str, newpassword1:str, newpassword2:str): """ Die Funktion ändert das Kennwort des Users -userid: string Die Userid (nicht id) des Users -oldpassword: string Das bisherige Kennwort des Users -newpassword1: string Das neue Kennwort des Users -newpassword2: string Die Wiederholung des neuen Kennwort des Users """ if newpassword1 != newpassword2: raise ValueError("Die neuen Kennworte stimmen nicht überein!") if newpassword1 is None or newpassword1.strip() == "": raise ValueError("Es muss ein neues Kennwort angegeben werden!") user:User = User.query.filter(User.userid == userid).first() if user is None or user.password != oldpassword: raise ValueError("Der angegebene Benutzer existiert nicht oder das alte Kennwort ist falsch") user.password = newpassword1 session.commit() return True def updateuser(data): """ Die User-Daten werden nur geändert, wenn der current_user entweder SysAdmin oder AppAdmin ist -data: Dict Ein Dictionary mit den Feldern, die beim User geändert werden sollen """ if not current_user.has_roles([SYS_ADMIN, APP_ADMIN]): raise AutorisationError(allowed_roles=[SYS_ADMIN, APP_ADMIN], user_roles=None) currentuser: User = None if data["id"] == -1: currentuser = User() currentuser.id = None currentuser.password = "" session.add(currentuser) else: currentuser = User.query.get(data["id"]) if currentuser is None: raise Exception ("404") currentuser.username = data["username"] currentuser.userid = data["userid"] currentuser.email = data["email"] currentuser.telefon = data["telefon"] session.commit() def deleteusers(userids): """ Hier werden die User gelöscht, deren userids übergeben werden. Gelöscht werden kann aber nur, wenn der current_user entweder SysAdmin oder AppAdmin ist. Wenn der zu löschende User Rollen in Applications hat, auf die der AppAdmin keinen Zugriff hat, Wird der User ebenfalls nicht gelöscht. - userids: string[] eine Liste der userids (nicht id) der User, die gelöscht werden sollen """ # Wenn er schon mal nirgendwo Sys- oder AppAdmin ist, fliegt er schon mal direkt raus if not current_user.has_roles([SYS_ADMIN, APP_ADMIN]): raise AutorisationError(allowed_roles=[SYS_ADMIN, APP_ADMIN], user_roles=None) # ansonsten: hier dürfen nur die User gelöscht werden, die in denjenigen Apps eine Rolle haben, # in dene der current_user entweder SysAdmin aod AppAdmin ist. Wenn der User noch eine Rolle in einer App haben, # auf die der current_user keinen Zugriff hat, darf nicht gelöscht werden for userid in userids: user: User = User.query.filter(User.userid == userid).one() if user is not None: for userapp in user.userapps: currentuser_userapp: Userapp = current_user.get_userapp(userapp.application.appid) if currentuser_userapp is None or len(currentuser_userapp.userapp_roles) == 0: raise ApplicationError(f"Der Benutzer {user.username} hat noch Rollen in Anwendungen, in denen Sie kein AppAdmin oder SysAdmin sind.", "Er kann daher nicht gelöscht werden.", "Der komplette Löschvorgang wurde abgebrochen.", htmlstatus=404) session.delete(user) session.commit() def applyuserapprole(data): """ Hier kann einem Benutzer eine Rolle für eine bestimmte App entzogen oder zugewiesen werden ### Parameter - data: dict - parentuserid: integer - Die id (nicht userid) des Users, für den eine Rolle geändert werden soll - parantappid: integer - Die id (nicht appid) der Application, für die eine Rolle geändert werden soll - roleid: integer - Die id (nicht roleid) der Rolle, die zugewiesen oder entzogen werden soll - ischecked: boolean - 'True' bedeutet, dass die Rolle zugewiesen werden soll, 'False' bedeutet, dass die Rolle entzogen werden soll """ user_id = data['parentuserid'] app_id = data['parentappid'] ischecked = data['ischecked'] role_id = data['roleid'] user: User = User.query.get(user_id) if user is None: raise Exception("Den User gibt es nicht") app: Application = Application.query.get(app_id) if app is None: raise Exception("Die Application gibt es nicht") role: Role = Role.query.get(role_id) if role is None: raise Exception("Die Rolle gibt es nicht") # hier darf nur zugewiesen werden, wenn der current_user entweder SysAdmin ist oder AppAdmin in der App, # für die die Rolle geändert wird if not current_user.is_SysAdmin() and not current_user.has_permission(app.appid, [APP_ADMIN]): raise AutorisationError(allowed_roles=[SYS_ADMIN, APP_ADMIN], user_roles=current_user.get_userapproles(app.appid)) userapp: Userapp = user.get_userapp_by_id(app_id) if userapp is None: userapp = Userapp() userapp.appid = app_id user.userapps.append(userapp) userapp_role: Role = userapp.get_role(role_id) if userapp_role is None and ischecked: userapp.userapp_roles.append(role) if userapp_role is not None and not ischecked: # eine SysAdmin oder ein AppAdmin kann sich selber nicht die Rolle als SysAdmin oder AppAdmin entziehen if current_user.userid == user.userid: if ((userapp_role.roleid == APP_ADMIN and current_user.has_permission(app.appid, [APP_ADMIN])) or (userapp_role.roleid == SYS_ADMIN and current_user.has_permission(app.appid, [SYS_ADMIN]))): raise ApplicationError("Sie können sich nicht selbst die Rolle als AppAdmin entziehen, da Sie dann keinen Zugriff auf das System mehr hätten!") userapp.userapp_roles.remove(userapp_role) # remove kann hier einfach so verwendet werden, da nicht über userapp.userapp_roles iteriert wird session.commit()