import hashlib
|
|
|
|
|
|
class User:
|
|
|
|
def __init__(self, username, password):
|
|
"""Create a new user object. The password will be encrypted before
|
|
storing"""
|
|
self.username = username
|
|
self.password = self._encrypt_pw(password)
|
|
self.is_logged_in = False
|
|
|
|
def _encrypt_pw(self, password):
|
|
"""Encrypt the password with the username and return the sha digest."""
|
|
hash_string = self.username + password
|
|
hash_string = hash_string.encode("utf8")
|
|
return hashlib.sha256(hash_string).hexdigest()
|
|
|
|
def check_password(self, password):
|
|
"""Return True if the password is valid for this user,
|
|
False otherwise"""
|
|
encrypted = self._encrypt_pw(password)
|
|
return encrypted == self.password
|
|
|
|
|
|
class Authenticator:
|
|
|
|
def __init__(self):
|
|
"""Construct an authenticator to manage users logging in and out.
|
|
The User objects are stored in a simple dictionary"""
|
|
self.users = {}
|
|
|
|
def add_user(self, username, password):
|
|
"""Add a User object with given username & password to the users
|
|
dictionary after checking if given username & password are valid"""
|
|
if username in self.users:
|
|
raise UsernameAlreadyExists(username)
|
|
if len(password) < 6:
|
|
raise PasswordTooShort(username)
|
|
self.users[username] = User(username, password)
|
|
|
|
def login(self, username, password):
|
|
try:
|
|
user = self.users[username]
|
|
except KeyError:
|
|
raise InvalidUsername(username)
|
|
if not user.check_password(password):
|
|
raise InvalidPassword(username, user)
|
|
user.is_logged_in = True
|
|
return True
|
|
|
|
def is_logged_in(self, username):
|
|
if username in self.users:
|
|
return self.users[username].is_logged_in
|
|
return False
|
|
|
|
|
|
authenticator = Authenticator()
|
|
|
|
|
|
class Authorizor():
|
|
|
|
def __init__(self, authenticator):
|
|
self.authenticator = authenticator
|
|
self.permissions = {}
|
|
|
|
def add_permission(self, perm_name):
|
|
"""Create a new permission that users can be added to"""
|
|
try:
|
|
perm_set = self.permissions[perm_name]
|
|
except KeyError:
|
|
self.permissions[perm_name] = set()
|
|
else:
|
|
raise PermissionError("Permission exists")
|
|
|
|
def permit_user(self, perm_name, username):
|
|
"""Grant the given permission to the given user"""
|
|
try:
|
|
perm_set = self.permissions[perm_name]
|
|
except KeyError:
|
|
raise PermissionError("Permission does not exist")
|
|
else:
|
|
if username not in self.authenticator.users:
|
|
raise InvalidUsername(username)
|
|
perm_set.add(username)
|
|
|
|
def check_permission(self, perm_name, username):
|
|
if not self.authenticator.is_logged_in(username):
|
|
raise NotLoggedInError(username)
|
|
try:
|
|
perm_set = self.permissions[perm_name]
|
|
except KeyError:
|
|
raise PermissionError("Permission does not exist")
|
|
if username not in perm_set:
|
|
raise NotPermittedError(username)
|
|
else:
|
|
return True
|
|
|
|
|
|
authorizor = Authorizor(authenticator)
|
|
|
|
|
|
# Exception classes
|
|
|
|
class AuthException(Exception):
|
|
|
|
def __init__(self, username, user=None):
|
|
super().__init__(username, user)
|
|
self.username = username
|
|
self.user = user
|
|
|
|
|
|
class UsernameAlreadyExists(AuthException):
|
|
pass
|
|
|
|
|
|
class PasswordTooShort(AuthException):
|
|
pass
|
|
|
|
|
|
class InvalidUsername(AuthException):
|
|
pass
|
|
|
|
|
|
class InvalidPassword(AuthException):
|
|
pass
|
|
|
|
|
|
class NotLoggedInError(AuthException):
|
|
pass
|
|
|
|
|
|
class NotPermittedError(AuthException):
|
|
pass
|
|
|
|
|
|
class PermissionError(Exception):
|
|
pass
|