From dc6b30e4e762bd2e21492b3f94c2e0690707542f Mon Sep 17 00:00:00 2001 From: Ferdinand Thiessen Date: Sat, 24 Oct 2020 20:09:45 +0200 Subject: [PATCH] Improved modify_user for backend plugins --- flaschengeist/modules/__init__.py | 2 +- flaschengeist/modules/auth_ldap/__init__.py | 13 ++++++++---- flaschengeist/modules/auth_plain/__init__.py | 11 +++++++--- .../system/controller/userController.py | 16 +++++++++----- flaschengeist/system/models/user.py | 21 ++++--------------- 5 files changed, 33 insertions(+), 30 deletions(-) diff --git a/flaschengeist/modules/__init__.py b/flaschengeist/modules/__init__.py index e7faac1..e957513 100644 --- a/flaschengeist/modules/__init__.py +++ b/flaschengeist/modules/__init__.py @@ -46,7 +46,7 @@ class AuthPlugin(Plugin): Args: user: User object - password: Password (some backends need the current password for changes) + password: Password (some backends need the current password for changes) if None force edit (admin) new_password: If set a password change is requested Raises: NotImplemented: If backend does not support this feature (or no password change) diff --git a/flaschengeist/modules/auth_ldap/__init__.py b/flaschengeist/modules/auth_ldap/__init__.py index d8cd710..ef48869 100644 --- a/flaschengeist/modules/auth_ldap/__init__.py +++ b/flaschengeist/modules/auth_ldap/__init__.py @@ -8,6 +8,7 @@ from werkzeug.exceptions import BadRequest from flaschengeist.modules import AuthPlugin from flaschengeist.system.models.user import User +import flaschengeist.system.controller.userController as userController class AuthLDAP(AuthPlugin): @@ -33,6 +34,8 @@ class AuthLDAP(AuthPlugin): app.config["LDAP_SECRET"] = (config["SECRET"],) self.ldap = LDAPConn(app) self.dn = config["BASEDN"] + self.admin_dn = config["ADMIN_DN"] + self.admin_secret = config["ADMIN_SECRET"] def login(self, user, password): if not user: @@ -55,8 +58,7 @@ class AuthLDAP(AuthPlugin): user.mail = r["mail"][0] if "displayName" in r: user.display_name = r["displayName"][0] - for group in self._get_groups(user.userid): - user.add_role(group) + userController.set_roles(user, self._get_groups(user.userid)) def _get_groups(self, uid): groups = [] @@ -84,7 +86,10 @@ class AuthLDAP(AuthPlugin): def modify_user(self, user: User, password, new_password=None): try: dn = user.attributes["DN"].value - ldap_conn = self.ldap.connect(dn, password) + if password: + ldap_conn = self.ldap.connect(dn, password) + else: + ldap_conn = self.ldap.connect(self.admin_dn, self.admin_secret) modifier = {} for name, ldap_name in [ ("firstname", "givenName"), @@ -92,7 +97,7 @@ class AuthLDAP(AuthPlugin): ("mail", "mail"), ("display_name", "displayName"), ]: - if getattr(user, name): + if hasattr(user, name): modifier[ldap_name] = [(MODIFY_REPLACE, [getattr(user, name)])] if new_password: salted_password = hashed(HASHED_SALTED_SHA512, new_password) diff --git a/flaschengeist/modules/auth_plain/__init__.py b/flaschengeist/modules/auth_plain/__init__.py index 4bb87c0..7d2e3a9 100644 --- a/flaschengeist/modules/auth_plain/__init__.py +++ b/flaschengeist/modules/auth_plain/__init__.py @@ -2,6 +2,8 @@ import binascii import hashlib import os +from werkzeug.exceptions import BadRequest + from flaschengeist.modules import AuthPlugin from flaschengeist.system.models.user import User @@ -23,9 +25,12 @@ def _verify_password(stored_password, provided_password): class AuthPlain(AuthPlugin): def login(self, user: User, password: str): - if user and "password" in user.attributes: - return _verify_password(user.attributes["password"].value, password) + if user.has_attribute("password"): + return _verify_password(user.get_attributes("password"), password) return False def modify_user(self, user, password, new_password=None): - pass + if password is not None and not self.login(user, password): + raise BadRequest + if new_password: + user.attributes["password"].value = _hash_password(new_password) diff --git a/flaschengeist/system/controller/userController.py b/flaschengeist/system/controller/userController.py index 4871fc7..9415bf6 100644 --- a/flaschengeist/system/controller/userController.py +++ b/flaschengeist/system/controller/userController.py @@ -1,5 +1,5 @@ from flask import current_app -from werkzeug.exceptions import NotFound +from werkzeug.exceptions import NotFound, BadRequest from flaschengeist.system.models.user import User, Role from flaschengeist.system.database import db @@ -25,15 +25,21 @@ def update_user(user): db.session.commit() +def set_roles(user: User, roles: [str]): + user.roles.clear() + for role_name in roles: + role = Role.query.filter(Role.name == role_name).one_or_one() + if not role: + raise BadRequest("Role not found >{}<".format(role_name)) + user.roles.append(role) + + def modify_user(user, password, new_password=None): """Modify given user on the backend Args: user: User object to sync with backend - password: Cu db.session.commit() - - # TODO: is this needed? - def user_has_rorrent password (most backends are needing this) + password: Current password (most backends are needing this) new_password (optional): New password, if password should be changed Raises: diff --git a/flaschengeist/system/models/user.py b/flaschengeist/system/models/user.py index fa4bfe6..a527478 100644 --- a/flaschengeist/system/models/user.py +++ b/flaschengeist/system/models/user.py @@ -70,24 +70,11 @@ class User(db.Model, ModelSerializeMixin): else: self._attributes[name] = _UserAttribute(name=name, value=value) - def add_role(self, name): - r = Role.query.filter_by(name=name).first() - if not r: - r = Role(name=name) - self.roles.append(r) + def has_attribute(self, name): + return name in self._attributes - def update_data(self, data): - logger.debug("update data of user") - if "userid" in data: - self.userid = data["userid"] - if "firstname" in data: - self.firstname = data["firstname"] - if "lastname" in data: - self.lastname = data["lastname"] - if "mail" in data: - self.mail = data["mail"] - if "display_name" in data: - self.display_name = data["display_name"] + def get_attribute(self, name): + return self._attributes[name].value def get_permissions(self): return ["user"] + [permission.name for role in self.roles for permission in role.permissions]