diff --git a/lumi2/ldap.py b/lumi2/ldap.py index d2f182b..e3d3b81 100644 --- a/lumi2/ldap.py +++ b/lumi2/ldap.py @@ -16,7 +16,7 @@ from flask import current_app from ldap3 import Connection, Server, ALL, Reader, Writer, ObjectDef from PIL import Image -from lumi2.usermodel import User +from lumi2.usermodel import User, Group from lumi2.exceptions import MissingConfigKeyError diff --git a/lumi2/usermodel.py b/lumi2/usermodel.py index 9a6a20f..9b6d16f 100644 --- a/lumi2/usermodel.py +++ b/lumi2/usermodel.py @@ -250,8 +250,103 @@ class User: self.picture = picture + def __eq__(self, other): + return self.username == other.username + + def __ne__(self, other): + return self.username != other.username + + def __lt__(self, other): + return self.username < other.username + + def __hash__(self): + return hash(self.username) + def __repr__(self): repr_str = f'User("{self.username}", "{self.password_hash}", ' \ f'"{self.email}", "{self.first_name}", "{self.last_name}", ' \ f'"{self.display_name}", "{self.picture}")' return repr_str + + +class Group: + """Class model for a group of users. + + Attributes + ---------- + groupname : str + The name (cn) of this group. + members : set[User] + The set of Users who are a member of this group. + """ + + @staticmethod + def is_valid_groupname(input_str: str) -> bool: + """Checks whether the input string is a valid group name. + + A valid group name consists of only alphanumeric characters, starts with + a latin character and has minimum length 1. + + Parameters + ---------- + input_str : str + The string to check for validity as a group name. + + Returns + ------- + bool + True if input_str is a valid group name, and False otherwise. + + Raises + ------ + TypeError + If input_str is not of type string. + """ + + if not isinstance(input_str, str): + raise TypeError(f"Expected a string but got: '{type(input_str)}'.") + + if not len(input_str): + return False + + if input_str[0] not in ascii_lowercase + ascii_uppercase: + return False + + for char in input_str: + if not char in ascii_uppercase + ascii_lowercase + digits: + return False + + return True + + + def __init__(self, groupname: str, members: set[User]): + + if not Group.is_valid_groupname(groupname): + raise ValueError("Not a valid group name: '{groupname}'.") + self.groupname = groupname + + if not isinstance(members, set): + raise TypeError(f"Expected a set but got: '{type(members)}'.") + for member in members: + if not isinstance(member, User): + raise TypeError(f"Expected only Users in members set but got: '{type(member)}'.") + if not len(members): + raise ValueError("Expected at least one group member.") + self.members = members + + + def __eq__(self, other): + return self.groupname == other.groupname + + def __ne__(self, other): + return self.groupname != other.groupname + + def __lt__(self, other): + return self.groupname < other.groupname + + def __hash__(self): + return hash(self.groupname) + + def __repr__(self): + repr_str = f'Group("{self.groupname}", "{self.members}")' + return repr_str