import logging import typing as t from enum import Enum from peewee import ( ForeignKeyField, CharField, IntegerField, DoesNotExist, ) from app.classes.models.base_model import BaseModel from app.classes.models.users import Users, ApiKeys, HelperUsers from app.classes.shared.permission_helper import PermissionHelper logger = logging.getLogger(__name__) # ********************************************************************************** # User_Crafty Class # ********************************************************************************** class UserCrafty(BaseModel): user_id = ForeignKeyField(Users, backref="users_crafty") permissions = CharField(default="00000000") limit_server_creation = IntegerField(default=-1) limit_user_creation = IntegerField(default=0) limit_role_creation = IntegerField(default=0) created_server = IntegerField(default=0) created_user = IntegerField(default=0) created_role = IntegerField(default=0) class Meta: table_name = "user_crafty" # ********************************************************************************** # Crafty Permissions Class # ********************************************************************************** class EnumPermissionsCrafty(Enum): SERVER_CREATION = 0 USER_CONFIG = 1 ROLES_CONFIG = 2 class PermissionsCrafty: # ********************************************************************************** # Crafty Permissions Methods # ********************************************************************************** @staticmethod def get_permissions_list(): return list(EnumPermissionsCrafty.__members__.values()) @staticmethod def get_permissions(permissions_mask): return [ permission for permission in EnumPermissionsCrafty.__members__.values() if PermissionsCrafty.has_permission(permissions_mask, permission) ] @staticmethod def has_permission(permission_mask, permission_tested: EnumPermissionsCrafty): return permission_mask[permission_tested.value] == "1" @staticmethod def set_permission( permission_mask, permission_tested: EnumPermissionsCrafty, value ): index = permission_tested.value return permission_mask[:index] + str(value) + permission_mask[index + 1 :] @staticmethod def get_permission(permission_mask, permission_tested: EnumPermissionsCrafty): return permission_mask[permission_tested.value] @staticmethod def get_crafty_permissions_mask(user_id): # TODO: only get the permissions of the UserCrafty user_crafty = PermissionsCrafty.get_user_crafty(user_id) permissions_mask = user_crafty.permissions return permissions_mask @staticmethod def get_all_permission_quantity_list(): return {name: -1 for name in EnumPermissionsCrafty.__members__.keys()} @staticmethod def get_permission_quantity_list(user_id): user_crafty = PermissionsCrafty.get_user_crafty(user_id) quantity_list = { EnumPermissionsCrafty.SERVER_CREATION.name: user_crafty.limit_server_creation, # pylint: disable=line-too-long EnumPermissionsCrafty.USER_CONFIG.name: user_crafty.limit_user_creation, EnumPermissionsCrafty.ROLES_CONFIG.name: user_crafty.limit_role_creation, } return quantity_list # ********************************************************************************** # User_Crafty Methods # ********************************************************************************** @staticmethod def get_user_crafty(user_id): try: user_crafty = UserCrafty.get(UserCrafty.user_id == user_id) except DoesNotExist: UserCrafty.insert( { UserCrafty.user_id: user_id, UserCrafty.permissions: "000", UserCrafty.limit_server_creation: 0, UserCrafty.limit_user_creation: 0, UserCrafty.limit_role_creation: 0, UserCrafty.created_server: 0, UserCrafty.created_user: 0, UserCrafty.created_role: 0, } ).execute() user_crafty = PermissionsCrafty.get_user_crafty(user_id) return user_crafty @staticmethod def get_user_crafty_optional(user_id) -> t.Optional[UserCrafty]: try: return UserCrafty.get(UserCrafty.user_id == user_id) except DoesNotExist: return None @staticmethod def add_user_crafty(user_id, uc_permissions): user_crafty = UserCrafty.insert( {UserCrafty.user_id: user_id, UserCrafty.permissions: uc_permissions} ).execute() return user_crafty @staticmethod def add_or_update_user( user_id, permissions_mask, limit_server_creation, limit_user_creation, limit_role_creation, ): # http://docs.peewee-orm.com/en/latest/peewee/querying.html#upsert UserCrafty.replace( { UserCrafty.user_id: user_id, UserCrafty.permissions: permissions_mask, UserCrafty.limit_server_creation: limit_server_creation, UserCrafty.limit_user_creation: limit_user_creation, UserCrafty.limit_role_creation: limit_role_creation, } ).execute() @staticmethod def get_created_quantity_list(user_id): user_crafty = PermissionsCrafty.get_user_crafty(user_id) quantity_list = { EnumPermissionsCrafty.SERVER_CREATION.name: user_crafty.created_server, EnumPermissionsCrafty.USER_CONFIG.name: user_crafty.created_user, EnumPermissionsCrafty.ROLES_CONFIG.name: user_crafty.created_role, } return quantity_list @staticmethod def get_crafty_limit_value(user_id, permission): quantity_list = PermissionsCrafty.get_permission_quantity_list(user_id) return quantity_list[permission] @staticmethod def can_add_in_crafty(user_id, permission): user_crafty = PermissionsCrafty.get_user_crafty(user_id) can = PermissionsCrafty.has_permission(user_crafty.permissions, permission) limit_list = PermissionsCrafty.get_permission_quantity_list(user_id) quantity_list = PermissionsCrafty.get_created_quantity_list(user_id) return can and ( (quantity_list[permission.name] < limit_list[permission.name]) or limit_list[permission.name] == -1 ) @staticmethod def add_server_creation(user_id: int): """Increase the "Server Creation" counter for this user Args: user_id (int): The modifiable user's ID """ UserCrafty.update(created_server=UserCrafty.created_server + 1).where( UserCrafty.user_id == user_id ).execute() @staticmethod def add_user_creation(user_id): user_crafty = PermissionsCrafty.get_user_crafty(user_id) user_crafty.created_user += 1 UserCrafty.save(user_crafty) return user_crafty.created_user @staticmethod def add_role_creation(user_id): user_crafty = PermissionsCrafty.get_user_crafty(user_id) user_crafty.created_role += 1 UserCrafty.save(user_crafty) return user_crafty.created_role @staticmethod def get_api_key_permissions_list(key: ApiKeys): user = HelperUsers.get_user(key.user_id) if user["superuser"] and key.superuser: return PermissionsCrafty.get_permissions_list() else: if user["superuser"]: # User is superuser but API key isn't user_permissions_mask = "111" else: # Not superuser user_permissions_mask = PermissionsCrafty.get_crafty_permissions_mask( user["user_id"] ) key_permissions_mask: str = key.crafty_permissions permissions_mask = PermissionHelper.combine_masks( user_permissions_mask, key_permissions_mask ) permissions_list = PermissionsCrafty.get_permissions(permissions_mask) return permissions_list