From 0a572fba92875f06eff49446a9a6a561b61d9728 Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Sun, 17 Mar 2024 12:50:11 -0400 Subject: [PATCH 01/26] Refactor API keys "super user" to "full access" --- app/classes/models/crafty_permissions.py | 2 +- app/classes/models/server_permissions.py | 2 +- app/classes/models/users.py | 6 +++--- app/classes/web/base_handler.py | 2 +- app/classes/web/panel_handler.py | 6 +++--- app/classes/web/routes/api/users/user/api.py | 6 +++--- app/classes/web/server_handler.py | 4 ++-- app/classes/web/upload_handler.py | 6 +++--- .../panel/panel_edit_user_apikeys.html | 8 ++++---- app/migrations/20240317_apikey_full_access.py | 17 +++++++++++++++++ 10 files changed, 38 insertions(+), 21 deletions(-) create mode 100644 app/migrations/20240317_apikey_full_access.py diff --git a/app/classes/models/crafty_permissions.py b/app/classes/models/crafty_permissions.py index 7430f332..e7a159d9 100644 --- a/app/classes/models/crafty_permissions.py +++ b/app/classes/models/crafty_permissions.py @@ -187,7 +187,7 @@ class PermissionsCrafty: @staticmethod def get_api_key_permissions_list(key: ApiKeys): user = HelperUsers.get_user(key.user_id) - if user["superuser"] and key.superuser: + if user["superuser"] and key.full_access: return PermissionsCrafty.get_permissions_list() if user["superuser"]: # User is superuser but API key isn't diff --git a/app/classes/models/server_permissions.py b/app/classes/models/server_permissions.py index 56f9d8ac..12301e30 100644 --- a/app/classes/models/server_permissions.py +++ b/app/classes/models/server_permissions.py @@ -264,7 +264,7 @@ class PermissionsServers: @staticmethod def get_api_key_permissions_list(key: ApiKeys, server_id: str): user = HelperUsers.get_user(key.user_id) - if user["superuser"] and key.superuser: + if user["superuser"] and key.full_access: return PermissionsServers.get_permissions_list() roles_list = HelperUsers.get_user_roles_id(user["user_id"]) role_server = ( diff --git a/app/classes/models/users.py b/app/classes/models/users.py index e44d06fb..3f96e651 100644 --- a/app/classes/models/users.py +++ b/app/classes/models/users.py @@ -71,7 +71,7 @@ class ApiKeys(BaseModel): user_id = ForeignKeyField(Users, backref="api_token", index=True) server_permissions = CharField(default="00000000") crafty_permissions = CharField(default="000") - superuser = BooleanField(default=False) + full_access = BooleanField(default=False) class Meta: table_name = "api_keys" @@ -408,7 +408,7 @@ class HelperUsers: def add_user_api_key( name: str, user_id: str, - superuser: bool = False, + full_access: bool = False, server_permissions_mask: t.Optional[str] = None, crafty_permissions_mask: t.Optional[str] = None, ): @@ -426,7 +426,7 @@ class HelperUsers: if crafty_permissions_mask is not None else {} ), - ApiKeys.superuser: superuser, + ApiKeys.full_access: full_access, } ).execute() diff --git a/app/classes/web/base_handler.py b/app/classes/web/base_handler.py index ced6cb97..6967ebe2 100644 --- a/app/classes/web/base_handler.py +++ b/app/classes/web/base_handler.py @@ -191,7 +191,7 @@ class BaseHandler(tornado.web.RequestHandler): superuser = user["superuser"] if api_key is not None: - superuser = superuser and api_key.superuser + superuser = superuser and api_key.full_access exec_user_role = set() if superuser: diff --git a/app/classes/web/panel_handler.py b/app/classes/web/panel_handler.py index d61e3c0e..0fe7c8ae 100644 --- a/app/classes/web/panel_handler.py +++ b/app/classes/web/panel_handler.py @@ -168,7 +168,7 @@ class PanelHandler(BaseHandler): # Commented out because there is no server access control for API keys, # they just inherit from the host user # if api_key is not None: - # superuser = superuser and api_key.superuser + # superuser = superuser and api_key.full_access if server_id is None: self.redirect("/panel/error?error=Invalid Server ID") @@ -242,7 +242,7 @@ class PanelHandler(BaseHandler): api_key, _token_data, exec_user = self.current_user superuser = exec_user["superuser"] if api_key is not None: - superuser = superuser and api_key.superuser + superuser = superuser and api_key.full_access if superuser: # TODO: Figure out a better solution defined_servers = self.controller.servers.list_defined_servers() @@ -351,7 +351,7 @@ class PanelHandler(BaseHandler): "created": api_key.created, "server_permissions": api_key.server_permissions, "crafty_permissions": api_key.crafty_permissions, - "superuser": api_key.superuser, + "full_access": api_key.full_access, } if api_key is not None else None diff --git a/app/classes/web/routes/api/users/user/api.py b/app/classes/web/routes/api/users/user/api.py index 1c7635f2..960cfe32 100644 --- a/app/classes/web/routes/api/users/user/api.py +++ b/app/classes/web/routes/api/users/user/api.py @@ -75,7 +75,7 @@ class ApiUsersUserKeyHandler(BaseApiHandler): "name": key.name, "server_permissions": key.server_permissions, "crafty_permissions": key.crafty_permissions, - "superuser": key.superuser, + "full_access": key.full_access, } ) self.finish_json( @@ -99,7 +99,7 @@ class ApiUsersUserKeyHandler(BaseApiHandler): "type": "string", "pattern": "^[01]{3}$", # 8 bits, see EnumPermissionsCrafty }, - "superuser": {"type": "boolean"}, + "full_access": {"type": "boolean"}, }, "additionalProperties": False, "minProperties": 1, @@ -163,7 +163,7 @@ class ApiUsersUserKeyHandler(BaseApiHandler): key_id = self.controller.users.add_user_api_key( data["name"], user_id, - data["superuser"], + data["full_access"], data["server_permissions_mask"], data["crafty_permissions_mask"], ) diff --git a/app/classes/web/server_handler.py b/app/classes/web/server_handler.py index 545029aa..085d8626 100644 --- a/app/classes/web/server_handler.py +++ b/app/classes/web/server_handler.py @@ -30,7 +30,7 @@ class ServerHandler(BaseHandler): ) = self.current_user superuser = exec_user["superuser"] if api_key is not None: - superuser = superuser and api_key.superuser + superuser = superuser and api_key.full_access if superuser: defined_servers = self.controller.servers.list_defined_servers() @@ -124,7 +124,7 @@ class ServerHandler(BaseHandler): "created": api_key.created, "server_permissions": api_key.server_permissions, "crafty_permissions": api_key.crafty_permissions, - "superuser": api_key.superuser, + "full_access": api_key.full_access, } if api_key is not None else None diff --git a/app/classes/web/upload_handler.py b/app/classes/web/upload_handler.py index 0667dd12..747fa63b 100644 --- a/app/classes/web/upload_handler.py +++ b/app/classes/web/upload_handler.py @@ -42,7 +42,7 @@ class UploadHandler(BaseHandler): if self.upload_type == "server_import": superuser = exec_user["superuser"] if api_key is not None: - superuser = superuser and api_key.superuser + superuser = superuser and api_key.full_access user_id = exec_user["user_id"] stream_size_value = self.helper.get_setting("stream_size_GB") @@ -133,7 +133,7 @@ class UploadHandler(BaseHandler): elif self.upload_type == "background": superuser = exec_user["superuser"] if api_key is not None: - superuser = superuser and api_key.superuser + superuser = superuser and api_key.full_access user_id = exec_user["user_id"] stream_size_value = self.helper.get_setting("stream_size_GB") @@ -212,7 +212,7 @@ class UploadHandler(BaseHandler): server_id = self.get_argument("server_id", None) superuser = exec_user["superuser"] if api_key is not None: - superuser = superuser and api_key.superuser + superuser = superuser and api_key.full_access user_id = exec_user["user_id"] stream_size_value = self.helper.get_setting("stream_size_GB") diff --git a/app/frontend/templates/panel/panel_edit_user_apikeys.html b/app/frontend/templates/panel/panel_edit_user_apikeys.html index 084db0c3..772a07b7 100644 --- a/app/frontend/templates/panel/panel_edit_user_apikeys.html +++ b/app/frontend/templates/panel/panel_edit_user_apikeys.html @@ -70,7 +70,7 @@ {{ apikey.name }} {{ apikey.created.strftime('%d/%m/%Y %H:%M:%S') }} - {% if apikey.superuser %} + {% if apikey.full_access %} {{ translate('apiKeys', 'yes', data['lang']) }} @@ -158,8 +158,8 @@ - - + +
@@ -240,7 +240,7 @@ "name": formDataObject.name, "server_permissions_mask": server_permissions, "crafty_permissions_mask": crafty_permissions, - "superuser": $("#superuser").prop('checked'), + "full_access": $("#full_access").prop('checked'), }); console.log(formDataJsonString); diff --git a/app/migrations/20240317_apikey_full_access.py b/app/migrations/20240317_apikey_full_access.py new file mode 100644 index 00000000..6ae223e1 --- /dev/null +++ b/app/migrations/20240317_apikey_full_access.py @@ -0,0 +1,17 @@ +# Generated by database migrator +import peewee + + +def migrate(migrator, database, **kwargs): + migrator.rename_column("api_keys", "superuser", "full_access") + + """ + Write your migrations here. + """ + + +def rollback(migrator, database, **kwargs): + migrator.rename_column("api_keys", "full_access", "superuser") + """ + Write your rollback migrations here. + """ From 089b49c85ed73f76d75fe3543cd8aeca4fbfdb32 Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Mon, 25 Mar 2024 13:04:09 -0400 Subject: [PATCH 02/26] Disable crafty perms user does not have access to --- app/classes/web/panel_handler.py | 3 +++ app/frontend/templates/panel/panel_edit_user_apikeys.html | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/app/classes/web/panel_handler.py b/app/classes/web/panel_handler.py index 0fe7c8ae..691e1806 100644 --- a/app/classes/web/panel_handler.py +++ b/app/classes/web/panel_handler.py @@ -1356,6 +1356,9 @@ class PanelHandler(BaseHandler): page_data["crafty_permissions_all"] = ( self.controller.crafty_perms.list_defined_crafty_permissions() ) + page_data["user_crafty_permissions"] = ( + self.controller.crafty_perms.get_crafty_permissions_list(user_id) + ) if user_id is None: self.redirect("/panel/error?error=Invalid User ID") diff --git a/app/frontend/templates/panel/panel_edit_user_apikeys.html b/app/frontend/templates/panel/panel_edit_user_apikeys.html index 772a07b7..b1b179ef 100644 --- a/app/frontend/templates/panel/panel_edit_user_apikeys.html +++ b/app/frontend/templates/panel/panel_edit_user_apikeys.html @@ -148,9 +148,15 @@ }} + {% if permission in data['user_crafty_permissions'] %} + {% else %} + + {% end %} {% end %} From 39cfd40fadc1abab81de1816dc3540af1aec291d Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Mon, 1 Apr 2024 19:09:26 -0400 Subject: [PATCH 03/26] Add link to go back to dashboard on error page --- app/frontend/templates/public/error.html | 4 ++++ app/translations/en_EN.json | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/app/frontend/templates/public/error.html b/app/frontend/templates/public/error.html index f51d1dc9..1df11458 100644 --- a/app/frontend/templates/public/error.html +++ b/app/frontend/templates/public/error.html @@ -60,6 +60,10 @@ {{ translate('error', 'hereIsTheError', data['lang']) }}: {{data['error']}}

That's all the help I can give you - Godspeed

+ {{ translate('error', 'return', + data['lang'])}} +
+
{{ translate('error', 'contact', data['lang']) }}

diff --git a/app/translations/en_EN.json b/app/translations/en_EN.json index 5c48b873..da7cb02b 100644 --- a/app/translations/en_EN.json +++ b/app/translations/en_EN.json @@ -203,6 +203,7 @@ "not-downloaded": "We can't seem to find your executable file. Has it finished downloading? Are the permissions set to executable?", "portReminder": "We have detected this is the first time {} has been run. Make sure to forward port {} through your router/firewall to make this remotely accessible from the internet.", "privMsg": "and the ", + "return": "Return to Dashboard", "serverJars1": "Server JARs API unreachable. Please check", "serverJars2": "for the most up to date information.", "start-error": "Server {} failed to start with error code: {}", @@ -671,4 +672,4 @@ "webhook_body": "Webhook Body", "webhooks": "Webhooks" } -} +} \ No newline at end of file From 46970e128309bc53d8e03e316eb68769af327329 Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Sat, 6 Apr 2024 11:39:06 -0400 Subject: [PATCH 04/26] Make dash button more noticable --- app/frontend/templates/public/error.html | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/app/frontend/templates/public/error.html b/app/frontend/templates/public/error.html index 1df11458..535c1205 100644 --- a/app/frontend/templates/public/error.html +++ b/app/frontend/templates/public/error.html @@ -1,5 +1,6 @@ - + @@ -60,8 +61,9 @@ {{ translate('error', 'hereIsTheError', data['lang']) }}: {{data['error']}}

That's all the help I can give you - Godspeed

- {{ translate('error', 'return', - data['lang'])}} +

{{ translate('error', From 9bed7092d6db6d275d56614c69667db81b4c3d55 Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Sat, 6 Apr 2024 13:42:41 -0400 Subject: [PATCH 05/26] Check for API permission as well as user permission --- .../controllers/server_perms_controller.py | 25 +++++ app/classes/web/base_handler.py | 6 +- .../web/routes/api/servers/server/action.py | 13 +-- .../servers/server/backups/backup/index.py | 36 ++++--- .../api/servers/server/backups/index.py | 25 ++--- .../web/routes/api/servers/server/files.py | 96 ++++++++++--------- .../web/routes/api/servers/server/index.py | 26 ++--- .../web/routes/api/servers/server/logs.py | 13 +-- .../web/routes/api/servers/server/stdin.py | 13 +-- .../routes/api/servers/server/tasks/index.py | 13 +-- .../api/servers/server/tasks/task/index.py | 37 +++---- .../api/servers/server/webhooks/index.py | 25 ++--- .../servers/server/webhooks/webhook/index.py | 50 +++++----- 13 files changed, 221 insertions(+), 157 deletions(-) diff --git a/app/classes/controllers/server_perms_controller.py b/app/classes/controllers/server_perms_controller.py index f6632cd7..30c69ab0 100644 --- a/app/classes/controllers/server_perms_controller.py +++ b/app/classes/controllers/server_perms_controller.py @@ -17,6 +17,10 @@ class ServerPermsController: def get_server_user_list(server_id): return PermissionsServers.get_server_user_list(server_id) + @staticmethod + def get_permissions(permissions_mask): + return PermissionsServers.get_permissions(permissions_mask) + @staticmethod def list_defined_permissions(): permissions_list = PermissionsServers.get_permissions_list() @@ -61,6 +65,22 @@ class ServerPermsController: def get_permissions_mask(role_id, server_id): return PermissionsServers.get_permissions_mask(role_id, server_id) + @staticmethod + def get_lowest_api_perm_mask(user_server_permissions_mask, api_key_permssions_mask): + mask = "" + # If this isn't an API key we'll know the request came from basic + # authentication and ignore the API key permissions mask. + if not api_key_permssions_mask: + return user_server_permissions_mask + for _index, (user_perm, api_perm) in enumerate( + zip(user_server_permissions_mask, api_key_permssions_mask) + ): + if user_perm == "1" and api_perm == "1": + mask += "1" + else: + mask += "0" + return mask + @staticmethod def set_permission( permission_mask, permission_tested: EnumPermissionsServer, value @@ -82,6 +102,11 @@ class ServerPermsController: def get_api_key_permissions_list(key: ApiKeys, server_id: str): return PermissionsServers.get_api_key_permissions_list(key, server_id) + @staticmethod + def get_user_permissions_mask(user_id: str, server_id: str): + user = HelperUsers.get_user_model(user_id) + return PermissionsServers.get_user_permissions_mask(user, server_id) + @staticmethod def get_authorized_servers_stats_from_roles(user_id): user_roles = HelperUsers.get_user_roles_id(user_id) diff --git a/app/classes/web/base_handler.py b/app/classes/web/base_handler.py index 6967ebe2..7cca08e8 100644 --- a/app/classes/web/base_handler.py +++ b/app/classes/web/base_handler.py @@ -182,6 +182,7 @@ class BaseHandler(tornado.web.RequestHandler): t.List[str], bool, t.Dict[str, t.Any], + str, ] ]: try: @@ -190,9 +191,10 @@ class BaseHandler(tornado.web.RequestHandler): ) superuser = user["superuser"] + server_permissions_api_mask = "" if api_key is not None: superuser = superuser and api_key.full_access - + server_permissions_api_mask = api_key.server_permissions exec_user_role = set() if superuser: authorized_servers = self.controller.servers.get_all_defined_servers() @@ -214,6 +216,7 @@ class BaseHandler(tornado.web.RequestHandler): user["user_id"] ) ) + logger.debug(user["roles"]) for r in user["roles"]: role = self.controller.roles.get_role(r) @@ -234,6 +237,7 @@ class BaseHandler(tornado.web.RequestHandler): exec_user_role, superuser, user, + server_permissions_api_mask, ) logging.debug("Auth unsuccessful") auth_log.error( diff --git a/app/classes/web/routes/api/servers/server/action.py b/app/classes/web/routes/api/servers/server/action.py index 01ce45c4..fde71056 100644 --- a/app/classes/web/routes/api/servers/server/action.py +++ b/app/classes/web/routes/api/servers/server/action.py @@ -18,13 +18,14 @@ class ApiServersServerActionHandler(BaseApiHandler): if server_id not in [str(x["server_id"]) for x in auth_data[0]]: # if the user doesn't have access to the server, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) - - if ( - EnumPermissionsServer.COMMANDS - not in self.controller.server_perms.get_user_id_permissions_list( + mask = self.controller.server_perms.get_lowest_api_perm_mask( + self.controller.server_perms.get_user_permissions_mask( auth_data[4]["user_id"], server_id - ) - ): + ), + auth_data[5], + ) + server_permissions = self.controller.server_perms.get_permissions(mask) + if EnumPermissionsServer.COMMANDS not in server_permissions: # if the user doesn't have Commands permission, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) diff --git a/app/classes/web/routes/api/servers/server/backups/backup/index.py b/app/classes/web/routes/api/servers/server/backups/backup/index.py index 05edd3a9..3235202a 100644 --- a/app/classes/web/routes/api/servers/server/backups/backup/index.py +++ b/app/classes/web/routes/api/servers/server/backups/backup/index.py @@ -26,12 +26,14 @@ class ApiServersServerBackupsBackupIndexHandler(BaseApiHandler): auth_data = self.authenticate_user() if not auth_data: return - if ( - EnumPermissionsServer.BACKUP - not in self.controller.server_perms.get_user_id_permissions_list( + mask = self.controller.server_perms.get_lowest_api_perm_mask( + self.controller.server_perms.get_user_permissions_mask( auth_data[4]["user_id"], server_id - ) - ): + ), + auth_data[5], + ) + server_permissions = self.controller.server_perms.get_permissions(mask) + if EnumPermissionsServer.BACKUP not in server_permissions: # if the user doesn't have Schedule permission, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) self.finish_json(200, self.controller.management.get_backup_config(server_id)) @@ -41,12 +43,14 @@ class ApiServersServerBackupsBackupIndexHandler(BaseApiHandler): backup_conf = self.controller.management.get_backup_config(server_id) if not auth_data: return - if ( - EnumPermissionsServer.BACKUP - not in self.controller.server_perms.get_user_id_permissions_list( + mask = self.controller.server_perms.get_lowest_api_perm_mask( + self.controller.server_perms.get_user_permissions_mask( auth_data[4]["user_id"], server_id - ) - ): + ), + auth_data[5], + ) + server_permissions = self.controller.server_perms.get_permissions(mask) + if EnumPermissionsServer.BACKUP not in server_permissions: # if the user doesn't have Schedule permission, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) @@ -89,12 +93,14 @@ class ApiServersServerBackupsBackupIndexHandler(BaseApiHandler): auth_data = self.authenticate_user() if not auth_data: return - if ( - EnumPermissionsServer.BACKUP - not in self.controller.server_perms.get_user_id_permissions_list( + mask = self.controller.server_perms.get_lowest_api_perm_mask( + self.controller.server_perms.get_user_permissions_mask( auth_data[4]["user_id"], server_id - ) - ): + ), + auth_data[5], + ) + server_permissions = self.controller.server_perms.get_permissions(mask) + if EnumPermissionsServer.BACKUP not in server_permissions: # if the user doesn't have Schedule permission, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) diff --git a/app/classes/web/routes/api/servers/server/backups/index.py b/app/classes/web/routes/api/servers/server/backups/index.py index 9e47bcfc..865fe25a 100644 --- a/app/classes/web/routes/api/servers/server/backups/index.py +++ b/app/classes/web/routes/api/servers/server/backups/index.py @@ -42,12 +42,14 @@ class ApiServersServerBackupsIndexHandler(BaseApiHandler): auth_data = self.authenticate_user() if not auth_data: return - if ( - EnumPermissionsServer.BACKUP - not in self.controller.server_perms.get_user_id_permissions_list( + mask = self.controller.server_perms.get_lowest_api_perm_mask( + self.controller.server_perms.get_user_permissions_mask( auth_data[4]["user_id"], server_id - ) - ): + ), + auth_data[5], + ) + server_permissions = self.controller.server_perms.get_permissions(mask) + if EnumPermissionsServer.BACKUP not in server_permissions: # if the user doesn't have Schedule permission, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) self.finish_json(200, self.controller.management.get_backup_config(server_id)) @@ -82,13 +84,14 @@ class ApiServersServerBackupsIndexHandler(BaseApiHandler): if server_id not in [str(x["server_id"]) for x in auth_data[0]]: # if the user doesn't have access to the server, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) - - if ( - EnumPermissionsServer.BACKUP - not in self.controller.server_perms.get_user_id_permissions_list( + mask = self.controller.server_perms.get_lowest_api_perm_mask( + self.controller.server_perms.get_user_permissions_mask( auth_data[4]["user_id"], server_id - ) - ): + ), + auth_data[5], + ) + server_permissions = self.controller.server_perms.get_permissions(mask) + if EnumPermissionsServer.BACKUP not in server_permissions: # if the user doesn't have Schedule permission, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) diff --git a/app/classes/web/routes/api/servers/server/files.py b/app/classes/web/routes/api/servers/server/files.py index 8e70d4fe..2951ff25 100644 --- a/app/classes/web/routes/api/servers/server/files.py +++ b/app/classes/web/routes/api/servers/server/files.py @@ -80,16 +80,16 @@ class ApiServersServerFilesIndexHandler(BaseApiHandler): if server_id not in [str(x["server_id"]) for x in auth_data[0]]: # if the user doesn't have access to the server, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) - + mask = self.controller.server_perms.get_lowest_api_perm_mask( + self.controller.server_perms.get_user_permissions_mask( + auth_data[4]["user_id"], server_id + ), + auth_data[5], + ) + server_permissions = self.controller.server_perms.get_permissions(mask) if ( - EnumPermissionsServer.FILES - not in self.controller.server_perms.get_user_id_permissions_list( - auth_data[4]["user_id"], server_id - ) - and EnumPermissionsServer.BACKUP - not in self.controller.server_perms.get_user_id_permissions_list( - auth_data[4]["user_id"], server_id - ) + EnumPermissionsServer.FILES not in server_permissions + and EnumPermissionsServer.BACKUP not in server_permissions ): # if the user doesn't have Files or Backup permission, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) @@ -197,13 +197,14 @@ class ApiServersServerFilesIndexHandler(BaseApiHandler): if server_id not in [str(x["server_id"]) for x in auth_data[0]]: # if the user doesn't have access to the server, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) - - if ( - EnumPermissionsServer.FILES - not in self.controller.server_perms.get_user_id_permissions_list( + mask = self.controller.server_perms.get_lowest_api_perm_mask( + self.controller.server_perms.get_user_permissions_mask( auth_data[4]["user_id"], server_id - ) - ): + ), + auth_data[5], + ) + server_permissions = self.controller.server_perms.get_permissions(mask) + if EnumPermissionsServer.FILES not in server_permissions: # if the user doesn't have Files permission, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) try: @@ -254,13 +255,14 @@ class ApiServersServerFilesIndexHandler(BaseApiHandler): if server_id not in [str(x["server_id"]) for x in auth_data[0]]: # if the user doesn't have access to the server, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) - - if ( - EnumPermissionsServer.FILES - not in self.controller.server_perms.get_user_id_permissions_list( + mask = self.controller.server_perms.get_lowest_api_perm_mask( + self.controller.server_perms.get_user_permissions_mask( auth_data[4]["user_id"], server_id - ) - ): + ), + auth_data[5], + ) + server_permissions = self.controller.server_perms.get_permissions(mask) + if EnumPermissionsServer.FILES not in server_permissions: # if the user doesn't have Files permission, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) try: @@ -307,13 +309,14 @@ class ApiServersServerFilesIndexHandler(BaseApiHandler): if server_id not in [str(x["server_id"]) for x in auth_data[0]]: # if the user doesn't have access to the server, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) - - if ( - EnumPermissionsServer.FILES - not in self.controller.server_perms.get_user_id_permissions_list( + mask = self.controller.server_perms.get_lowest_api_perm_mask( + self.controller.server_perms.get_user_permissions_mask( auth_data[4]["user_id"], server_id - ) - ): + ), + auth_data[5], + ) + server_permissions = self.controller.server_perms.get_permissions(mask) + if EnumPermissionsServer.FILES not in server_permissions: # if the user doesn't have Files permission, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) try: @@ -373,13 +376,14 @@ class ApiServersServerFilesCreateHandler(BaseApiHandler): if server_id not in [str(x["server_id"]) for x in auth_data[0]]: # if the user doesn't have access to the server, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) - - if ( - EnumPermissionsServer.FILES - not in self.controller.server_perms.get_user_id_permissions_list( + mask = self.controller.server_perms.get_lowest_api_perm_mask( + self.controller.server_perms.get_user_permissions_mask( auth_data[4]["user_id"], server_id - ) - ): + ), + auth_data[5], + ) + server_permissions = self.controller.server_perms.get_permissions(mask) + if EnumPermissionsServer.FILES not in server_permissions: # if the user doesn't have Files permission, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) try: @@ -438,13 +442,14 @@ class ApiServersServerFilesCreateHandler(BaseApiHandler): if server_id not in [str(x["server_id"]) for x in auth_data[0]]: # if the user doesn't have access to the server, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) - - if ( - EnumPermissionsServer.FILES - not in self.controller.server_perms.get_user_id_permissions_list( + mask = self.controller.server_perms.get_lowest_api_perm_mask( + self.controller.server_perms.get_user_permissions_mask( auth_data[4]["user_id"], server_id - ) - ): + ), + auth_data[5], + ) + server_permissions = self.controller.server_perms.get_permissions(mask) + if EnumPermissionsServer.FILES not in server_permissions: # if the user doesn't have Files permission, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) try: @@ -504,13 +509,14 @@ class ApiServersServerFilesZipHandler(BaseApiHandler): if server_id not in [str(x["server_id"]) for x in auth_data[0]]: # if the user doesn't have access to the server, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) - - if ( - EnumPermissionsServer.FILES - not in self.controller.server_perms.get_user_id_permissions_list( + mask = self.controller.server_perms.get_lowest_api_perm_mask( + self.controller.server_perms.get_user_permissions_mask( auth_data[4]["user_id"], server_id - ) - ): + ), + auth_data[5], + ) + server_permissions = self.controller.server_perms.get_permissions(mask) + if EnumPermissionsServer.FILES not in server_permissions: # if the user doesn't have Files permission, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) try: diff --git a/app/classes/web/routes/api/servers/server/index.py b/app/classes/web/routes/api/servers/server/index.py index 81035bd0..9bfc3a9a 100644 --- a/app/classes/web/routes/api/servers/server/index.py +++ b/app/classes/web/routes/api/servers/server/index.py @@ -102,13 +102,14 @@ class ApiServersServerIndexHandler(BaseApiHandler): if server_id not in [str(x["server_id"]) for x in auth_data[0]]: # if the user doesn't have access to the server, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) - - if ( - EnumPermissionsServer.CONFIG - not in self.controller.server_perms.get_user_id_permissions_list( + mask = self.controller.server_perms.get_lowest_api_perm_mask( + self.controller.server_perms.get_user_permissions_mask( auth_data[4]["user_id"], server_id - ) - ): + ), + auth_data[5], + ) + server_permissions = self.controller.server_perms.get_permissions(mask) + if EnumPermissionsServer.CONFIG not in server_permissions: # if the user doesn't have Config permission, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) @@ -154,13 +155,14 @@ class ApiServersServerIndexHandler(BaseApiHandler): if server_id not in [str(x["server_id"]) for x in auth_data[0]]: # if the user doesn't have access to the server, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) - - if ( - EnumPermissionsServer.CONFIG - not in self.controller.server_perms.get_user_id_permissions_list( + mask = self.controller.server_perms.get_lowest_api_perm_mask( + self.controller.server_perms.get_user_permissions_mask( auth_data[4]["user_id"], server_id - ) - ): + ), + auth_data[5], + ) + server_permissions = self.controller.server_perms.get_permissions(mask) + if EnumPermissionsServer.CONFIG not in server_permissions: # if the user doesn't have Config permission, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) diff --git a/app/classes/web/routes/api/servers/server/logs.py b/app/classes/web/routes/api/servers/server/logs.py index 94a8a71b..eb6ede00 100644 --- a/app/classes/web/routes/api/servers/server/logs.py +++ b/app/classes/web/routes/api/servers/server/logs.py @@ -30,13 +30,14 @@ class ApiServersServerLogsHandler(BaseApiHandler): if server_id not in [str(x["server_id"]) for x in auth_data[0]]: # if the user doesn't have access to the server, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) - - if ( - EnumPermissionsServer.LOGS - not in self.controller.server_perms.get_user_id_permissions_list( + mask = self.controller.server_perms.get_lowest_api_perm_mask( + self.controller.server_perms.get_user_permissions_mask( auth_data[4]["user_id"], server_id - ) - ): + ), + auth_data[5], + ) + server_permissions = self.controller.server_perms.get_permissions(mask) + if EnumPermissionsServer.LOGS not in server_permissions: # if the user doesn't have Logs permission, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) diff --git a/app/classes/web/routes/api/servers/server/stdin.py b/app/classes/web/routes/api/servers/server/stdin.py index ba8400b7..ca2cd7d9 100644 --- a/app/classes/web/routes/api/servers/server/stdin.py +++ b/app/classes/web/routes/api/servers/server/stdin.py @@ -16,13 +16,14 @@ class ApiServersServerStdinHandler(BaseApiHandler): if server_id not in [str(x["server_id"]) for x in auth_data[0]]: # if the user doesn't have access to the server, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) - - if ( - EnumPermissionsServer.COMMANDS - not in self.controller.server_perms.get_user_id_permissions_list( + mask = self.controller.server_perms.get_lowest_api_perm_mask( + self.controller.server_perms.get_user_permissions_mask( auth_data[4]["user_id"], server_id - ) - ): + ), + auth_data[5], + ) + server_permissions = self.controller.server_perms.get_permissions(mask) + if EnumPermissionsServer.COMMANDS not in server_permissions: # if the user doesn't have Commands permission, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) diff --git a/app/classes/web/routes/api/servers/server/tasks/index.py b/app/classes/web/routes/api/servers/server/tasks/index.py index 8e98bbbe..0c03319c 100644 --- a/app/classes/web/routes/api/servers/server/tasks/index.py +++ b/app/classes/web/routes/api/servers/server/tasks/index.py @@ -78,13 +78,14 @@ class ApiServersServerTasksIndexHandler(BaseApiHandler): if server_id not in [str(x["server_id"]) for x in auth_data[0]]: # if the user doesn't have access to the server, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) - - if ( - EnumPermissionsServer.SCHEDULE - not in self.controller.server_perms.get_user_id_permissions_list( + mask = self.controller.server_perms.get_lowest_api_perm_mask( + self.controller.server_perms.get_user_permissions_mask( auth_data[4]["user_id"], server_id - ) - ): + ), + auth_data[5], + ) + server_permissions = self.controller.server_perms.get_permissions(mask) + if EnumPermissionsServer.SCHEDULE not in server_permissions: # if the user doesn't have Schedule permission, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) data["server_id"] = server_id diff --git a/app/classes/web/routes/api/servers/server/tasks/task/index.py b/app/classes/web/routes/api/servers/server/tasks/task/index.py index 742312a6..dac60762 100644 --- a/app/classes/web/routes/api/servers/server/tasks/task/index.py +++ b/app/classes/web/routes/api/servers/server/tasks/task/index.py @@ -54,12 +54,14 @@ class ApiServersServerTasksTaskIndexHandler(BaseApiHandler): auth_data = self.authenticate_user() if not auth_data: return - if ( - EnumPermissionsServer.SCHEDULE - not in self.controller.server_perms.get_user_id_permissions_list( + mask = self.controller.server_perms.get_lowest_api_perm_mask( + self.controller.server_perms.get_user_permissions_mask( auth_data[4]["user_id"], server_id - ) - ): + ), + auth_data[5], + ) + server_permissions = self.controller.server_perms.get_permissions(mask) + if EnumPermissionsServer.SCHEDULE not in server_permissions: # if the user doesn't have Schedule permission, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) self.finish_json(200, self.controller.management.get_scheduled_task(task_id)) @@ -68,12 +70,14 @@ class ApiServersServerTasksTaskIndexHandler(BaseApiHandler): auth_data = self.authenticate_user() if not auth_data: return - if ( - EnumPermissionsServer.SCHEDULE - not in self.controller.server_perms.get_user_id_permissions_list( + mask = self.controller.server_perms.get_lowest_api_perm_mask( + self.controller.server_perms.get_user_permissions_mask( auth_data[4]["user_id"], server_id - ) - ): + ), + auth_data[5], + ) + server_permissions = self.controller.server_perms.get_permissions(mask) + if EnumPermissionsServer.SCHEDULE not in server_permissions: # if the user doesn't have Schedule permission, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) @@ -120,13 +124,14 @@ class ApiServersServerTasksTaskIndexHandler(BaseApiHandler): if server_id not in [str(x["server_id"]) for x in auth_data[0]]: # if the user doesn't have access to the server, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) - - if ( - EnumPermissionsServer.SCHEDULE - not in self.controller.server_perms.get_user_id_permissions_list( + mask = self.controller.server_perms.get_lowest_api_perm_mask( + self.controller.server_perms.get_user_permissions_mask( auth_data[4]["user_id"], server_id - ) - ): + ), + auth_data[5], + ) + server_permissions = self.controller.server_perms.get_permissions(mask) + if EnumPermissionsServer.SCHEDULE not in server_permissions: # if the user doesn't have Schedule permission, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) diff --git a/app/classes/web/routes/api/servers/server/webhooks/index.py b/app/classes/web/routes/api/servers/server/webhooks/index.py index 223171c8..2557c309 100644 --- a/app/classes/web/routes/api/servers/server/webhooks/index.py +++ b/app/classes/web/routes/api/servers/server/webhooks/index.py @@ -38,12 +38,14 @@ class ApiServersServerWebhooksIndexHandler(BaseApiHandler): auth_data = self.authenticate_user() if not auth_data: return - if ( - EnumPermissionsServer.CONFIG - not in self.controller.server_perms.get_user_id_permissions_list( + mask = self.controller.server_perms.get_lowest_api_perm_mask( + self.controller.server_perms.get_user_permissions_mask( auth_data[4]["user_id"], server_id - ) - ): + ), + auth_data[5], + ) + server_permissions = self.controller.server_perms.get_permissions(mask) + if EnumPermissionsServer.CONFIG not in server_permissions: # if the user doesn't have Schedule permission, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) self.finish_json( @@ -81,13 +83,14 @@ class ApiServersServerWebhooksIndexHandler(BaseApiHandler): if server_id not in [str(x["server_id"]) for x in auth_data[0]]: # if the user doesn't have access to the server, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) - - if ( - EnumPermissionsServer.CONFIG - not in self.controller.server_perms.get_user_id_permissions_list( + mask = self.controller.server_perms.get_lowest_api_perm_mask( + self.controller.server_perms.get_user_permissions_mask( auth_data[4]["user_id"], server_id - ) - ): + ), + auth_data[5], + ) + server_permissions = self.controller.server_perms.get_permissions(mask) + if EnumPermissionsServer.CONFIG not in server_permissions: # if the user doesn't have Schedule permission, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) data["server_id"] = server_id diff --git a/app/classes/web/routes/api/servers/server/webhooks/webhook/index.py b/app/classes/web/routes/api/servers/server/webhooks/webhook/index.py index 4b58011e..c94aa975 100644 --- a/app/classes/web/routes/api/servers/server/webhooks/webhook/index.py +++ b/app/classes/web/routes/api/servers/server/webhooks/webhook/index.py @@ -39,12 +39,14 @@ class ApiServersServerWebhooksManagementIndexHandler(BaseApiHandler): auth_data = self.authenticate_user() if not auth_data: return - if ( - EnumPermissionsServer.CONFIG - not in self.controller.server_perms.get_user_id_permissions_list( + mask = self.controller.server_perms.get_lowest_api_perm_mask( + self.controller.server_perms.get_user_permissions_mask( auth_data[4]["user_id"], server_id - ) - ): + ), + auth_data[5], + ) + server_permissions = self.controller.server_perms.get_permissions(mask) + if EnumPermissionsServer.CONFIG not in server_permissions: # if the user doesn't have Schedule permission, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) if ( @@ -66,12 +68,14 @@ class ApiServersServerWebhooksManagementIndexHandler(BaseApiHandler): auth_data = self.authenticate_user() if not auth_data: return - if ( - EnumPermissionsServer.CONFIG - not in self.controller.server_perms.get_user_id_permissions_list( + mask = self.controller.server_perms.get_lowest_api_perm_mask( + self.controller.server_perms.get_user_permissions_mask( auth_data[4]["user_id"], server_id - ) - ): + ), + auth_data[5], + ) + server_permissions = self.controller.server_perms.get_permissions(mask) + if EnumPermissionsServer.CONFIG not in server_permissions: # if the user doesn't have Schedule permission, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) @@ -117,13 +121,14 @@ class ApiServersServerWebhooksManagementIndexHandler(BaseApiHandler): if server_id not in [str(x["server_id"]) for x in auth_data[0]]: # if the user doesn't have access to the server, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) - - if ( - EnumPermissionsServer.CONFIG - not in self.controller.server_perms.get_user_id_permissions_list( + mask = self.controller.server_perms.get_lowest_api_perm_mask( + self.controller.server_perms.get_user_permissions_mask( auth_data[4]["user_id"], server_id - ) - ): + ), + auth_data[5], + ) + server_permissions = self.controller.server_perms.get_permissions(mask) + if EnumPermissionsServer.CONFIG not in server_permissions: # if the user doesn't have Schedule permission, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) @@ -159,13 +164,14 @@ class ApiServersServerWebhooksManagementIndexHandler(BaseApiHandler): if server_id not in [str(x["server_id"]) for x in auth_data[0]]: # if the user doesn't have access to the server, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) - - if ( - EnumPermissionsServer.CONFIG - not in self.controller.server_perms.get_user_id_permissions_list( + mask = self.controller.server_perms.get_lowest_api_perm_mask( + self.controller.server_perms.get_user_permissions_mask( auth_data[4]["user_id"], server_id - ) - ): + ), + auth_data[5], + ) + server_permissions = self.controller.server_perms.get_permissions(mask) + if EnumPermissionsServer.CONFIG not in server_permissions: # if the user doesn't have Schedule permission, return an error return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) webhook = self.controller.management.get_webhook_by_id(webhook_id) From 5f00f9d6fa1c7db1157601078ae7330f47f9b728 Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Sat, 6 Apr 2024 13:53:38 -0400 Subject: [PATCH 06/26] Add full access translation --- app/frontend/templates/panel/panel_edit_user_apikeys.html | 4 ++-- app/translations/en_EN.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/frontend/templates/panel/panel_edit_user_apikeys.html b/app/frontend/templates/panel/panel_edit_user_apikeys.html index b1b179ef..76fa780b 100644 --- a/app/frontend/templates/panel/panel_edit_user_apikeys.html +++ b/app/frontend/templates/panel/panel_edit_user_apikeys.html @@ -58,7 +58,7 @@ {{ translate('apiKeys', 'name', data['lang']) }} {{ translate('apiKeys', 'created', data['lang']) }} - {{ translate('apiKeys', 'superUser', data['lang']) }} + {{ translate('apiKeys', 'fullAccess', data['lang']) }} {{ translate('apiKeys', 'perms', data['lang']) }} {{ translate('apiKeys', 'buttons', data['lang']) }} @@ -164,7 +164,7 @@ - +
diff --git a/app/translations/en_EN.json b/app/translations/en_EN.json index 5c48b873..cdc4cbf2 100644 --- a/app/translations/en_EN.json +++ b/app/translations/en_EN.json @@ -28,7 +28,7 @@ "permName": "Permission Name", "perms": "Permissions", "server": "Server: ", - "superUser": "Super User", + "fullAccess": "Full Access", "yes": "Yes" }, "base": { @@ -671,4 +671,4 @@ "webhook_body": "Webhook Body", "webhooks": "Webhooks" } -} +} \ No newline at end of file From 36f2256273350e5e830808721ebe773e00955b8d Mon Sep 17 00:00:00 2001 From: Analicia Abernathy Date: Sun, 7 Apr 2024 18:25:05 -0500 Subject: [PATCH 07/26] Update languages for merge 743 --- app/translations/cs_CS.json | 1 + app/translations/de_DE.json | 1 + app/translations/en_EN.json | 2 +- app/translations/es_ES.json | 1 + app/translations/fr_FR.json | 1 + app/translations/he_IL.json | 1 + app/translations/it_IT.json | 1 + app/translations/lol_EN.json | 1 + app/translations/lv_LV.json | 1 + app/translations/nl_BE.json | 1 + app/translations/pl_PL.json | 1 + app/translations/th_TH.json | 1 + app/translations/tr_TR.json | 1 + app/translations/uk_UA.json | 1 + app/translations/zh_CN.json | 1 + 15 files changed, 15 insertions(+), 1 deletion(-) diff --git a/app/translations/cs_CS.json b/app/translations/cs_CS.json index 2229d5cb..1d0ad986 100644 --- a/app/translations/cs_CS.json +++ b/app/translations/cs_CS.json @@ -218,6 +218,7 @@ "not-downloaded": "Zdá se, že nemůžeme najít váš spustitelný soubor. Bylo jeho stahování dokončeno? Jsou oprávnění nastavena na spustitelný soubor?", "portReminder": "Zjistili jsme, že server {} byl spuštěn poprvé. Ujistěte se, že jste přesměrovali port {} přes váš směrovač/firewall, aby byl tento port vzdáleně přístupný z internetu.", "privMsg": "a ", + "return": "vrátit se na hlavní stránku", "serverJars1": "Server JAR api je nepřístupná. Prosím zkontrolujte", "serverJars2": "pro aktualní informace.", "start-error": "Server {} se nepodařilo spustit s kódem chyby: {}", diff --git a/app/translations/de_DE.json b/app/translations/de_DE.json index c9ffea15..e4457765 100644 --- a/app/translations/de_DE.json +++ b/app/translations/de_DE.json @@ -203,6 +203,7 @@ "not-downloaded": "Crafty kann die auszuführende Datei nicht finden. Ist der Download abgeschlossen? Sind die Berechtigungen für Crafty korrekt?", "portReminder": "Wir haben festgestellt, dass dies das erste Mal ist, dass {} ausgeführt wurde. Stellen Sie sicher, dass Sie Port {} durch Ihren Router/Firewall weiterleiten, um den Fernzugriff aus dem Internet zu ermöglichen.", "privMsg": "und der/die/das ", + "return": "Zurück zum Dashboard", "serverJars1": "Server-JAR-API nicht erreichbar. Bitte überprüfen Sie ", "serverJars2": "um die aktuellsten Informationen zu erhalten.", "start-error": "Der Server {} konnte wegen dem Fehlercode: {} nicht gestartet werden", diff --git a/app/translations/en_EN.json b/app/translations/en_EN.json index da7cb02b..cce93d23 100644 --- a/app/translations/en_EN.json +++ b/app/translations/en_EN.json @@ -672,4 +672,4 @@ "webhook_body": "Webhook Body", "webhooks": "Webhooks" } -} \ No newline at end of file +} diff --git a/app/translations/es_ES.json b/app/translations/es_ES.json index 5f750fc7..3c4ec4db 100644 --- a/app/translations/es_ES.json +++ b/app/translations/es_ES.json @@ -203,6 +203,7 @@ "not-downloaded": "No podemos encontrar el archivo ejecutable. ¿Ha terminado de descargarse? ¿Están los permisos puestos como ejecutable?", "portReminder": "Detectamos que es la primera vez que se inicia {}. Asegúrese de configurar el puerto {} a través de su router/firewall para hacer el servidor accesible por Internet.", "privMsg": "y el ", + "return": "Volver al panel de control", "serverJars1": "API de Servidor JAR no disponible. por favor, compruebe", "serverJars2": "para la información más actualizada.", "start-error": "Servidor {} fallo al iniciar con código de error: {}", diff --git a/app/translations/fr_FR.json b/app/translations/fr_FR.json index be429c83..70228914 100644 --- a/app/translations/fr_FR.json +++ b/app/translations/fr_FR.json @@ -203,6 +203,7 @@ "not-downloaded": "Nous ne parvenons pas à trouver le fichier exécutable. A-t-il fini de Télécharger ? Les permissions permettent elles l'exécution ?", "portReminder": "Nous avons détecté que c'est la première fois que {} est exécuté. Assurez-vous de transférer le port {} via votre routeur/pare-feu pour le rendre accessible à distance depuis Internet.", "privMsg": "et le ", + "return": "Revenir au Tableau de Bord", "serverJars1": "l'API Server JARs est inaccessible. Merci de vérifier", "serverJars2": "pour les informations les plus à jour.", "start-error": "Le serveur {} n'a pas pu démarrer avec le code d'erreur : {}", diff --git a/app/translations/he_IL.json b/app/translations/he_IL.json index 7e2b1403..480300a9 100644 --- a/app/translations/he_IL.json +++ b/app/translations/he_IL.json @@ -203,6 +203,7 @@ "not-downloaded": "לא הצלחנו למצוא את קובץ ההפעלה שלך. האם זה סיים להוריד? האם ההרשאות מוגדרות בשביל הפעלה?", "portReminder": "זיהינו שזו הפעם הראשונה ש-{} מופעל. הקפידו להעביר את היציאה {} דרך הנתב/חומת האש שלכם כדי להפוך אותה לנגישה מרחוק מהאינטרנט.", "privMsg": "וה", + "return": "חזרה לפאנל", "serverJars1": "API של צנצנות השרת אינו נגיש. אנא בדוק", "serverJars2": "למידע מעודכן ביותר.", "start-error": "השרת {} לא הצליח להתחיל עם קוד שגיאה: {}", diff --git a/app/translations/it_IT.json b/app/translations/it_IT.json index adb59c7d..a13d9999 100644 --- a/app/translations/it_IT.json +++ b/app/translations/it_IT.json @@ -203,6 +203,7 @@ "not-downloaded": "We can't seem to find your executable file. Has it finished downloading? Are the permissions set to executable?", "portReminder": "We have detected this is the first time {} has been run. Make sure to forward port {} through your router/firewall to make this remotely accessible from the internet.", "privMsg": "e il ", + "return": "Torna alla pagina iniziale", "serverJars1": "API JAR del server non raggiungibile. Si prega di controllare", "serverJars2": "per informazioni più aggiornate.", "start-error": "Server {} failed to start with error code: {}", diff --git a/app/translations/lol_EN.json b/app/translations/lol_EN.json index aa07ff5f..607cac2e 100644 --- a/app/translations/lol_EN.json +++ b/app/translations/lol_EN.json @@ -203,6 +203,7 @@ "not-downloaded": "SOZ BUT I FAILDZ CAN'T SEEM TO FINDZ YOUR FISH. PLZ GIB MEZ IT. I HUNGRY.", "portReminder": "WE HAS DETECTD DIS AR TEH FURST TIEM {} IZ BEAN RUN. IF U WANTS IT ACESIBLE TO NEIGHBORHOOD CATS PLZ UNLOCK CAT_FLAP, {}, THRU UR ROUTR IF U HAS NOT DUN SO.", "privMsg": "AND THEEZ ", + "return": "Go Bak to Dashbored", "serverJars1": "CAN'T TALK TO SERVER JARS API. CHECKZ", "serverJars2": "TO SEE NEWZ STUFFZ.", "start-error": "CHAIR {} FAILD 2 START WIF OOF CODE: {}", diff --git a/app/translations/lv_LV.json b/app/translations/lv_LV.json index d337d38f..af282603 100644 --- a/app/translations/lv_LV.json +++ b/app/translations/lv_LV.json @@ -204,6 +204,7 @@ "not-downloaded": "Mēs nevaram atrast jūsu izpildāmo failu. Vai tas ir beidzis lejupielādēties? Vai tā peikļuves ir uzstādītas kā palaižamas?", "portReminder": "Mēs noteicām ka šī ir pirmā reize, kad {} ir ticis palaists. Pārliecinies izlaist portu {} cauri savam rūterim/ugunsmūrim lai padarītu šo attāli pieejamu no interneta.", "privMsg": "un ", + "return": "Atgriezties uz pārskatu", "serverJars1": "Serveru JAR API nav sasniedzams. Lūdzu pārbaudiet", "serverJars2": "priekš jaunākās informācijas.", "start-error": "Serveris {} neveiskmīgi startējās ar kļūdas kodu: {}", diff --git a/app/translations/nl_BE.json b/app/translations/nl_BE.json index d20e209c..c73fa409 100644 --- a/app/translations/nl_BE.json +++ b/app/translations/nl_BE.json @@ -203,6 +203,7 @@ "not-downloaded": "We kunnen uw uitvoerbare bestand niet vinden. Is het klaar met downloaden? Zijn de rechten ingesteld op uitvoerbaar?", "portReminder": "We hebben ontdekt dat dit de eerste keer is dat {} wordt uitgevoerd. Zorg ervoor dat u poort {} doorstuurt via uw router/firewall om deze op afstand toegankelijk te maken vanaf het internet.", "privMsg": "en de ", + "return": "Terug naar Dashboard", "serverJars1": "Server JARs API niet bereikbaar. Controleer alstublieft", "serverJars2": "voor de meest recente informatie.", "start-error": "Server {} kan niet starten met foutcode: {}", diff --git a/app/translations/pl_PL.json b/app/translations/pl_PL.json index ade8c5a5..506df608 100644 --- a/app/translations/pl_PL.json +++ b/app/translations/pl_PL.json @@ -203,6 +203,7 @@ "not-downloaded": "Nie możemy znaleść twojego pliku serwera. Czy skończył się pobierać? Czy permisje są ustawione na wykonywanle?", "portReminder": "Zauważyliśmy że to jest pierwszy raz {} kiedy był włączony. Upewnij się że otworzyłeś port {} na swoim routerze/firewallu aby korzystać z tego poza domem.", "privMsg": "i także ", + "return": "Powrót do panelu", "serverJars1": "API Server Jars jest niedostępne. Proszę sprawdź", "serverJars2": "dla najnowzsych informacji.", "start-error": "Serwer {} nie mógł się odpalić z powodu: {}", diff --git a/app/translations/th_TH.json b/app/translations/th_TH.json index bbb82dae..7114504e 100644 --- a/app/translations/th_TH.json +++ b/app/translations/th_TH.json @@ -203,6 +203,7 @@ "not-downloaded": "ดูเหมือนว่าเราจะไม่พบแฟ้มกระทำการของคุณ (.jar) ตรวจสอบให้แน่ใจว่าการดาวโหลดน์เสร็จสิ้นแล้ว, การอนุญาตถูกตั้งไปยังแฟ้มกระทำการหรือไม่?", "portReminder": "เราตรวจพบว่านี่เป็นครั้งแรกที่มีการเรียกใช้ {} ตรวจสอบให้แน่ใจว่าได้ Forward port {} ผ่านเราเตอร์/ไฟร์วอลล์ของคุณเพื่อให้สามารถเข้าถึงได้จากอินเทอร์เน็ตจากระยะไกล", "privMsg": "และ ", + "return": "ย้อนกลับไปยังแผงควบคุม", "serverJars1": "ไม่สามารถเข้าถึงเซิร์ฟเวอร์ JARs API กรุณาตรวจสอบ", "serverJars2": "เพื่อข้อมูลที่ทันสมัยที่สุด", "start-error": "เซิร์ฟเวอร์ {} ไม่สามารถเริ่มต้นได้เนื่องจากรหัสข้อผิดพลาด: {}", diff --git a/app/translations/tr_TR.json b/app/translations/tr_TR.json index cddd2a50..a6ab4df7 100644 --- a/app/translations/tr_TR.json +++ b/app/translations/tr_TR.json @@ -203,6 +203,7 @@ "not-downloaded": "Çalıştırılabilir dosyanızı bulamıyoruz. İndirme işlemi tamamlandı mı? İzinler çalıştırılabilir olarak ayarlandı mı?", "portReminder": "{} ilk kez çalıştırılıyor olduğunu tespit ettik. Bunu internetten uzaktan erişilebilir kılmak için {} bağlantı noktasını yönlendiriciniz/güvenlik duvarınız üzerinden ilettiğinizden emin olun.", "privMsg": "ve ", + "return": "Arayüze Geri Dön", "serverJars1": "Sunucu JARs API'ına erişilemiyor.", "serverJars2": "en güncel bilgilere sahiptir", "start-error": "{} sunucusu başlamatılamadı. Hata kodu: {}", diff --git a/app/translations/uk_UA.json b/app/translations/uk_UA.json index 74b683dd..5d4b9326 100644 --- a/app/translations/uk_UA.json +++ b/app/translations/uk_UA.json @@ -203,6 +203,7 @@ "not-downloaded": "Здається, ми не можемо знайти ваш виконуваний файл. Чи завершилось завантаження? Чи встановлено дозволи на виконуваний файл?", "portReminder": "Ми виявили це вперше {} був запущений. Обов’язково перенаправте порт {} через ваш маршрутизатор/брандмауер, щоб зробити це доступним з Інтернету.", "privMsg": "і ", + "return": "Повернутись до панелі", "serverJars1": "API сервера JAR недоступний. Будь ласка, перевірте", "serverJars2": "для найактуальнішої інформації.", "start-error": "Сервер {} не запустився через помилку: {}", diff --git a/app/translations/zh_CN.json b/app/translations/zh_CN.json index 0b817b7e..538950e4 100644 --- a/app/translations/zh_CN.json +++ b/app/translations/zh_CN.json @@ -203,6 +203,7 @@ "not-downloaded": "我们似乎找不到您的可执行文件。它下载完成了吗?可执行文件的权限设置正确了吗?", "portReminder": "我们检测到这是你首次运行 {}。请确保从您的路由器/防火墙转发 {} 端口,以使程序可以从公网远程访问。", "privMsg": "以及", + "return": "返回仪表板", "serverJars1": "无法访问服务器 JAR API。请检查", "serverJars2": "以获取最新信息。", "start-error": "服务器 {} 启动失败,错误代码为:{}", From ed37387fbf4565eaf2a548b13af02e2424635358 Mon Sep 17 00:00:00 2001 From: Analicia Abernathy Date: Wed, 10 Apr 2024 18:18:44 -0500 Subject: [PATCH 08/26] updated translations for branch refactor/api-key-su --- app/translations/{cs_CS_incomplete.json => cs_CS.json} | 1 + app/translations/de_DE.json | 2 ++ app/translations/en_EN.json | 4 ++-- app/translations/es_ES.json | 1 + app/translations/fr_FR.json | 1 + app/translations/he_IL.json | 1 + app/translations/{it_IT_incomplete.json => it_IT.json} | 1 + app/translations/lol_EN.json | 1 + app/translations/lv_LV.json | 1 + app/translations/nl_BE.json | 1 + app/translations/pl_PL.json | 1 + app/translations/th_TH.json | 1 + app/translations/tr_TR.json | 1 + app/translations/zh_CN.json | 1 + 14 files changed, 16 insertions(+), 2 deletions(-) rename app/translations/{cs_CS_incomplete.json => cs_CS.json} (99%) rename app/translations/{it_IT_incomplete.json => it_IT.json} (99%) diff --git a/app/translations/cs_CS_incomplete.json b/app/translations/cs_CS.json similarity index 99% rename from app/translations/cs_CS_incomplete.json rename to app/translations/cs_CS.json index 879b78cd..ebf1276f 100644 --- a/app/translations/cs_CS_incomplete.json +++ b/app/translations/cs_CS.json @@ -29,6 +29,7 @@ "perms": "Oprávnění", "server": "Server: ", "superUser": "Super uživatel", + "fullAccess": "všechno", "yes": "Ano" }, "base": { diff --git a/app/translations/de_DE.json b/app/translations/de_DE.json index c9ffea15..de8588ea 100644 --- a/app/translations/de_DE.json +++ b/app/translations/de_DE.json @@ -28,7 +28,9 @@ "permName": "Berechtigungs Name", "perms": "Berechtigungen", "server": "Server: ", + "fullAccess": "Vollzugriff", "superUser": "Super Benutzer", + "yes": "Ja" }, "base": { diff --git a/app/translations/en_EN.json b/app/translations/en_EN.json index cdc4cbf2..957cc29b 100644 --- a/app/translations/en_EN.json +++ b/app/translations/en_EN.json @@ -20,6 +20,7 @@ "created": "Created", "deleteKeyConfirmation": "Do you want to delete this API key? This cannot be undone.", "deleteKeyConfirmationTitle": "Remove API key ${keyId}?", + "fullAccess": "Full Access", "getToken": "Get A Token", "name": "Name", "nameDesc": "What would you like to call this API token? ", @@ -28,7 +29,6 @@ "permName": "Permission Name", "perms": "Permissions", "server": "Server: ", - "fullAccess": "Full Access", "yes": "Yes" }, "base": { @@ -671,4 +671,4 @@ "webhook_body": "Webhook Body", "webhooks": "Webhooks" } -} \ No newline at end of file +} diff --git a/app/translations/es_ES.json b/app/translations/es_ES.json index 5f750fc7..14c2e9ad 100644 --- a/app/translations/es_ES.json +++ b/app/translations/es_ES.json @@ -29,6 +29,7 @@ "perms": "Permisos", "server": "Servidor: ", "superUser": "Super Usuario", + "fullAccess": "Acceso completo", "yes": "Si" }, "base": { diff --git a/app/translations/fr_FR.json b/app/translations/fr_FR.json index be429c83..cd154439 100644 --- a/app/translations/fr_FR.json +++ b/app/translations/fr_FR.json @@ -29,6 +29,7 @@ "perms": "Permissions", "server": "Serveur: ", "superUser": "Super Utilisateur", + "fullAccess": "Accès Complet", "yes": "Oui" }, "base": { diff --git a/app/translations/he_IL.json b/app/translations/he_IL.json index 7e2b1403..bf17dc2d 100644 --- a/app/translations/he_IL.json +++ b/app/translations/he_IL.json @@ -27,6 +27,7 @@ "pageTitle": "של משתמש זה API עריכת מפתחות", "permName": "שם הגישה", "perms": "גישות", + "fullAccess": "גישה מלאה להכל", "server": "שרת: ", "superUser": "משתמש על", "yes": "כן" diff --git a/app/translations/it_IT_incomplete.json b/app/translations/it_IT.json similarity index 99% rename from app/translations/it_IT_incomplete.json rename to app/translations/it_IT.json index 99b29d7e..db434ffc 100644 --- a/app/translations/it_IT_incomplete.json +++ b/app/translations/it_IT.json @@ -29,6 +29,7 @@ "perms": "Permessi", "server": "Server: ", "superUser": "Super User", + "fullAccess": " Accesso completo", "yes": "Sì" }, "base": { diff --git a/app/translations/lol_EN.json b/app/translations/lol_EN.json index aa07ff5f..1a9037da 100644 --- a/app/translations/lol_EN.json +++ b/app/translations/lol_EN.json @@ -28,6 +28,7 @@ "permName": "PERMISSION NAME", "perms": "PERMISSIONS", "server": "SERVER: ", + "fullAccess": "All da Doors Open", "superUser": "SUPA DOOPA USR", "yes": "YESH!" }, diff --git a/app/translations/lv_LV.json b/app/translations/lv_LV.json index d337d38f..b76d5d94 100644 --- a/app/translations/lv_LV.json +++ b/app/translations/lv_LV.json @@ -29,6 +29,7 @@ "perms": "Atļaujas", "server": "Serveris: ", "superUser": "Super Lietotājs", + "fullAccess": "Pilna piekļuve", "yes": "Jā" }, "base": { diff --git a/app/translations/nl_BE.json b/app/translations/nl_BE.json index d20e209c..96edc5ff 100644 --- a/app/translations/nl_BE.json +++ b/app/translations/nl_BE.json @@ -29,6 +29,7 @@ "perms": "Machtigingen", "server": "Server: ", "superUser": "Supergebruiker", + "fullAccess": "Volledige toegang", "yes": "Ja" }, "base": { diff --git a/app/translations/pl_PL.json b/app/translations/pl_PL.json index ade8c5a5..b8159cf0 100644 --- a/app/translations/pl_PL.json +++ b/app/translations/pl_PL.json @@ -29,6 +29,7 @@ "perms": "Permisje", "server": "Serwer: ", "superUser": "Super użytkownik", + "fullAccess": "Pełny dostęp", "yes": "Tak" }, "base": { diff --git a/app/translations/th_TH.json b/app/translations/th_TH.json index bbb82dae..79c39e3e 100644 --- a/app/translations/th_TH.json +++ b/app/translations/th_TH.json @@ -29,6 +29,7 @@ "perms": "สิทธิ์อนุญาต", "server": "เซิร์ฟเวอร์: ", "superUser": "Super User", + "fullAccess": "เข้าถึงได้ทั้งหมด", "yes": "ใช่" }, "base": { diff --git a/app/translations/tr_TR.json b/app/translations/tr_TR.json index cddd2a50..b5fe4d89 100644 --- a/app/translations/tr_TR.json +++ b/app/translations/tr_TR.json @@ -29,6 +29,7 @@ "perms": "Yetkiler", "server": "Sunucu: ", "superUser": "Süper Kullanıcı", + "fullAccess": "Tam Erişim", "yes": "Evet" }, "base": { diff --git a/app/translations/zh_CN.json b/app/translations/zh_CN.json index 0b817b7e..31d4da98 100644 --- a/app/translations/zh_CN.json +++ b/app/translations/zh_CN.json @@ -29,6 +29,7 @@ "perms": "权限", "server": "服务器:", "superUser": "超级用户", + "fullAccess": "完全访问", "yes": "是" }, "base": { From 2a601c9f31e2bc09b4401bca0eb753ab14ef4463 Mon Sep 17 00:00:00 2001 From: Analicia Abernathy Date: Thu, 11 Apr 2024 09:16:03 -0500 Subject: [PATCH 09/26] update translations for refactor/api-key-su --- app/translations/cs_CS.json | 2 +- app/translations/de_DE.json | 3 +-- app/translations/es_ES.json | 2 +- app/translations/fr_FR.json | 2 +- app/translations/he_IL.json | 2 +- app/translations/it_IT.json | 2 +- app/translations/lol_EN.json | 2 +- app/translations/lv_LV.json | 2 +- app/translations/nl_BE.json | 2 +- app/translations/pl_PL.json | 2 +- app/translations/th_TH.json | 2 +- app/translations/tr_TR.json | 2 +- app/translations/uk_UA.json | 1 + app/translations/zh_CN.json | 2 +- 14 files changed, 14 insertions(+), 14 deletions(-) diff --git a/app/translations/cs_CS.json b/app/translations/cs_CS.json index 7a799d7b..fa5acbae 100644 --- a/app/translations/cs_CS.json +++ b/app/translations/cs_CS.json @@ -20,6 +20,7 @@ "created": "Vytvořen", "deleteKeyConfirmation": "Chcete tento API klíč odstranit? Tuto akci nelze vrátit zpět.", "deleteKeyConfirmationTitle": "Odstranit klíč API ${keyId}?", + "fullAccess": "všechno", "getToken": "Získat token", "name": "Jméno", "nameDesc": "Jak chcete nazvat tento token API? ", @@ -29,7 +30,6 @@ "perms": "Oprávnění", "server": "Server: ", "superUser": "Super uživatel", - "fullAccess": "všechno", "yes": "Ano" }, "base": { diff --git a/app/translations/de_DE.json b/app/translations/de_DE.json index de8588ea..d57292eb 100644 --- a/app/translations/de_DE.json +++ b/app/translations/de_DE.json @@ -20,6 +20,7 @@ "created": "Erstellt", "deleteKeyConfirmation": "Möchten Sie diesen API Schlüssel löschen? Diese Aktion kann nicht rückgängig gemacht werden.", "deleteKeyConfirmationTitle": "Folgenden API Schlüssel löschen: ${keyId}?", + "fullAccess": "Vollzugriff", "getToken": "Schlüssel erhalten", "name": "Name", "nameDesc": "Wie soll der API Schlüssel genannt werden? ", @@ -28,9 +29,7 @@ "permName": "Berechtigungs Name", "perms": "Berechtigungen", "server": "Server: ", - "fullAccess": "Vollzugriff", "superUser": "Super Benutzer", - "yes": "Ja" }, "base": { diff --git a/app/translations/es_ES.json b/app/translations/es_ES.json index 14c2e9ad..1c968dd6 100644 --- a/app/translations/es_ES.json +++ b/app/translations/es_ES.json @@ -20,6 +20,7 @@ "created": "Creado", "deleteKeyConfirmation": "¿Quieres eliminar esta clave de API? Esto no se puede deshacer.", "deleteKeyConfirmationTitle": "¿Eliminar la clave API ${keyId}?", + "fullAccess": "Acceso completo", "getToken": "Conseguir un Token", "name": "Nombre", "nameDesc": "¿Como te gustaría llamar a este Token de API? ", @@ -29,7 +30,6 @@ "perms": "Permisos", "server": "Servidor: ", "superUser": "Super Usuario", - "fullAccess": "Acceso completo", "yes": "Si" }, "base": { diff --git a/app/translations/fr_FR.json b/app/translations/fr_FR.json index cd154439..dd428ce3 100644 --- a/app/translations/fr_FR.json +++ b/app/translations/fr_FR.json @@ -20,6 +20,7 @@ "created": "Crée", "deleteKeyConfirmation": "Es-tu sûr de vouloir supprimer cette clé API? Tu ne pourras plus revenir en arrière.", "deleteKeyConfirmationTitle": "Supprimer la clé API ${keyId}?", + "fullAccess": "Accès Complet", "getToken": "Obtenir un Jeton", "name": "Nom", "nameDesc": "Comment appeler ce Jeton d'API ? ", @@ -29,7 +30,6 @@ "perms": "Permissions", "server": "Serveur: ", "superUser": "Super Utilisateur", - "fullAccess": "Accès Complet", "yes": "Oui" }, "base": { diff --git a/app/translations/he_IL.json b/app/translations/he_IL.json index bf17dc2d..e773755f 100644 --- a/app/translations/he_IL.json +++ b/app/translations/he_IL.json @@ -20,6 +20,7 @@ "created": "נוצר", "deleteKeyConfirmation": "האם ברצונך למחוק מפתח API זה? אי אפשר לבטל את זה.", "deleteKeyConfirmationTitle": "? ${keyId} API-להסיר את מפתח ה", + "fullAccess": "גישה מלאה להכל", "getToken": "קבלת אסימון", "name": "שם", "nameDesc": "הזה API-איך תרצו לקרוא לאסימון ה", @@ -27,7 +28,6 @@ "pageTitle": "של משתמש זה API עריכת מפתחות", "permName": "שם הגישה", "perms": "גישות", - "fullAccess": "גישה מלאה להכל", "server": "שרת: ", "superUser": "משתמש על", "yes": "כן" diff --git a/app/translations/it_IT.json b/app/translations/it_IT.json index 66a2602f..7c9adf83 100644 --- a/app/translations/it_IT.json +++ b/app/translations/it_IT.json @@ -20,6 +20,7 @@ "created": "Creato", "deleteKeyConfirmation": "Vuoi cancellare questa chiave API? Non puoi tornare indietro.", "deleteKeyConfirmationTitle": "Rimuovere la chiave API ${keyId}?", + "fullAccess": " Accesso completo", "getToken": "Prendi un Token", "name": "Nome", "nameDesc": "Come desideri chiamare questo Token API? ", @@ -29,7 +30,6 @@ "perms": "Permessi", "server": "Server: ", "superUser": "Super User", - "fullAccess": " Accesso completo", "yes": "Sì" }, "base": { diff --git a/app/translations/lol_EN.json b/app/translations/lol_EN.json index 1a9037da..fa5e8575 100644 --- a/app/translations/lol_EN.json +++ b/app/translations/lol_EN.json @@ -20,6 +20,7 @@ "created": "CREATED", "deleteKeyConfirmation": "U SURE U WANTZ TO DELETE DIS? CAN'T UNDO!", "deleteKeyConfirmationTitle": "I CAN EATZ IT??? : ${keyId}?", + "fullAccess": "All da Doors Open", "getToken": "GIT TOKEN", "name": "NAME", "nameDesc": "WUT WUD U LIEK 2 CALL DIS API TOKEN? ", @@ -28,7 +29,6 @@ "permName": "PERMISSION NAME", "perms": "PERMISSIONS", "server": "SERVER: ", - "fullAccess": "All da Doors Open", "superUser": "SUPA DOOPA USR", "yes": "YESH!" }, diff --git a/app/translations/lv_LV.json b/app/translations/lv_LV.json index b76d5d94..66e24cb0 100644 --- a/app/translations/lv_LV.json +++ b/app/translations/lv_LV.json @@ -20,6 +20,7 @@ "created": "Izveidots", "deleteKeyConfirmation": "Vai vēlies dzēst šo API atslēgu? Šo nevar atdarīt.", "deleteKeyConfirmationTitle": "Noņemt API atslēgu ${keyId}?", + "fullAccess": "Pilna piekļuve", "getToken": "Saņemt Pilnvaru (Token)", "name": "Nosaukums", "nameDesc": "Kā jūs vēlaties nosaukt šo Pilnvaru (Token)? ", @@ -29,7 +30,6 @@ "perms": "Atļaujas", "server": "Serveris: ", "superUser": "Super Lietotājs", - "fullAccess": "Pilna piekļuve", "yes": "Jā" }, "base": { diff --git a/app/translations/nl_BE.json b/app/translations/nl_BE.json index 96edc5ff..1b5d9a5f 100644 --- a/app/translations/nl_BE.json +++ b/app/translations/nl_BE.json @@ -20,6 +20,7 @@ "created": "Gecreëerd", "deleteKeyConfirmation": "Wilt u deze API sleutel verwijderen? Dit kan niet ongedaan gemaakt worden.", "deleteKeyConfirmationTitle": "API sleutel verwijderen ${keyId}?", + "fullAccess": "Volledige toegang", "getToken": "Verkrijg een Token", "name": "Naam", "nameDesc": "Hoe wilt u dit API token noemen? ", @@ -29,7 +30,6 @@ "perms": "Machtigingen", "server": "Server: ", "superUser": "Supergebruiker", - "fullAccess": "Volledige toegang", "yes": "Ja" }, "base": { diff --git a/app/translations/pl_PL.json b/app/translations/pl_PL.json index b8159cf0..bcbd6ff8 100644 --- a/app/translations/pl_PL.json +++ b/app/translations/pl_PL.json @@ -20,6 +20,7 @@ "created": "Stworzono", "deleteKeyConfirmation": "Czy chcesz usunąć ten klucz API? Nie można tego cofnąć.", "deleteKeyConfirmationTitle": "Usunąć Klucz API ${keyId}?", + "fullAccess": "Pełny dostęp", "getToken": "Zdobądź token", "name": "Nazwa", "nameDesc": "Jak chcesz nazwać ten klucz API? ", @@ -29,7 +30,6 @@ "perms": "Permisje", "server": "Serwer: ", "superUser": "Super użytkownik", - "fullAccess": "Pełny dostęp", "yes": "Tak" }, "base": { diff --git a/app/translations/th_TH.json b/app/translations/th_TH.json index 79c39e3e..ed21b959 100644 --- a/app/translations/th_TH.json +++ b/app/translations/th_TH.json @@ -20,6 +20,7 @@ "created": "สร้างเมื่อ", "deleteKeyConfirmation": "คุณต้องการลบคีย์ API นี้หรือไม่ สิ่งนี้ไม่สามารถยกเลิกได้", "deleteKeyConfirmationTitle": "ลบคีย์ API นี้ ${keyId} หรือไม่?", + "fullAccess": "เข้าถึงได้ทั้งหมด", "getToken": "แสดงโทเค็น", "name": "ชื่อ", "nameDesc": "คุณต้องการเรียกโทเค็น API นี้ว่าอะไร ? ", @@ -29,7 +30,6 @@ "perms": "สิทธิ์อนุญาต", "server": "เซิร์ฟเวอร์: ", "superUser": "Super User", - "fullAccess": "เข้าถึงได้ทั้งหมด", "yes": "ใช่" }, "base": { diff --git a/app/translations/tr_TR.json b/app/translations/tr_TR.json index b5fe4d89..74f6545e 100644 --- a/app/translations/tr_TR.json +++ b/app/translations/tr_TR.json @@ -20,6 +20,7 @@ "created": "Oluşturuldu", "deleteKeyConfirmation": "Bu API anahtarını silmek istediğine emin misin? Bu geri alınamaz.", "deleteKeyConfirmationTitle": "${keyId} API anahtarını kaldırma işlemi.", + "fullAccess": "Tam Erişim", "getToken": "Bir Token Al", "name": "Ad", "nameDesc": "Bu API tokeninin adı ne olsun?", @@ -29,7 +30,6 @@ "perms": "Yetkiler", "server": "Sunucu: ", "superUser": "Süper Kullanıcı", - "fullAccess": "Tam Erişim", "yes": "Evet" }, "base": { diff --git a/app/translations/uk_UA.json b/app/translations/uk_UA.json index 74b683dd..a4791d45 100644 --- a/app/translations/uk_UA.json +++ b/app/translations/uk_UA.json @@ -20,6 +20,7 @@ "created": "Створений", "deleteKeyConfirmation": "Ви дійсно бажаєте видалити API ключ? Це незворотня дія.", "deleteKeyConfirmationTitle": "Видалення API ключ ${keyId}?", + "fullAccess": "Повний доступ", "getToken": "Отримати Токен", "name": "Ім'я", "nameDesc": "Як ви хочете назвати даний API токен?", diff --git a/app/translations/zh_CN.json b/app/translations/zh_CN.json index 31d4da98..5e63590e 100644 --- a/app/translations/zh_CN.json +++ b/app/translations/zh_CN.json @@ -20,6 +20,7 @@ "created": "创建时间", "deleteKeyConfirmation": "您想要删除这个 API 密钥吗?此操作不能撤销。", "deleteKeyConfirmationTitle": "删除 API 密钥 ${keyId}?", + "fullAccess": "完全访问", "getToken": "获得一个令牌", "name": "名称", "nameDesc": "你想把这个 API 令牌叫做什么?", @@ -29,7 +30,6 @@ "perms": "权限", "server": "服务器:", "superUser": "超级用户", - "fullAccess": "完全访问", "yes": "是" }, "base": { From 6c28ef63278aa8fd6b9de999e8779595ae633910 Mon Sep 17 00:00:00 2001 From: Analicia Abernathy Date: Mon, 15 Apr 2024 17:48:53 -0500 Subject: [PATCH 10/26] Update cs_CS.json --- app/translations/cs_CS.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/translations/cs_CS.json b/app/translations/cs_CS.json index 2229d5cb..f12fe284 100644 --- a/app/translations/cs_CS.json +++ b/app/translations/cs_CS.json @@ -612,7 +612,7 @@ "credits": "Zásluhy", "dashboard": "Ovládací panel", "documentation": "Dokumentace", - "inApp": "V app dokumentaci", + "inApp": "V lokalní dokumentaci", "navigation": "Navigace", "newServer": "Vytvořit nový server", "servers": "Servery" From 92bd7b80c80c5f02cf0c35b3fd5ba201f888a01e Mon Sep 17 00:00:00 2001 From: --unset Date: Tue, 16 Apr 2024 10:26:09 -0400 Subject: [PATCH 11/26] Remove console log on login --- app/frontend/templates/public/login.html | 1 - 1 file changed, 1 deletion(-) diff --git a/app/frontend/templates/public/login.html b/app/frontend/templates/public/login.html index 275d2000..9c7d3f91 100644 --- a/app/frontend/templates/public/login.html +++ b/app/frontend/templates/public/login.html @@ -171,7 +171,6 @@ //Create an object from the form data entries let formDataObject = Object.fromEntries(formData.entries()); - console.log(formDataObject) let res = await fetch(`/login`, { method: 'POST', headers: { From 89b552a880b16b0bc786f46034677b9ef3f896da Mon Sep 17 00:00:00 2001 From: --unset Date: Tue, 16 Apr 2024 10:26:32 -0400 Subject: [PATCH 12/26] Redirect to /login if garbage is in query args --- app/classes/web/public_handler.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/classes/web/public_handler.py b/app/classes/web/public_handler.py index 21e2d495..a3d89d25 100644 --- a/app/classes/web/public_handler.py +++ b/app/classes/web/public_handler.py @@ -48,7 +48,10 @@ class PublicHandler(BaseHandler): } if self.request.query: - page_data["query"] = self.request.query_arguments.get("next")[0].decode() + request_query = self.request.query_arguments.get("next") + if not request_query: + self.redirect("/login") + page_data["query"] = request_query[0].decode() # sensible defaults template = "public/404.html" From 227d642546e78f3eb302c61801c504822a578cda Mon Sep 17 00:00:00 2001 From: --unset Date: Wed, 17 Apr 2024 18:03:10 -0400 Subject: [PATCH 13/26] Set audit logging to logfile instead of DB --- app/classes/logging/log_formatter.py | 54 ++++++++++++++++++++++++ app/classes/models/management.py | 61 +++++++++------------------- app/config/logging.json | 17 ++++++++ main.py | 6 +++ 4 files changed, 96 insertions(+), 42 deletions(-) create mode 100644 app/classes/logging/log_formatter.py diff --git a/app/classes/logging/log_formatter.py b/app/classes/logging/log_formatter.py new file mode 100644 index 00000000..7167ab4d --- /dev/null +++ b/app/classes/logging/log_formatter.py @@ -0,0 +1,54 @@ +import logging +import logging.config +import json +from datetime import datetime + + +class JsonEncoderStrFallback(json.JSONEncoder): + def default(self, o): + try: + return super().default(o) + except TypeError as exc: + if "not JSON serializable" in str(exc): + return str(o) + raise + + +class JsonEncoderDatetime(JsonEncoderStrFallback): + def default(self, o): + if isinstance(o, datetime): + return o.strftime("%Y-%m-%dT%H:%M:%S%z") + else: + return super().default(o) + + +class JsonFormatter(logging.Formatter): + def formatTime(self, record, datefmt=None): + """ + Override formatTime to customize the time format. + """ + timestamp = datetime.fromtimestamp(record.created) + if datefmt: + # Use the specified date format + return timestamp.strftime(datefmt) + else: + # Default date format: YYYY-MM-DD HH:MM:SS,mmm + secs = int(record.msecs) + return f"{timestamp.strftime('%Y-%m-%d %H:%M:%S')},{secs:03d}" + + def format(self, record): + log_data = { + "level": record.levelname, + "time": self.formatTime(record), + "log_msg": record.getMessage(), + } + + # Filter out standard log record attributes and include only custom ones + custom_attrs = ["user_name", "user_id", "server_id", "source_ip"] + extra_attrs = { + key: value for key, value in record.__dict__.items() if key in custom_attrs + } + + # Merge extra attributes with log data + log_data.update(extra_attrs) + return json.dumps(log_data) diff --git a/app/classes/models/management.py b/app/classes/models/management.py index ffe207c2..12eeac0b 100644 --- a/app/classes/models/management.py +++ b/app/classes/models/management.py @@ -20,6 +20,7 @@ from app.classes.shared.main_models import DatabaseShortcuts from app.classes.shared.websocket_manager import WebSocketManager logger = logging.getLogger(__name__) +auth_logger = logging.getLogger("audit_log") # ********************************************************************************** @@ -166,50 +167,26 @@ class HelpersManagement: WebSocketManager().broadcast_user(user, "notification", audit_msg) except Exception as e: logger.error(f"Error broadcasting to user {user} - {e}") - - AuditLog.insert( - { - AuditLog.user_name: user_data["username"], - AuditLog.user_id: user_id, - AuditLog.server_id: server_id, - AuditLog.log_msg: audit_msg, - AuditLog.source_ip: source_ip, - } - ).execute() - # deletes records when there's more than 300 - ordered = AuditLog.select().order_by(+AuditLog.created) - for item in ordered: - if not self.helper.get_setting("max_audit_entries"): - max_entries = 300 - else: - max_entries = self.helper.get_setting("max_audit_entries") - if AuditLog.select().count() > max_entries: - AuditLog.delete().where(AuditLog.audit_id == item.audit_id).execute() - else: - return + auth_logger.info( + str(log_msg), + extra={ + "user_name": user_data["username"], + "user_id": user_id, + "server_id": server_id, + "source_ip": source_ip, + }, + ) def add_to_audit_log_raw(self, user_name, user_id, server_id, log_msg, source_ip): - AuditLog.insert( - { - AuditLog.user_name: user_name, - AuditLog.user_id: user_id, - AuditLog.server_id: server_id, - AuditLog.log_msg: log_msg, - AuditLog.source_ip: source_ip, - } - ).execute() - # deletes records when there's more than 300 - ordered = AuditLog.select().order_by(+AuditLog.created) - for item in ordered: - # configurable through app/config/config.json - if not self.helper.get_setting("max_audit_entries"): - max_entries = 300 - else: - max_entries = self.helper.get_setting("max_audit_entries") - if AuditLog.select().count() > max_entries: - AuditLog.delete().where(AuditLog.audit_id == item.audit_id).execute() - else: - return + auth_logger.info( + str(log_msg), + extra={ + "user_name": user_name, + "user_id": user_id, + "server_id": server_id, + "source_ip": source_ip, + }, + ) @staticmethod def create_crafty_row(): diff --git a/app/config/logging.json b/app/config/logging.json index fd1173eb..d0a20cdf 100644 --- a/app/config/logging.json +++ b/app/config/logging.json @@ -14,6 +14,9 @@ "auth": { "format": "%(asctime)s - [AUTH] - %(levelname)s - %(message)s" }, + "audit": { + "()": "app.classes.logging.log_formatter.JsonFormatter" + }, "cmd_queue": { "format": "%(asctime)s - [CMD_QUEUE] - %(levelname)s - %(message)s" } @@ -70,6 +73,14 @@ "maxBytes": 10485760, "backupCount": 20, "encoding": "utf8" + }, + "audit_log_handler": { + "class": "logging.handlers.RotatingFileHandler", + "formatter": "audit", + "filename": "logs/audit.log", + "maxBytes": 10485760, + "backupCount": 20, + "encoding": "utf8" } }, "loggers": { @@ -108,6 +119,12 @@ "cmd_queue_file_handler" ], "propagate": false + }, + "audit_log": { + "level": "INFO", + "handlers": [ + "audit_log_handler" + ] } } } \ No newline at end of file diff --git a/main.py b/main.py index ebaf7806..f8a4aab1 100644 --- a/main.py +++ b/main.py @@ -17,6 +17,7 @@ from app.classes.models.users import HelperUsers from app.classes.models.management import HelpersManagement from app.classes.shared.import_helper import ImportHelpers from app.classes.shared.websocket_manager import WebSocketManager +from app.classes.logging.log_formatter import JsonFormatter console = Console() helper = Helpers() @@ -284,6 +285,11 @@ def setup_logging(debug=True): logging.config.dictConfig(logging_config) + # Apply JSON formatting to the "audit" handler + for handler in logging.getLogger().handlers: + if handler.name == "audit_log_handler": + handler.setFormatter(JsonFormatter()) + else: logging.basicConfig(level=logging.DEBUG) logging.warning(f"Unable to read logging config from {logging_config_file}") From 92dfd18dbd923cdff7eb456e70cc8bab745ceed3 Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Sat, 20 Apr 2024 15:47:34 -0400 Subject: [PATCH 14/26] Refactor API for new activity log format --- app/classes/web/routes/api/crafty/clogs/index.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/app/classes/web/routes/api/crafty/clogs/index.py b/app/classes/web/routes/api/crafty/clogs/index.py index 97a24a34..f42d7e2c 100644 --- a/app/classes/web/routes/api/crafty/clogs/index.py +++ b/app/classes/web/routes/api/crafty/clogs/index.py @@ -1,3 +1,5 @@ +import os +import json from app.classes.web.base_api_handler import BaseApiHandler @@ -22,9 +24,17 @@ class ApiCraftyLogIndexHandler(BaseApiHandler): raise NotImplementedError if log_type == "audit": + with open( + os.path.join(self.controller.project_root, "logs", "audit.log"), + "r", + encoding="utf-8", + ) as f: + log_lines = [json.loads(line) for line in f] + rev_log_lines = log_lines[::-1] + return self.finish_json( 200, - {"status": "ok", "data": self.controller.management.get_activity_log()}, + {"status": "ok", "data": rev_log_lines}, ) if log_type == "session": From be2e6f5e6cbf2d87f465cce17ea6f02252a6b799 Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Sat, 20 Apr 2024 15:47:50 -0400 Subject: [PATCH 15/26] Update acttivity log page to use new format --- .../templates/panel/activity_logs.html | 76 ++++++++++++------- 1 file changed, 49 insertions(+), 27 deletions(-) diff --git a/app/frontend/templates/panel/activity_logs.html b/app/frontend/templates/panel/activity_logs.html index 389edaf5..27f0459c 100644 --- a/app/frontend/templates/panel/activity_logs.html +++ b/app/frontend/templates/panel/activity_logs.html @@ -36,25 +36,14 @@ - - - - - + + + + + - {% for row in data['audit_logs'] %} - - - - - - - - {% end %}
UsernameTimeActionServer IDIPTimeUsernameActionServer IDIP
{{ row['user_name'] }} - {{ row['created'].strftime('%Y-%m-%d %H:%M:%S') }} - {{ row['log_msg'] }}{{ row['server_id'] }}{{ row['source_ip'] }}
@@ -79,17 +68,6 @@ {% end %} {% block js %} - {% end %} \ No newline at end of file From 37373733d905d759859d7d04cf0af828f7847bc4 Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Sat, 20 Apr 2024 16:07:58 -0400 Subject: [PATCH 16/26] Add loading splash screen --- .../templates/panel/activity_logs.html | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/app/frontend/templates/panel/activity_logs.html b/app/frontend/templates/panel/activity_logs.html index 27f0459c..45ab3a79 100644 --- a/app/frontend/templates/panel/activity_logs.html +++ b/app/frontend/templates/panel/activity_logs.html @@ -44,6 +44,13 @@ + + + Crafty Logo, Crafty is loading

{{ translate('datatables', + 'loadingRecords', data['lang'])}} + + @@ -134,6 +141,26 @@ bootbox.alert(responseData.error) } } + + function rotateImage(degree) { + $('#logo-animate').animate({ transform: degree }, { + step: function (now, fx) { + $(this).css({ + '-webkit-transform': 'rotate(' + now + 'deg)', + '-moz-transform': 'rotate(' + now + 'deg)', + 'transform': 'rotate(' + now + 'deg)' + }); + } + }); + setTimeout(function () { + rotateImage(360); + }, 2000); + } + $(document).ready(function () { + setTimeout(function () { + rotateImage(360); + }, 2000); + }); {% end %} \ No newline at end of file From 038f275388c136603463e6e8ea2f0aa234184dd0 Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Sat, 20 Apr 2024 16:08:16 -0400 Subject: [PATCH 17/26] Restructure translation json --- app/translations/cs_CS.json | 3 ++- app/translations/de_DE.json | 3 ++- app/translations/en_EN.json | 3 ++- app/translations/es_ES.json | 3 ++- app/translations/fi_FI_incomplete.json | 3 ++- app/translations/fr_FR.json | 3 ++- app/translations/fy_NL_incomplete.json | 3 ++- app/translations/he_IL.json | 3 ++- app/translations/hr_HR_incomplete.json | 3 ++- app/translations/id_ID_incomplete.json | 3 ++- app/translations/it_IT.json | 3 ++- app/translations/lol_EN.json | 3 ++- app/translations/lv_LV.json | 3 ++- app/translations/nl_BE.json | 3 ++- app/translations/nl_NL_incomplete.json | 3 ++- app/translations/pl_PL.json | 3 ++- app/translations/pt_BR_incomplete.json | 3 ++- app/translations/th_TH.json | 3 ++- app/translations/tr_TR.json | 3 ++- app/translations/uk_UA.json | 3 ++- app/translations/zh_CN.json | 3 ++- 21 files changed, 42 insertions(+), 21 deletions(-) diff --git a/app/translations/cs_CS.json b/app/translations/cs_CS.json index 2229d5cb..0e12dc11 100644 --- a/app/translations/cs_CS.json +++ b/app/translations/cs_CS.json @@ -116,6 +116,7 @@ "welcome": "Vítejte v Crafty Controlleru" }, "datatables": { + "loadingRecords": "Načítání...", "i18n": { "aria": { "sortAscending": ": aktivace řazení sloupce vzestupně", @@ -691,4 +692,4 @@ "webhook_body": "Webhook Body", "webhooks": "Webhooky" } -} +} \ No newline at end of file diff --git a/app/translations/de_DE.json b/app/translations/de_DE.json index c9ffea15..2ebd902f 100644 --- a/app/translations/de_DE.json +++ b/app/translations/de_DE.json @@ -116,6 +116,7 @@ "welcome": "Willkommen bei Crafty Controller" }, "datatables": { + "loadingRecords": "Laden...", "i18n": { "aria": { "sortAscending": ": Aktivieren, um die Spalte aufsteigend zu sortieren", @@ -672,4 +673,4 @@ "webhook_body": "Webhook-Inhalt", "webhooks": "Webhooks" } -} +} \ No newline at end of file diff --git a/app/translations/en_EN.json b/app/translations/en_EN.json index 5c48b873..91ff2f17 100644 --- a/app/translations/en_EN.json +++ b/app/translations/en_EN.json @@ -116,6 +116,7 @@ "welcome": "Welcome to Crafty Controller" }, "datatables": { + "loadingRecords": "Loading...", "i18n": { "aria": { "sortAscending": ": activate to sort column ascending", @@ -671,4 +672,4 @@ "webhook_body": "Webhook Body", "webhooks": "Webhooks" } -} +} \ No newline at end of file diff --git a/app/translations/es_ES.json b/app/translations/es_ES.json index 5f750fc7..e59458e7 100644 --- a/app/translations/es_ES.json +++ b/app/translations/es_ES.json @@ -116,6 +116,7 @@ "welcome": "Bienvenido a Crafty Controller" }, "datatables": { + "loadingRecords": "Cargando...", "i18n": { "aria": { "sortAscending": ": activar para ordenar las columnas de manera ascendente", @@ -672,4 +673,4 @@ "webhook_body": "Cuerpo del Webhook", "webhooks": "Webhooks" } -} +} \ No newline at end of file diff --git a/app/translations/fi_FI_incomplete.json b/app/translations/fi_FI_incomplete.json index 55cd990c..8d6168a6 100644 --- a/app/translations/fi_FI_incomplete.json +++ b/app/translations/fi_FI_incomplete.json @@ -100,6 +100,7 @@ "welcome": "Tervetuloa Crafty Controller" }, "datatables": { + "loadingRecords": "Ladataan...", "i18n": { "aria": { "sortAscending": ": lajittele sarake nousevasti", @@ -560,4 +561,4 @@ "userSettings": "Käyttäjäasetukset", "uses": "Sallittujen käyttäkertojen määtä (-1 == Ei rajaa)" } -} +} \ No newline at end of file diff --git a/app/translations/fr_FR.json b/app/translations/fr_FR.json index be429c83..1014f44f 100644 --- a/app/translations/fr_FR.json +++ b/app/translations/fr_FR.json @@ -116,6 +116,7 @@ "welcome": "Bienvenue sur Crafty Controller" }, "datatables": { + "loadingRecords": "Chargement ...", "i18n": { "aria": { "sortAscending": ": activer pour trier les colonnes dans l'ordre croissant", @@ -672,4 +673,4 @@ "webhook_body": "Corps du Webhook", "webhooks": "Webhooks" } -} +} \ No newline at end of file diff --git a/app/translations/fy_NL_incomplete.json b/app/translations/fy_NL_incomplete.json index 98785a2b..6c5d76e8 100644 --- a/app/translations/fy_NL_incomplete.json +++ b/app/translations/fy_NL_incomplete.json @@ -99,6 +99,7 @@ "welcome": "Wolkom by Crafty Controller" }, "datatables": { + "loadingRecords": "Laden...", "i18n": { "aria": { "sortAscending": ": aktivearje om kolom oprinnend te sortearjen", @@ -529,4 +530,4 @@ "userSettings": "Brûkersynstellingen", "uses": "Oantal gebrûk tastien (-1==Gjin limyt)" } -} +} \ No newline at end of file diff --git a/app/translations/he_IL.json b/app/translations/he_IL.json index 7e2b1403..ce08bb01 100644 --- a/app/translations/he_IL.json +++ b/app/translations/he_IL.json @@ -116,6 +116,7 @@ "welcome": "ברוכים הבאים ל-פאנל קראפטי" }, "datatables": { + "loadingRecords": "...טוען", "i18n": { "aria": { "sortAscending": ": הפעילו כדי למיין עמודות בסדר עולה", @@ -672,4 +673,4 @@ "webhook_body": "גוף ה-Webhook", "webhooks": "Webhooks" } -} +} \ No newline at end of file diff --git a/app/translations/hr_HR_incomplete.json b/app/translations/hr_HR_incomplete.json index 3f63770f..392ee098 100644 --- a/app/translations/hr_HR_incomplete.json +++ b/app/translations/hr_HR_incomplete.json @@ -99,6 +99,7 @@ "welcome": "Dobrodošli u Crafty Controller" }, "datatables": { + "loadingRecords": "Učitavanje...", "i18n": { "aria": { "sortAscending": ": aktiviraj za sortiranje stupca uzlazno", @@ -529,4 +530,4 @@ "userSettings": "Korisničke postavke", "uses": "Broj dopuštenih upotreba (-1==Bez ograničenja)" } -} +} \ No newline at end of file diff --git a/app/translations/id_ID_incomplete.json b/app/translations/id_ID_incomplete.json index cfec5557..c2e8813d 100644 --- a/app/translations/id_ID_incomplete.json +++ b/app/translations/id_ID_incomplete.json @@ -100,6 +100,7 @@ "welcome": "Selamat Datang Di Crafty Controller" }, "datatables": { + "loadingRecords": "Loading...", "i18n": { "aria": { "sortAscending": ": aktifkan untuk mengurutkan kolom menaik", @@ -536,4 +537,4 @@ "userSettings": "Pengaturan Pengguna", "uses": "Jumlah penggunaan yang diizinkan (-1==No Limit)" } -} +} \ No newline at end of file diff --git a/app/translations/it_IT.json b/app/translations/it_IT.json index adb59c7d..f2613f22 100644 --- a/app/translations/it_IT.json +++ b/app/translations/it_IT.json @@ -116,6 +116,7 @@ "welcome": "Benvenuto su Crafty Controller" }, "datatables": { + "loadingRecords": "Carico...", "i18n": { "aria": { "sortAscending": ": attiva per ordinare le colonne in modo ascendente", @@ -672,4 +673,4 @@ "webhook_body": "Corpo del Webhook", "webhooks": "Webhook" } -} +} \ No newline at end of file diff --git a/app/translations/lol_EN.json b/app/translations/lol_EN.json index aa07ff5f..038608a5 100644 --- a/app/translations/lol_EN.json +++ b/app/translations/lol_EN.json @@ -116,6 +116,7 @@ "welcome": "WELCOM 2 CWAFTY CONTROLLR" }, "datatables": { + "loadingRecords": "Loading...", "i18n": { "aria": { "sortAscending": ": activate to sort column ascending", @@ -672,4 +673,4 @@ "webhook_body": "WEBHOOK FISH", "webhooks": "WEBHOOKZ" } -} +} \ No newline at end of file diff --git a/app/translations/lv_LV.json b/app/translations/lv_LV.json index d337d38f..02974c8c 100644 --- a/app/translations/lv_LV.json +++ b/app/translations/lv_LV.json @@ -117,6 +117,7 @@ "welcome": "Esiet sveicināts Crafty Controller" }, "datatables": { + "loadingRecords": "Ielādē...", "i18n": { "aria": { "sortAscending": ": aktivizēt lai kārotu kolonnu augoši", @@ -673,4 +674,4 @@ "webhook_body": "Webhook Saturs", "webhooks": "Webhooki" } -} +} \ No newline at end of file diff --git a/app/translations/nl_BE.json b/app/translations/nl_BE.json index d20e209c..428c0323 100644 --- a/app/translations/nl_BE.json +++ b/app/translations/nl_BE.json @@ -116,6 +116,7 @@ "welcome": "Welkom bij Crafty Controller " }, "datatables": { + "loadingRecords": "Bezig met laden...", "i18n": { "aria": { "sortAscending": ": activeren om kolom oplopend te sorteren", @@ -672,4 +673,4 @@ "webhook_body": "Webhook-body", "webhooks": "Webhooks" } -} +} \ No newline at end of file diff --git a/app/translations/nl_NL_incomplete.json b/app/translations/nl_NL_incomplete.json index 8fd97240..1d158594 100644 --- a/app/translations/nl_NL_incomplete.json +++ b/app/translations/nl_NL_incomplete.json @@ -99,6 +99,7 @@ "welcome": "Welkom bij Crafty Controller" }, "datatables": { + "loadingRecords": "Laden...", "i18n": { "aria": { "sortAscending": ": activeer om kolom oplopend te sorteren", @@ -529,4 +530,4 @@ "userSettings": "Gebruikersinstellingen", "uses": "Aantal keer toegestaan (-1==Geen limiet)" } -} +} \ No newline at end of file diff --git a/app/translations/pl_PL.json b/app/translations/pl_PL.json index ade8c5a5..2d089607 100644 --- a/app/translations/pl_PL.json +++ b/app/translations/pl_PL.json @@ -116,6 +116,7 @@ "welcome": "Witamy w Crafty Controller" }, "datatables": { + "loadingRecords": "Wczytywanie...", "i18n": { "aria": { "sortAscending": ": aktywuj, aby sortować kolumny w góre", @@ -671,4 +672,4 @@ "webhook_body": "Treść Webhooka", "webhooks": "Webhooki" } -} +} \ No newline at end of file diff --git a/app/translations/pt_BR_incomplete.json b/app/translations/pt_BR_incomplete.json index c8844f40..dcd375f6 100644 --- a/app/translations/pt_BR_incomplete.json +++ b/app/translations/pt_BR_incomplete.json @@ -100,6 +100,7 @@ "welcome": "Bem-vindo ao Crafty Controller" }, "datatables": { + "loadingRecords": "Carregando...", "i18n": { "aria": { "sortAscending": ": ative para ordenar a coluna de forma ascendente", @@ -537,4 +538,4 @@ "userSettings": "Configurações do Usuário", "uses": "Número de Usos Permitidos (-1==Sem Limite)" } -} +} \ No newline at end of file diff --git a/app/translations/th_TH.json b/app/translations/th_TH.json index bbb82dae..e60e86e0 100644 --- a/app/translations/th_TH.json +++ b/app/translations/th_TH.json @@ -116,6 +116,7 @@ "welcome": "ยินดีต้อนรับสู่ Crafty Controller" }, "datatables": { + "loadingRecords": "กำลังโหลด...", "i18n": { "aria": { "sortAscending": ": เปิดใช้งานเพื่อเรียงลำดับคอลัมน์จากน้อยไปมาก", @@ -671,4 +672,4 @@ "webhook_body": "ภายใน Webhook", "webhooks": "Webhooks" } -} +} \ No newline at end of file diff --git a/app/translations/tr_TR.json b/app/translations/tr_TR.json index cddd2a50..c3a1bf5b 100644 --- a/app/translations/tr_TR.json +++ b/app/translations/tr_TR.json @@ -116,6 +116,7 @@ "welcome": "Crafty Controller'a Hoşgeldiniz!" }, "datatables": { + "loadingRecords": "Yükleniyor...", "i18n": { "aria": { "sortAscending": ": artan sütun sıralamasını aktifleştir", @@ -671,4 +672,4 @@ "webhook_body": "Webhook Gövdesi", "webhooks": "Webhooklar" } -} +} \ No newline at end of file diff --git a/app/translations/uk_UA.json b/app/translations/uk_UA.json index 74b683dd..116792b8 100644 --- a/app/translations/uk_UA.json +++ b/app/translations/uk_UA.json @@ -116,6 +116,7 @@ "welcome": "Ласкаво просимо у Crafty Controller" }, "datatables": { + "loadingRecords": "Завантаження...", "i18n": { "aria": { "sortAscending": ": активуйте, щоб сортувати стовпці за зростанням", @@ -671,4 +672,4 @@ "webhook_body": "Код Вебхука", "webhooks": "Вебхуки" } -} +} \ No newline at end of file diff --git a/app/translations/zh_CN.json b/app/translations/zh_CN.json index 0b817b7e..68067fb7 100644 --- a/app/translations/zh_CN.json +++ b/app/translations/zh_CN.json @@ -116,6 +116,7 @@ "welcome": "欢迎来到 Crafty Controller" }, "datatables": { + "loadingRecords": "正在加载……", "i18n": { "aria": { "sortAscending": ":激活对队列的升序排列", @@ -672,4 +673,4 @@ "webhook_body": "Webhook 消息体(Body)", "webhooks": "Webhook" } -} +} \ No newline at end of file From 3fac1a39a8095e1fd1b2e02ba730cb5801c9b579 Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Sat, 20 Apr 2024 16:21:06 -0400 Subject: [PATCH 18/26] Setup drop table migrations --- .../controllers/management_controller.py | 3 -- app/classes/models/management.py | 22 ------------ app/classes/web/panel_handler.py | 2 -- .../20240216_rework_servers_uuid.py | 19 ----------- .../20240217_rework_servers_uuid_part2.py | 30 ---------------- app/migrations/20240420_audit_log_drop.py | 34 +++++++++++++++++++ 6 files changed, 34 insertions(+), 76 deletions(-) create mode 100644 app/migrations/20240420_audit_log_drop.py diff --git a/app/classes/controllers/management_controller.py b/app/classes/controllers/management_controller.py index 7085b503..cab755b6 100644 --- a/app/classes/controllers/management_controller.py +++ b/app/classes/controllers/management_controller.py @@ -95,9 +95,6 @@ class ManagementController: # ********************************************************************************** # Audit_Log Methods # ********************************************************************************** - @staticmethod - def get_activity_log(): - return HelpersManagement.get_activity_log() def add_to_audit_log(self, user_id, log_msg, server_id=None, source_ip=None): return self.management_helper.add_to_audit_log( diff --git a/app/classes/models/management.py b/app/classes/models/management.py index 12eeac0b..38ce53b2 100644 --- a/app/classes/models/management.py +++ b/app/classes/models/management.py @@ -23,24 +23,6 @@ logger = logging.getLogger(__name__) auth_logger = logging.getLogger("audit_log") -# ********************************************************************************** -# Audit_Log Class -# ********************************************************************************** -class AuditLog(BaseModel): - audit_id = AutoField() - created = DateTimeField(default=datetime.datetime.now) - user_name = CharField(default="") - user_id = IntegerField(default=0, index=True) - source_ip = CharField(default="127.0.0.1") - server_id = ForeignKeyField( - Servers, backref="audit_server", null=True - ) # When auditing global events, use server ID null - log_msg = TextField(default="") - - class Meta: - table_name = "audit_log" - - # ********************************************************************************** # Crafty Settings Class # ********************************************************************************** @@ -150,10 +132,6 @@ class HelpersManagement: # ********************************************************************************** # Audit_Log Methods # ********************************************************************************** - @staticmethod - def get_activity_log(): - query = AuditLog.select() - return DatabaseShortcuts.return_db_rows(query) def add_to_audit_log(self, user_id, log_msg, server_id=None, source_ip=None): logger.debug(f"Adding to audit log User:{user_id} - Message: {log_msg} ") diff --git a/app/classes/web/panel_handler.py b/app/classes/web/panel_handler.py index 716671c8..dc2cc313 100644 --- a/app/classes/web/panel_handler.py +++ b/app/classes/web/panel_handler.py @@ -1503,8 +1503,6 @@ class PanelHandler(BaseHandler): template = "panel/panel_edit_role.html" elif page == "activity_logs": - page_data["audit_logs"] = self.controller.management.get_activity_log() - template = "panel/activity_logs.html" elif page == "download_file": diff --git a/app/migrations/20240216_rework_servers_uuid.py b/app/migrations/20240216_rework_servers_uuid.py index facd0e42..7850346d 100644 --- a/app/migrations/20240216_rework_servers_uuid.py +++ b/app/migrations/20240216_rework_servers_uuid.py @@ -6,7 +6,6 @@ import logging from app.classes.shared.console import Console from app.classes.shared.migration import Migrator, MigrateHistory from app.classes.models.management import ( - AuditLog, Webhooks, Schedules, Backups, @@ -61,17 +60,6 @@ def migrate(migrator: Migrator, database, **kwargs): peewee.CharField(primary_key=True, default=str(uuid.uuid4())), ) - # Changes on Audit Log Table - migrator.alter_column_type( - AuditLog, - "server_id", - peewee.ForeignKeyField( - Servers, - backref="audit_server", - null=True, - field=peewee.CharField(primary_key=True, default=str(uuid.uuid4())), - ), - ) # Changes on Webhook Table migrator.alter_column_type( Webhooks, @@ -109,13 +97,6 @@ def rollback(migrator: Migrator, database, **kwargs): peewee.AutoField(), ) - # Changes on Audit Log Table - migrator.alter_column_type( - AuditLog, - "server_id", - peewee.IntegerField(default=None, index=True), - ) - # Changes on Webhook Table migrator.alter_column_type( Webhooks, diff --git a/app/migrations/20240217_rework_servers_uuid_part2.py b/app/migrations/20240217_rework_servers_uuid_part2.py index eab04c28..a4b01c45 100644 --- a/app/migrations/20240217_rework_servers_uuid_part2.py +++ b/app/migrations/20240217_rework_servers_uuid_part2.py @@ -6,7 +6,6 @@ import logging from app.classes.shared.console import Console from app.classes.shared.migration import Migrator, MigrateHistory from app.classes.models.management import ( - AuditLog, Webhooks, Schedules, Backups, @@ -73,20 +72,6 @@ def migrate(migrator: Migrator, database, **kwargs): try: logger.info("Migrating Data from Int to UUID (Foreign Keys)") Console.info("Migrating Data from Int to UUID (Foreign Keys)") - # Changes on Audit Log Table - for audit_log in AuditLog.select(): - old_server_id = audit_log.server_id_id - if old_server_id == "0" or old_server_id is None: - server_uuid = None - else: - try: - server = Servers.get_by_id(old_server_id) - server_uuid = server.server_uuid - except: - server_uuid = old_server_id - AuditLog.update(server_id=server_uuid).where( - AuditLog.audit_id == audit_log.audit_id - ).execute() # Changes on Webhooks Log Table for webhook in Webhooks.select(): @@ -247,21 +232,6 @@ def rollback(migrator: Migrator, database, **kwargs): try: logger.info("Migrating Data from UUID to Int (Foreign Keys)") Console.info("Migrating Data from UUID to Int (Foreign Keys)") - # Changes on Audit Log Table - for audit_log in AuditLog.select(): - old_server_id = audit_log.server_id_id - if old_server_id is None: - new_server_id = 0 - else: - try: - server = Servers.get_or_none(Servers.server_uuid == old_server_id) - new_server_id = server.server_id - except: - new_server_id = old_server_id - AuditLog.update(server_id=new_server_id).where( - AuditLog.audit_id == audit_log.audit_id - ).execute() - # Changes on Webhooks Log Table for webhook in Webhooks.select(): old_server_id = webhook.server_id_id diff --git a/app/migrations/20240420_audit_log_drop.py b/app/migrations/20240420_audit_log_drop.py new file mode 100644 index 00000000..be153f11 --- /dev/null +++ b/app/migrations/20240420_audit_log_drop.py @@ -0,0 +1,34 @@ +import peewee +import datetime +from peewee import ( + AutoField, + DateTimeField, + CharField, + IntegerField, + ForeignKeyField, + TextField, +) + +from app.classes.shared.server import Servers + + +def migrate(migrator, db): + migrator.drop_table("audit_log") + + +def rollback(migrator, db): + class AuditLog(peewee.Model): + audit_id = AutoField() + created = DateTimeField(default=datetime.datetime.now) + user_name = CharField(default="") + user_id = IntegerField(default=0, index=True) + source_ip = CharField(default="127.0.0.1") + server_id = ForeignKeyField( + Servers, backref="audit_server", null=True + ) # When auditing global events, use server ID null + log_msg = TextField(default="") + + class Meta: + table_name = "audit_log" + + migrator.create_table(AuditLog) From 2134c4226de25957c7a778dc7ada93eb1e007a83 Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Sat, 20 Apr 2024 16:54:33 -0400 Subject: [PATCH 19/26] Fix audit log raw --- app/classes/models/management.py | 2 ++ app/frontend/templates/panel/activity_logs.html | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/app/classes/models/management.py b/app/classes/models/management.py index 38ce53b2..dc57816d 100644 --- a/app/classes/models/management.py +++ b/app/classes/models/management.py @@ -156,6 +156,8 @@ class HelpersManagement: ) def add_to_audit_log_raw(self, user_name, user_id, server_id, log_msg, source_ip): + if isinstance(server_id, Servers) and server_id is not None: + server_id = server_id.server_id auth_logger.info( str(log_msg), extra={ diff --git a/app/frontend/templates/panel/activity_logs.html b/app/frontend/templates/panel/activity_logs.html index 45ab3a79..e053e50e 100644 --- a/app/frontend/templates/panel/activity_logs.html +++ b/app/frontend/templates/panel/activity_logs.html @@ -111,7 +111,11 @@ $.each(data, function (index, value) { let row = $(''); row.append(`${value.time}`); - row.append(`
${value.user_name}`); + if (value.user_name != "system" && value.user_id != "-1") { + row.append(`${value.user_name}`); + } else { + row.append(`${value.user_name}`); + } row.append(`${value.log_msg}`); row.append(`${value.server_id}`); row.append(`${value.source_ip}`); From d998d82de022e907bd864fbf79a7fcb9c5bd9e66 Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Sat, 20 Apr 2024 17:04:30 -0400 Subject: [PATCH 20/26] Fix code quaity issues --- app/classes/logging/log_formatter.py | 11 +++++------ app/classes/models/management.py | 1 - 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/app/classes/logging/log_formatter.py b/app/classes/logging/log_formatter.py index 7167ab4d..e3f2b4f7 100644 --- a/app/classes/logging/log_formatter.py +++ b/app/classes/logging/log_formatter.py @@ -18,8 +18,8 @@ class JsonEncoderDatetime(JsonEncoderStrFallback): def default(self, o): if isinstance(o, datetime): return o.strftime("%Y-%m-%dT%H:%M:%S%z") - else: - return super().default(o) + + return super().default(o) class JsonFormatter(logging.Formatter): @@ -31,10 +31,9 @@ class JsonFormatter(logging.Formatter): if datefmt: # Use the specified date format return timestamp.strftime(datefmt) - else: - # Default date format: YYYY-MM-DD HH:MM:SS,mmm - secs = int(record.msecs) - return f"{timestamp.strftime('%Y-%m-%d %H:%M:%S')},{secs:03d}" + # Default date format: YYYY-MM-DD HH:MM:SS,mmm + secs = int(record.msecs) + return f"{timestamp.strftime('%Y-%m-%d %H:%M:%S')},{secs:03d}" def format(self, record): log_data = { diff --git a/app/classes/models/management.py b/app/classes/models/management.py index dc57816d..e59dd39c 100644 --- a/app/classes/models/management.py +++ b/app/classes/models/management.py @@ -16,7 +16,6 @@ from app.classes.models.base_model import BaseModel from app.classes.models.users import HelperUsers from app.classes.models.servers import Servers from app.classes.models.server_permissions import PermissionsServers -from app.classes.shared.main_models import DatabaseShortcuts from app.classes.shared.websocket_manager import WebSocketManager logger = logging.getLogger(__name__) From 1655a16ba04d90ec27bf60d0ae18902a032e1f5c Mon Sep 17 00:00:00 2001 From: Zedifus Date: Thu, 9 May 2024 20:11:46 +0100 Subject: [PATCH 21/26] Re-tag test jobs to new shared runner standard (GL17) --- .gitlab/lint.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.gitlab/lint.yml b/.gitlab/lint.yml index bc797808..37649e1a 100644 --- a/.gitlab/lint.yml +++ b/.gitlab/lint.yml @@ -5,7 +5,7 @@ yamllint: stage: lint image: registry.gitlab.com/pipeline-components/yamllint:latest tags: - - docker + - saas-linux-medium-amd64 rules: - if: "$CODE_QUALITY_DISABLED" when: never @@ -18,7 +18,7 @@ jsonlint: stage: lint image: registry.gitlab.com/pipeline-components/jsonlint:latest tags: - - docker + - saas-linux-medium-amd64 rules: - if: "$CODE_QUALITY_DISABLED" when: never @@ -33,7 +33,7 @@ black: stage: lint image: registry.gitlab.com/pipeline-components/black:latest tags: - - docker + - saas-linux-medium-amd64 rules: - if: "$CODE_QUALITY_DISABLED" when: never @@ -46,7 +46,7 @@ pylint: stage: lint image: registry.gitlab.com/pipeline-components/pylint:latest tags: - - docker + - saas-linux-medium-amd64 rules: - if: "$CODE_QUALITY_DISABLED" when: never @@ -69,7 +69,7 @@ sonarcloud-check: name: sonarsource/sonar-scanner-cli:latest entrypoint: [""] tags: - - docker + - saas-linux-medium-amd64 rules: - if: "$SONAR_TOKEN == null" when: never @@ -91,7 +91,7 @@ lang-check: stage: lint image: alpine:latest tags: - - docker + - saas-linux-medium-amd64 rules: - if: "$CODE_QUALITY_DISABLED" when: never From 6bcdb21bb84f01179b14f89a1ee46e130890b221 Mon Sep 17 00:00:00 2001 From: Zedifus Date: Thu, 9 May 2024 20:30:38 +0100 Subject: [PATCH 22/26] Update changelog !731 --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3be9e1a1..cee5a414 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ # Changelog ## --- [4.3.3] - 2024/TBD +### Refactor +- Refactor API keys "super user" to "full access" ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/731)) ### New features TBD ### Bug fixes From 27eeb2fa0febfa3327f81096796343e0a6b34c10 Mon Sep 17 00:00:00 2001 From: Zedifus Date: Thu, 9 May 2024 20:43:56 +0100 Subject: [PATCH 23/26] Update changelog !743 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cee5a414..cdc9d383 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ TBD ### Bug fixes TBD ### Tweaks -TBD +- Add link to go back to dashboard on error page ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/743)) ### Lang TBD

From 100872966d0baf8b052731a7114183d41734c834 Mon Sep 17 00:00:00 2001 From: Zedifus Date: Thu, 9 May 2024 20:51:19 +0100 Subject: [PATCH 24/26] Update changelog !749 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cdc9d383..a72bbc60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ TBD ### Tweaks - Add link to go back to dashboard on error page ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/743)) ### Lang -TBD +- Changes of phrase in `cs_CS` translation ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/749))

## --- [4.3.2] - 2024/04/07 From 4cd3bf17aed7ae55202ca59f1c6bdc5319c96aaf Mon Sep 17 00:00:00 2001 From: Zedifus Date: Thu, 9 May 2024 20:58:26 +0100 Subject: [PATCH 25/26] Update changelog !750 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a72bbc60..6197feba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ ### New features TBD ### Bug fixes -TBD +- Reset query arguments on login if `?next` is not available ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/750)) ### Tweaks - Add link to go back to dashboard on error page ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/743)) ### Lang From 367e77765c77a7661e4fd81a4bb95f02059cee1e Mon Sep 17 00:00:00 2001 From: Zedifus Date: Thu, 9 May 2024 21:04:34 +0100 Subject: [PATCH 26/26] Update changelog !751 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6197feba..5515ec9f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ TBD - Reset query arguments on login if `?next` is not available ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/750)) ### Tweaks - Add link to go back to dashboard on error page ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/743)) +- Set audit logging to logfile instead of DB ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/751)) ### Lang - Changes of phrase in `cs_CS` translation ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/749))