From a2b711b5ac3fc4853d5ea4b7b8ed580c161b8e24 Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Mon, 16 May 2022 15:39:10 -0400 Subject: [PATCH 01/14] Add password reset to Crafty Console --- app/classes/controllers/users_controller.py | 6 +++-- app/classes/shared/command.py | 29 ++++++++++++++++++++- main.py | 2 +- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/app/classes/controllers/users_controller.py b/app/classes/controllers/users_controller.py index bce58fa9..6d13cf46 100644 --- a/app/classes/controllers/users_controller.py +++ b/app/classes/controllers/users_controller.py @@ -69,11 +69,13 @@ class UsersController: elif key == "password": if user_data["password"] is not None and user_data["password"] != "": up_data["password"] = self.helper.encode_pass(user_data["password"]) + elif key == "lang": + up_data["lang"] = user_data["lang"] + elif key == "hints": + up_data["hints"] = user_data["hints"] elif base_data[key] != user_data[key]: up_data[key] = user_data[key] up_data["last_update"] = self.helper.get_time_as_string() - up_data["lang"] = user_data["lang"] - up_data["hints"] = user_data["hints"] logger.debug(f"user: {user_data} +role:{added_roles} -role:{removed_roles}") for role in added_roles: HelperUsers.get_or_create(user_id=user_id, role_id=role) diff --git a/app/classes/shared/command.py b/app/classes/shared/command.py index f8fa8b48..92913639 100644 --- a/app/classes/shared/command.py +++ b/app/classes/shared/command.py @@ -3,6 +3,7 @@ import cmd import time import threading import logging +import getpass from app.classes.shared.console import Console from app.classes.shared.import3 import Import3 @@ -11,11 +12,13 @@ logger = logging.getLogger(__name__) class MainPrompt(cmd.Cmd): - def __init__(self, helper, tasks_manager, migration_manager): + def __init__(self, helper, tasks_manager, migration_manager, main_controller): super().__init__() self.helper = helper self.tasks_manager = tasks_manager self.migration_manager = migration_manager + self.controller = main_controller + # overrides the default Prompt self.prompt = f"Crafty Controller v{self.helper.get_version_string()} > " @@ -49,6 +52,30 @@ class MainPrompt(cmd.Cmd): else: Console.info("Unknown migration command") + def do_set_passwd(self, line): + + try: + username = str(line).lower() + user_id = self.controller.users.get_id_by_name(username) + except Exception as e: + Console.error(f"User: {line} Not Found") + return False + new_pass = getpass.getpass(prompt=f"NEW password for: {username} > ") + new_pass_conf = getpass.getpass(prompt="Re-enter your password: > ") + + if new_pass != new_pass_conf: + Console.error("Passwords do not match. Please try again.") + return False + + if len(new_pass) > 512: + Console.warning("Password Too Long") + return False + + if len(new_pass) < 6: + Console.warning("Password Too Short") + return False + self.controller.users.update_user(user_id, {"password": new_pass}) + @staticmethod def do_threads(_line): for thread in threading.enumerate(): diff --git a/main.py b/main.py index 7a0239a0..4de06eb4 100644 --- a/main.py +++ b/main.py @@ -168,7 +168,7 @@ if __name__ == "__main__": if not controller.check_system_user(): controller.add_system_user() - Crafty = MainPrompt(helper, tasks_manager, migration_manager) + Crafty = MainPrompt(helper, tasks_manager, migration_manager, controller) project_root = os.path.dirname(__file__) controller.set_project_root(project_root) From e12814d0b01c361940b28595f297d937aba10ca4 Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Tue, 17 May 2022 16:01:37 -0400 Subject: [PATCH 02/14] Appease the linter --- app/classes/shared/command.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/classes/shared/command.py b/app/classes/shared/command.py index 92913639..ced33890 100644 --- a/app/classes/shared/command.py +++ b/app/classes/shared/command.py @@ -57,7 +57,7 @@ class MainPrompt(cmd.Cmd): try: username = str(line).lower() user_id = self.controller.users.get_id_by_name(username) - except Exception as e: + except: Console.error(f"User: {line} Not Found") return False new_pass = getpass.getpass(prompt=f"NEW password for: {username} > ") From 8737c15fcff49858ba1aafb96d67faba58ed3df9 Mon Sep 17 00:00:00 2001 From: luukas Date: Wed, 18 May 2022 01:09:58 +0300 Subject: [PATCH 03/14] Add a permission matrix to the role add and edit --- .../controllers/server_perms_controller.py | 9 +- app/classes/models/server_permissions.py | 13 + app/classes/web/panel_handler.py | 106 ++++-- .../templates/panel/panel_edit_role.html | 357 ++++++++++-------- 4 files changed, 284 insertions(+), 201 deletions(-) diff --git a/app/classes/controllers/server_perms_controller.py b/app/classes/controllers/server_perms_controller.py index 3ee5ea18..95395fec 100644 --- a/app/classes/controllers/server_perms_controller.py +++ b/app/classes/controllers/server_perms_controller.py @@ -29,9 +29,8 @@ class ServerPermsController: return permissions_mask @staticmethod - def get_role_permissions(role_id): - permissions_list = PermissionsServers.get_role_permissions_list(role_id) - return permissions_list + def get_role_permissions_dict(role_id): + return PermissionsServers.get_role_permissions_dict(role_id) @staticmethod def add_role_server(server_id, role_id, rs_permissions="00000000"): @@ -71,10 +70,6 @@ class ServerPermsController: permission_mask, permission_tested, value ) - @staticmethod - def get_role_permissions_list(role_id): - return PermissionsServers.get_role_permissions_list(role_id) - @staticmethod def get_user_id_permissions_list(user_id: str, server_id: str): return PermissionsServers.get_user_id_permissions_list(user_id, server_id) diff --git a/app/classes/models/server_permissions.py b/app/classes/models/server_permissions.py index b36a275d..02a4572c 100644 --- a/app/classes/models/server_permissions.py +++ b/app/classes/models/server_permissions.py @@ -6,6 +6,7 @@ from peewee import ( CompositeKey, JOIN, ) +import typing as t from app.classes.models.base_model import BaseModel from app.classes.models.servers import Servers @@ -154,6 +155,18 @@ class PermissionsServers: permissions_list = PermissionsServers.get_permissions(permissions_mask) return permissions_list + @staticmethod + def get_role_permissions_dict(role_id): + permissions_dict: t.Dict[str, t.List[EnumPermissionsServer]] = {} + role_servers = RoleServers.select( + RoleServers.server_id, RoleServers.permissions + ).where(RoleServers.role_id == role_id) + for role_server in role_servers: + permissions_dict[ + role_server.server_id_id + ] = PermissionsServers.get_permissions(role_server.permissions) + return permissions_dict + @staticmethod def update_role_permission(role_id, server_id, permissions_mask): role_server = ( diff --git a/app/classes/web/panel_handler.py b/app/classes/web/panel_handler.py index 5c61d3ac..4c0e0746 100644 --- a/app/classes/web/panel_handler.py +++ b/app/classes/web/panel_handler.py @@ -16,8 +16,12 @@ from tornado import iostream # TZLocal is set as a hidden import on win pipeline from tzlocal import get_localzone from cron_validator import CronValidator +from app.classes.models.roles import HelperRoles -from app.classes.models.server_permissions import EnumPermissionsServer +from app.classes.models.server_permissions import ( + EnumPermissionsServer, + PermissionsServers, +) from app.classes.models.crafty_permissions import EnumPermissionsCrafty from app.classes.models.management import HelpersManagement from app.classes.shared.helpers import Helpers @@ -39,15 +43,27 @@ class PanelHandler(BaseHandler): def get_role_servers(self) -> set: servers = set() for server in self.controller.list_defined_servers(): - argument = int( - float( - bleach.clean( - self.get_argument(f"server_{server['server_id']}_access", "0") - ) + argument = self.get_argument(f"server_{server['server_id']}_access", "0") + if argument == "0": + print("doesn't exist " + f"server_{server['server_id']}_access") + continue + + permission_mask = "0" * len(EnumPermissionsServer) + for permission in self.controller.server_perms.list_defined_permissions(): + argument = self.get_argument( + f"permission_{server['server_id']}_{permission.name}", "0" ) - ) - if argument: - servers.add(server["server_id"]) + print( + "trying to get " + + f"permission_{server['server_id']}_{permission.name}" + ) + if argument == "1": + print(f"{permission.name} is 1") + permission_mask = self.controller.server_perms.set_permission( + permission_mask, permission, "1" + ) + + servers.add((server["server_id"], permission_mask)) return servers def get_perms_quantity(self) -> Tuple[str, dict]: @@ -85,19 +101,9 @@ class PanelHandler(BaseHandler): permission ) in self.controller.crafty_perms.list_defined_crafty_permissions(): argument = self.get_argument(f"permission_{permission.name}", None) - if argument is not None: + if argument is not None and argument == "1": permissions_mask = self.controller.crafty_perms.set_permission( - permissions_mask, permission, 1 if argument == "1" else 0 - ) - return permissions_mask - - def get_perms_server(self) -> str: - permissions_mask = "00000000" - for permission in self.controller.server_perms.list_defined_permissions(): - argument = self.get_argument(f"permission_{permission.name}", None) - if argument is not None: - permissions_mask = self.controller.server_perms.set_permission( - permissions_mask, permission, 1 if argument == "1" else 0 + permissions_mask, permission, "1" ) return permissions_mask @@ -1085,7 +1091,7 @@ class PanelHandler(BaseHandler): page_data[ "permissions_all" ] = self.controller.server_perms.list_defined_permissions() - page_data["permissions_list"] = set() + page_data["permissions_dict"] = {} template = "panel/panel_edit_role.html" elif page == "edit_role": @@ -1098,8 +1104,8 @@ class PanelHandler(BaseHandler): "permissions_all" ] = self.controller.server_perms.list_defined_permissions() page_data[ - "permissions_list" - ] = self.controller.server_perms.get_role_permissions(role_id) + "permissions_dict" + ] = self.controller.server_perms.get_role_permissions_dict(role_id) page_data["user-roles"] = user_roles page_data["users"] = self.controller.users.get_all_users() @@ -1999,16 +2005,43 @@ class PanelHandler(BaseHandler): return servers = self.get_role_servers() - permissions_mask = self.get_perms_server() - role_data = {"role_name": role_name, "servers": servers} - self.controller.roles.update_role( - role_id, role_data=role_data, permissions_mask=permissions_mask + # TODO: use update_role_advanced when API v2 gets merged + base_data = self.controller.roles.get_role_with_servers(role_id) + + server_ids = {server[0] for server in servers} + server_permissions_map = {server[0]: server[1] for server in servers} + + added_servers = server_ids.difference(set(base_data["servers"])) + removed_servers = set(base_data["servers"]).difference(server_ids) + same_servers = server_ids.intersection(set(base_data["servers"])) + logger.debug( + f"role: {role_id} +server:{added_servers} -server{removed_servers}" ) + for server_id in added_servers: + PermissionsServers.get_or_create( + role_id, server_id, server_permissions_map[server_id] + ) + for server_id in same_servers: + print( + f"!!same servers? {server_id} {server_permissions_map[server_id]}" + ) + PermissionsServers.update_role_permission( + role_id, server_id, server_permissions_map[server_id] + ) + if len(removed_servers) != 0: + PermissionsServers.delete_roles_permissions(role_id, removed_servers) + + up_data = { + "role_name": role_name, + "last_update": Helpers.get_time_as_string(), + } + # TODO: do the last_update on the db side + HelperRoles.update_role(role_id, up_data) self.controller.management.add_to_audit_log( exec_user["user_id"], - f"Edited role {role_name} (RID:{role_id}) with servers {servers}", + f"edited role {role_name} (RID:{role_id}) with servers {servers}", server_id=0, source_ip=self.get_remote_ip(), ) @@ -2032,22 +2065,15 @@ class PanelHandler(BaseHandler): return servers = self.get_role_servers() - permissions_mask = self.get_perms_server() role_id = self.controller.roles.add_role(role_name) - self.controller.roles.update_role( - role_id, {"servers": servers}, permissions_mask - ) + # TODO: use add_role_advanced when API v2 gets merged + for server in servers: + PermissionsServers.get_or_create(role_id, server[0], server[1]) self.controller.management.add_to_audit_log( exec_user["user_id"], - f"Added role {role_name} (RID:{role_id})", - server_id=0, - source_ip=self.get_remote_ip(), - ) - self.controller.management.add_to_audit_log( - exec_user["user_id"], - f"Edited role {role_name} (RID:{role_id}) with servers {servers}", + f"created role {role_name} (RID:{role_id})", server_id=0, source_ip=self.get_remote_ip(), ) diff --git a/app/frontend/templates/panel/panel_edit_role.html b/app/frontend/templates/panel/panel_edit_role.html index e97e081f..52442799 100644 --- a/app/frontend/templates/panel/panel_edit_role.html +++ b/app/frontend/templates/panel/panel_edit_role.html @@ -37,180 +37,229 @@
- -
-
- {% if data['new_role'] %} -
- {% else %} - - {% end %} - {% raw xsrf_form_html() %} - - + +
+
+ + {% raw xsrf_form_html() %} + + -
-
-

{{ translate('rolesConfig', 'roleTitle', data['lang']) }}

-
-
-
- - -
-
-
- -
-
-

{{ translate('rolesConfig', 'roleServers', data['lang']) }} {{ translate('rolesConfig', 'serversDesc', data['lang']) }}

-
-
-
-
- - - - - - - - - {% for server in data['servers_all'] %} - - - - - {% end %} - - -
{{ translate('rolesConfig', 'serverName', data['lang']) }}{{ translate('rolesConfig', 'serverAccess', data['lang']) }}
{{ server['server_name'] }} - {% if server['server_id'] in data['role']['servers'] %} - - {% else %} - - {% end %} -
-
-
-
-
- -
-
-

{{ translate('rolesConfig', 'rolePerms', data['lang']) }} - {{ translate('rolesConfig', 'permsServer', data['lang']) }}

-
-
-
-
- - - - - - - - - {% for permission in data['permissions_all'] %} - - - - - {% end %} - - -
{{ translate('rolesConfig', 'permName', data['lang']) }}{{ translate('rolesConfig', 'permAccess', data['lang']) }}
{{ permission.name }} - {% if permission in data['permissions_list'] %} - - {% else %} - - {% end %} -
-
-
-
-
- - - - - -
-
-
-
-

{{ translate('rolesConfig', 'roleUsers', data['lang']) }}

+
+
+

{{ translate('rolesConfig', 'roleTitle', data['lang']) }}

+
+
+
+ +
-
-
- + + + +
+
+

{{ translate('rolesConfig', 'roleServers', data['lang']) }} {{ translate('rolesConfig', 'serversDesc', data['lang']) }}

+
+
+
+
+
+ - - + + + {% for permission in data['permissions_all'] %} + + {% end %} - {% for user in data['users'] %} - {% for ruser in data['user-roles'][user.user_id] %} - {% if ruser == data['role']['role_name'] %} - - - - + {% for server in data['servers_all'] %} + + + + {% for permission in data['permissions_all'] %} + {% end %} - {% end %} + {% end %} +
{{ translate('rolesConfig', 'roleUserName', data['lang']) }}{{ translate('rolesConfig', 'serverName', data['lang']) }}
{{ translate('rolesConfig', 'serverAccess', data['lang']) }}
{{ permission.name }}
{{ user.username }} - -
{{ server['server_name'] }} + + + +
-
-
-
-
-
-

{{ translate('rolesConfig', 'roleConfigArea', data['lang']) }}

-

{{ translate('rolesConfig', 'configDesc', data['lang']) }}

-
-

- {{ translate('rolesConfig', 'created', data['lang']) }} {{ str(data['role']['created']) }} -
- {{ translate('rolesConfig', 'configUpdate', data['lang']) }} {{ str(data['role']['last_update']) }} -
-

-
-
- {% if data['new_role'] %} - {{ translate('rolesConfig', 'delRole', data['lang']) }}
- {{ translate('rolesConfig', 'doesNotExist', data['lang']) }} - {% else %} - {{ translate('rolesConfig', 'delRole', data['lang']) }} - {% end %} -
-
+
+ +
+
+

{{ translate('panelConfig', 'save', data['lang']) }}

+
+ + +
+
+ + +
+
+

{{ translate('rolesConfig', 'roleUsers', data['lang']) }}

+
+
+
+ + + + + + + + + {% for user in data['users'] %} + {% for ruser in data['user-roles'][user.user_id] %} + {% if ruser == data['role']['role_name'] %} + + + + + {% end %} + {% end %} + {% end %} + +
{{ translate('rolesConfig', 'roleUserName', data['lang']) }}
{{ user.username }} + +
+
+
+
+ +
+
+

{{ translate('rolesConfig', 'roleConfigArea', data['lang']) }}

+

{{ translate('rolesConfig', 'configDesc', data['lang']) }}

+
+

+ {{ translate('rolesConfig', 'created', data['lang']) }} {{ str(data['role']['created']) }} +
+ {{ translate('rolesConfig', 'configUpdate', data['lang']) }} {{ str(data['role']['last_update']) }} +
+

+
+
+ {% if data['new_role'] %} + {{ translate('rolesConfig', 'delRole', data['lang']) }}
+ {{ translate('rolesConfig', 'doesNotExist', data['lang']) }} + {% else %} + {{ translate('rolesConfig', 'delRole', data['lang']) }} + {% end %} +
+
- - -
@@ -233,4 +282,4 @@ -{% end %} \ No newline at end of file +{% end %} From d67711e898051497c0231b298ece673fa3e1ead3 Mon Sep 17 00:00:00 2001 From: luukas Date: Wed, 18 May 2022 13:04:38 +0300 Subject: [PATCH 04/14] Fix cq degradation: C0411 --- app/classes/models/server_permissions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/classes/models/server_permissions.py b/app/classes/models/server_permissions.py index 02a4572c..c4ed6c48 100644 --- a/app/classes/models/server_permissions.py +++ b/app/classes/models/server_permissions.py @@ -1,3 +1,4 @@ +import typing as t from enum import Enum import logging from peewee import ( @@ -6,7 +7,6 @@ from peewee import ( CompositeKey, JOIN, ) -import typing as t from app.classes.models.base_model import BaseModel from app.classes.models.servers import Servers From 3432d660ef05f61e47a767e23d2a1ea09b4e22e4 Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Thu, 19 May 2022 11:04:13 -0400 Subject: [PATCH 05/14] Expand Cron explain --- app/translations/en_EN.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/translations/en_EN.json b/app/translations/en_EN.json index dfb9d06f..6be25f00 100644 --- a/app/translations/en_EN.json +++ b/app/translations/en_EN.json @@ -389,7 +389,7 @@ "command": "Command", "command-explain": "What command do you want us to execute? Do not include the '/'", "cron": "Cron", - "cron-explain": "Enter your cron string", + "cron-explain": "Enter your cron string -- NOTE: 0 = Monday on last option.", "custom": "Custom Command", "days": "Days", "enabled": "Enabled", From e3248e865708f3417317ea22238489dc4f52e992 Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Wed, 18 May 2022 13:53:55 -0400 Subject: [PATCH 06/14] Change cron validation to allow day abbreviations --- app/classes/web/panel_handler.py | 14 +++++--------- requirements.txt | 2 +- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/app/classes/web/panel_handler.py b/app/classes/web/panel_handler.py index 5c61d3ac..a5e451ca 100644 --- a/app/classes/web/panel_handler.py +++ b/app/classes/web/panel_handler.py @@ -15,7 +15,7 @@ from tornado import iostream # TZLocal is set as a hidden import on win pipeline from tzlocal import get_localzone -from cron_validator import CronValidator +from croniter import croniter from app.classes.models.server_permissions import EnumPermissionsServer from app.classes.models.crafty_permissions import EnumPermissionsCrafty @@ -1447,11 +1447,9 @@ class PanelHandler(BaseHandler): else: interval_type = "" cron_string = bleach.clean(self.get_argument("cron", "")) - try: - CronValidator.parse(cron_string) - except Exception as e: + if not croniter.is_valid(cron_string): self.redirect( - f"/panel/error?error=INVALID FORMAT: Invalid Cron Format. {e}" + "/panel/error?error=INVALID FORMAT: Invalid Cron Format." ) return action = bleach.clean(self.get_argument("action", None)) @@ -1605,11 +1603,9 @@ class PanelHandler(BaseHandler): interval_type = "" cron_string = bleach.clean(self.get_argument("cron", "")) sch_id = self.get_argument("sch_id", None) - try: - CronValidator.parse(cron_string) - except Exception as e: + if not croniter.is_valid(cron_string): self.redirect( - f"/panel/error?error=INVALID FORMAT: Invalid Cron Format. {e}" + "/panel/error?error=INVALID FORMAT: Invalid Cron Format." ) return action = bleach.clean(self.get_argument("action", None)) diff --git a/requirements.txt b/requirements.txt index 26ecc613..83650349 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,7 +4,7 @@ argon2-cffi==20.1 bleach==4.1 cached_property==1.5.2 colorama==0.4 -cron-validator==1.0.3 +crontier==1.3.5 cryptography==3.4.8 libgravatar==1.0.0 peewee==3.13 From 12390306fd8a65c0a37ddf84f291b2a3cd3f9734 Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Wed, 18 May 2022 14:33:22 -0400 Subject: [PATCH 07/14] Add permissions checks for quantity for users/role Remove the ability to add quantities for general users. --- .../controllers/crafty_perms_controller.py | 26 ++++++++++++------- app/classes/models/crafty_permissions.py | 14 ++++++++++ app/classes/web/panel_handler.py | 15 +++++++++++ .../templates/panel/panel_edit_user.html | 5 ++-- 4 files changed, 48 insertions(+), 12 deletions(-) diff --git a/app/classes/controllers/crafty_perms_controller.py b/app/classes/controllers/crafty_perms_controller.py index 04072784..1b7fad23 100644 --- a/app/classes/controllers/crafty_perms_controller.py +++ b/app/classes/controllers/crafty_perms_controller.py @@ -35,20 +35,18 @@ class CraftyPermsController: ) @staticmethod - def can_add_user(): # Add back argument 'user_id' when you work on this - return True + def can_add_user(user_id): # Add back argument 'user_id' when you work on this # TODO: Complete if we need a User Addition limit - # return crafty_permissions.can_add_in_crafty( - # user_id, Enum_Permissions_Crafty.User_Config - # ) + return PermissionsCrafty.can_add_in_crafty( + user_id, EnumPermissionsCrafty.USER_CONFIG + ) @staticmethod - def can_add_role(): # Add back argument 'user_id' when you work on this - return True + def can_add_role(user_id): # Add back argument 'user_id' when you work on this # TODO: Complete if we need a Role Addition limit - # return crafty_permissions.can_add_in_crafty( - # user_id, Enum_Permissions_Crafty.Roles_Config - # ) + return PermissionsCrafty.can_add_in_crafty( + user_id, EnumPermissionsCrafty.ROLES_CONFIG + ) @staticmethod def list_all_crafty_permissions_quantity_limits(): @@ -68,6 +66,14 @@ class CraftyPermsController: def add_server_creation(user_id): return PermissionsCrafty.add_server_creation(user_id) + @staticmethod + def add_user_creation(user_id): + return PermissionsCrafty.add_user_creation(user_id) + + @staticmethod + def add_role_creation(user_id): + return PermissionsCrafty.add_role_creation(user_id) + @staticmethod def get_api_key_permissions_list(key: ApiKeys): return PermissionsCrafty.get_api_key_permissions_list(key) diff --git a/app/classes/models/crafty_permissions.py b/app/classes/models/crafty_permissions.py index 5d4f0461..b58b3c7d 100644 --- a/app/classes/models/crafty_permissions.py +++ b/app/classes/models/crafty_permissions.py @@ -193,6 +193,20 @@ class PermissionsCrafty: UserCrafty.save(user_crafty) return user_crafty.created_server + @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) diff --git a/app/classes/web/panel_handler.py b/app/classes/web/panel_handler.py index a5e451ca..8bee8df7 100644 --- a/app/classes/web/panel_handler.py +++ b/app/classes/web/panel_handler.py @@ -768,6 +768,7 @@ class PanelHandler(BaseHandler): page_data["user"]["last_update"] = "N/A" page_data["user"]["roles"] = set() page_data["user"]["hints"] = True + page_data["superuser"] = superuser if EnumPermissionsCrafty.USER_CONFIG not in exec_user_crafty_permissions: self.redirect( @@ -955,6 +956,7 @@ class PanelHandler(BaseHandler): page_data["role-servers"] = page_role_servers page_data["roles_all"] = self.controller.roles.get_all_roles() page_data["servers_all"] = self.controller.list_defined_servers() + page_data["superuser"] = superuser page_data[ "permissions_all" ] = self.controller.crafty_perms.list_defined_crafty_permissions() @@ -1927,6 +1929,12 @@ class PanelHandler(BaseHandler): "/panel/error?error=Unauthorized access: not a user editor" ) return + + if not self.controller.crafty_perms.can_add_user(exec_user["user_id"]): + self.redirect( + "/panel/error?error=Unauthorized access: quantity limit reached" + ) + return elif username is None or username == "": self.redirect("/panel/error?error=Invalid username") return @@ -1971,6 +1979,7 @@ class PanelHandler(BaseHandler): server_id=0, source_ip=self.get_remote_ip(), ) + self.controller.crafty_perms.add_user_creation(exec_user["user_id"]) self.redirect("/panel/panel_config") elif page == "edit_role": @@ -2018,6 +2027,11 @@ class PanelHandler(BaseHandler): "/panel/error?error=Unauthorized access: not a role editor" ) return + elif not self.controller.crafty_perms.can_add_role(exec_user["user_id"]): + self.redirect( + "/panel/error?error=Unauthorized access: quantity limit reached" + ) + return elif role_name is None or role_name == "": self.redirect("/panel/error?error=Invalid role name") return @@ -2047,6 +2061,7 @@ class PanelHandler(BaseHandler): server_id=0, source_ip=self.get_remote_ip(), ) + self.controller.crafty_perms.add_role_creation(exec_user["user_id"]) self.redirect("/panel/panel_config") else: diff --git a/app/frontend/templates/panel/panel_edit_user.html b/app/frontend/templates/panel/panel_edit_user.html index fa6f6773..c3154d7a 100644 --- a/app/frontend/templates/panel/panel_edit_user.html +++ b/app/frontend/templates/panel/panel_edit_user.html @@ -158,13 +158,14 @@
- + {% if data['superuser'] %}

{{ translate('userConfig', 'craftyPerms', data['lang']) }} - {{ translate('userConfig', 'craftyPermDesc', data['lang']) }}

+
@@ -200,7 +201,7 @@
- + {% end %}