mirror of
https://github.com/Noettore/lagomareGateKeeperBot.git
synced 2025-10-15 11:36:40 +02:00
126 lines
4.9 KiB
Python
126 lines
4.9 KiB
Python
from datetime import datetime, timezone
|
|
|
|
from src.models import Status, Role, Credential, Grant, User
|
|
from src.repository import UsersRepository
|
|
|
|
|
|
class UsersService:
|
|
|
|
def __init__(self, users_repository: UsersRepository):
|
|
self._users_repository = users_repository
|
|
|
|
def add_user(self, uid: str) -> User:
|
|
user = self._users_repository.get_by_uid(uid)
|
|
if not user:
|
|
user = User(uid)
|
|
self._users_repository.save(uid, user)
|
|
return user
|
|
|
|
def get_user(self, uid: str) -> User:
|
|
user = self._users_repository.get_by_uid(uid)
|
|
if not user:
|
|
raise Exception("User not found")
|
|
return user
|
|
|
|
def get_role(self, uid: str) -> Role:
|
|
return self.get_user(uid).role
|
|
|
|
def get_credentials(self, uid: str, gate_key: str) -> Credential | None:
|
|
user = self._users_repository.get_by_uid(uid)
|
|
if user.role in (Role.ADMIN, Role.MEMBER):
|
|
creds = user.credentials
|
|
if not creds:
|
|
raise Exception("Please set your credentials with `/setcredentials` first")
|
|
elif user.role == Role.GUEST and self.can_open_gate(uid, gate_key):
|
|
grantor = self.get_grantor(user, gate_key)
|
|
if not grantor:
|
|
raise Exception("No valid grantor available.")
|
|
creds = grantor.credentials
|
|
if not creds:
|
|
raise Exception("No valid grantor credentials available.")
|
|
self.update_grant_last_used(uid, gate_key)
|
|
# try:
|
|
# await context.bot.send_message(chat_id=grantor, text=f"Guest {uid} opened {gate_name}")
|
|
# except Exception as e:
|
|
# print(f"Failed to notify {grantor} that guest {uid} opened {gate_name}: {e}")
|
|
else:
|
|
raise Exception("Access denied.")
|
|
|
|
def set_credentials(self, uid: str, credentials: Credential) -> bool:
|
|
user = self._users_repository.get_by_uid(uid)
|
|
if user:
|
|
user.credentials = credentials
|
|
self._users_repository.save(uid, user)
|
|
return True
|
|
return False
|
|
|
|
def can_open_gate(self, uid: str, gate_key: str) -> bool:
|
|
user = self._users_repository.get_by_uid(uid)
|
|
if not user or user.status != Status.ENABLED:
|
|
return False
|
|
if user.role == Role.ADMIN or user.role == Role.MEMBER:
|
|
return True
|
|
grant = user.grants.get(gate_key)
|
|
if not grant or grant.status != Status.ENABLED:
|
|
return False
|
|
if grant.expires_at <= datetime.now(timezone.utc):
|
|
return False
|
|
return True
|
|
|
|
def has_grants(self, uid: str) -> bool:
|
|
user = self._users_repository.get_by_uid(uid)
|
|
if not user or user.status != Status.ENABLED:
|
|
return False
|
|
if user.role == Role.ADMIN or user.role == Role.MEMBER:
|
|
return True
|
|
return any(grant.status == Status.ENABLED and grant.expires_at > datetime.now(timezone.utc) for grant in
|
|
user.grants.values())
|
|
|
|
def get_grantor(self, user: User, gate: str) -> User | None:
|
|
grant = user.grants.get(gate)
|
|
return self._users_repository.get_by_uid(grant.grantor) if grant else None
|
|
|
|
def get_admins(self) -> list[str]:
|
|
return [user.uid for user in self._users_repository.get_all() if user.role == Role.ADMIN]
|
|
|
|
def grant_access(self, uid: str, gate: str, expires_at: datetime, grantor_id: str) -> bool:
|
|
user = self._users_repository.get_by_uid(uid)
|
|
if not user:
|
|
return False
|
|
user.grants[gate] = Grant(grantor_id, expires_at)
|
|
self._users_repository.save(uid, user)
|
|
return True
|
|
|
|
def revoke_access(self, uid: str, gate: str) -> bool:
|
|
user = self._users_repository.get_by_uid(uid)
|
|
if not user:
|
|
return False
|
|
if gate in user.grants:
|
|
del user.grants[gate]
|
|
self._users_repository.save(uid, user)
|
|
return True
|
|
return False
|
|
|
|
def update_grant_last_used(self, uid: str, gate_key: str) -> bool:
|
|
user = self._users_repository.get_by_uid(uid)
|
|
if not user:
|
|
return False
|
|
grant = user.grants.get(gate_key)
|
|
if not grant:
|
|
return False
|
|
grant.last_used_at = datetime.now(timezone.utc)
|
|
self._users_repository.save(uid, user)
|
|
return True
|
|
|
|
def get_granted_gates(self, uid: str) -> list[str]:
|
|
user = self._users_repository.get_by_uid(uid)
|
|
if not user:
|
|
return []
|
|
if user.role == Role.ADMIN or user.role == Role.MEMBER:
|
|
return ['all']
|
|
if 'all' in user.grants and user.grants['all'].status == Status.ENABLED and user.grants[
|
|
'all'].expires_at > datetime.now(timezone.utc):
|
|
return ['all']
|
|
return [gate for gate, grant in user.grants.items() if
|
|
grant.status == Status.ENABLED and grant.expires_at > datetime.now(timezone.utc)]
|