Files
kbcrm/App_Server/root/auth/model/users.py
T

180 lines
9.0 KiB
Python

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()