From bf59e2de6c59e6bace09e4bcf16fa3754afec40f Mon Sep 17 00:00:00 2001 From: luukas Date: Sun, 8 May 2022 00:07:55 +0300 Subject: [PATCH] Add and fix API v2 and db * Add basic role routes * Add API v2 404 handler * Add API v2 home handler pointing to the wiki * Add tons more todos * Add get_*_columns and get_*_column functions for many db models * Modify and add tons of model and controller functions --- .../controllers/crafty_perms_controller.py | 2 +- app/classes/controllers/roles_controller.py | 20 +++--- app/classes/controllers/users_controller.py | 25 +++---- app/classes/models/crafty_permissions.py | 2 +- app/classes/models/roles.py | 26 +++++++- app/classes/models/server_permissions.py | 22 +++++-- app/classes/models/servers.py | 20 ++++++ app/classes/models/users.py | 37 ++++++++--- app/classes/web/panel_handler.py | 6 +- app/classes/web/routes/api/api_handlers.py | 66 ++++++++++++++----- app/classes/web/routes/api/index_handler.py | 17 +++++ app/classes/web/routes/api/not_found.py | 9 +++ app/classes/web/routes/api/roles/index.py | 33 ++++++++++ .../web/routes/api/roles/role/index.py | 24 +++++++ .../web/routes/api/roles/role/servers.py | 27 ++++++++ .../web/routes/api/roles/role/users.py | 36 ++++++++++ app/classes/web/routes/api/users/index.py | 5 +- .../web/routes/api/users/user/index.py | 1 + 18 files changed, 317 insertions(+), 61 deletions(-) create mode 100644 app/classes/web/routes/api/index_handler.py create mode 100644 app/classes/web/routes/api/not_found.py create mode 100644 app/classes/web/routes/api/roles/role/servers.py diff --git a/app/classes/controllers/crafty_perms_controller.py b/app/classes/controllers/crafty_perms_controller.py index 92bafee2..b555b97f 100644 --- a/app/classes/controllers/crafty_perms_controller.py +++ b/app/classes/controllers/crafty_perms_controller.py @@ -66,7 +66,7 @@ class CraftyPermsController: @staticmethod def add_server_creation(user_id): - """Increase the "Server Creation" counter for this use + """Increase the "Server Creation" counter for this user Args: user_id (int): The modifiable user's ID diff --git a/app/classes/controllers/roles_controller.py b/app/classes/controllers/roles_controller.py index 266bb658..60bf97b5 100644 --- a/app/classes/controllers/roles_controller.py +++ b/app/classes/controllers/roles_controller.py @@ -16,6 +16,10 @@ class RolesController: def get_all_roles(): return HelperRoles.get_all_roles() + @staticmethod + def get_all_role_ids(): + return HelperRoles.get_all_role_ids() + @staticmethod def get_roleid_by_name(role_name): return HelperRoles.get_roleid_by_name(role_name) @@ -36,8 +40,12 @@ class RolesController: if key == "role_id": continue elif key == "servers": - added_servers = role_data["servers"].difference(base_data["servers"]) - removed_servers = base_data["servers"].difference(role_data["servers"]) + added_servers = set(role_data["servers"]).difference( + set(base_data["servers"]) + ) + removed_servers = set(base_data["servers"]).difference( + set(role_data["servers"]) + ) elif base_data[key] != role_data[key]: up_data[key] = role_data[key] up_data["last_update"] = Helpers.get_time_as_string() @@ -73,12 +81,8 @@ class RolesController: role = HelperRoles.get_role(role_id) if role: - servers_query = PermissionsServers.get_servers_from_role(role_id) - # TODO: this query needs to be narrower - servers = set() - for s in servers_query: - servers.add(s.server_id.server_id) - role["servers"] = servers + server_ids = PermissionsServers.get_server_ids_from_role(role_id) + role["servers"] = list(server_ids) # logger.debug("role: ({}) {}".format(role_id, role)) return role else: diff --git a/app/classes/controllers/users_controller.py b/app/classes/controllers/users_controller.py index c50c93dd..69e8d281 100644 --- a/app/classes/controllers/users_controller.py +++ b/app/classes/controllers/users_controller.py @@ -1,6 +1,5 @@ import logging -from typing import Optional -import typing +import typing as t from app.classes.models.users import HelperUsers from app.classes.models.crafty_permissions import ( @@ -28,7 +27,7 @@ class UsersController: "quantity": {"type": "number", "minimum": 0}, "enabled": {"type": "boolean"}, } - self.user_jsonschema_props: typing.Final = { + self.user_jsonschema_props: t.Final = { "username": { "type": "string", "maxLength": 20, @@ -90,7 +89,7 @@ class UsersController: return HelperUsers.get_all_users() @staticmethod - def get_all_user_ids(): + def get_all_user_ids() -> t.List[int]: return HelperUsers.get_all_user_ids() @staticmethod @@ -134,8 +133,12 @@ class UsersController: if key == "user_id": continue elif key == "roles": - added_roles = user_data["roles"].difference(base_data["roles"]) - removed_roles = base_data["roles"].difference(user_data["roles"]) + added_roles = set(user_data["roles"]).difference( + set(base_data["roles"]) + ) + removed_roles = set(base_data["roles"]).difference( + set(user_data["roles"]) + ) elif key == "password": if user_data["password"] is not None and user_data["password"] != "": up_data["password"] = self.helper.encode_pass(user_data["password"]) @@ -177,14 +180,12 @@ class UsersController: self.users_helper.update_user(user_id, up_data) - def raw_update_user( - self, user_id: int, up_data: typing.Optional[typing.Dict[str, typing.Any]] - ): + def raw_update_user(self, user_id: int, up_data: t.Optional[t.Dict[str, t.Any]]): """Directly passes the data to the model helper. Args: user_id (int): The id of the user to update. - up_data (typing.Optional[typing.Dict[str, typing.Any]]): Update data. + up_data (t.Optional[t.Dict[str, t.Any]]): Update data. """ self.users_helper.update_user(user_id, up_data) @@ -286,8 +287,8 @@ class UsersController: name: str, user_id: str, superuser: bool = False, - server_permissions_mask: Optional[str] = None, - crafty_permissions_mask: Optional[str] = None, + server_permissions_mask: t.Optional[str] = None, + crafty_permissions_mask: t.Optional[str] = None, ): return self.users_helper.add_user_api_key( name, user_id, superuser, server_permissions_mask, crafty_permissions_mask diff --git a/app/classes/models/crafty_permissions.py b/app/classes/models/crafty_permissions.py index f8e71daa..b53ae930 100644 --- a/app/classes/models/crafty_permissions.py +++ b/app/classes/models/crafty_permissions.py @@ -192,7 +192,7 @@ class PermissionsCrafty: @staticmethod def add_server_creation(user_id): - """Increase the "Server Creation" counter for this use + """Increase the "Server Creation" counter for this user Args: user_id (int): The modifiable user's ID diff --git a/app/classes/models/roles.py b/app/classes/models/roles.py index 373fa11d..fffdd37f 100644 --- a/app/classes/models/roles.py +++ b/app/classes/models/roles.py @@ -1,5 +1,6 @@ import logging import datetime +import typing as t from peewee import ( CharField, DoesNotExist, @@ -35,8 +36,11 @@ class HelperRoles: @staticmethod def get_all_roles(): - query = Roles.select() - return query + return Roles.select() + + @staticmethod + def get_all_role_ids() -> t.List[int]: + return [role.role_id for role in Roles.select(Roles.role_id).execute()] @staticmethod def get_roleid_by_name(role_name): @@ -49,6 +53,24 @@ class HelperRoles: def get_role(role_id): return model_to_dict(Roles.get(Roles.role_id == role_id)) + @staticmethod + def get_role_columns( + role_id: t.Union[str, int], column_names: t.List[str] + ) -> t.List[t.Any]: + columns = [getattr(Roles, column) for column in column_names] + return model_to_dict( + Roles.select(*columns).where(Roles.role_id == role_id).get(), + only=columns, + ) + + @staticmethod + def get_role_column(role_id: t.Union[str, int], column_name: str) -> t.Any: + column = getattr(Roles, column_name) + return model_to_dict( + Roles.select(column).where(Roles.role_id == role_id).get(), + only=[column], + )[column_name] + @staticmethod def add_role(role_name): role_id = Roles.insert( diff --git a/app/classes/models/server_permissions.py b/app/classes/models/server_permissions.py index 6726c86c..8cdcc0d7 100644 --- a/app/classes/models/server_permissions.py +++ b/app/classes/models/server_permissions.py @@ -1,6 +1,6 @@ from enum import Enum import logging -import typing +import typing as t from peewee import ( ForeignKeyField, CharField, @@ -52,14 +52,14 @@ class PermissionsServers: @staticmethod def get_permissions_list(): - permissions_list: typing.List[EnumPermissionsServer] = [] + permissions_list: t.List[EnumPermissionsServer] = [] for member in EnumPermissionsServer.__members__.items(): permissions_list.append(member[1]) return permissions_list @staticmethod def get_permissions(permissions_mask): - permissions_list: typing.List[EnumPermissionsServer] = [] + permissions_list: t.List[EnumPermissionsServer] = [] for member in EnumPermissionsServer.__members__.items(): if PermissionsServers.has_permission(permissions_mask, member[1]): permissions_list.append(member[1]) @@ -96,17 +96,29 @@ class PermissionsServers: # Role_Servers Methods # ********************************************************************************** @staticmethod - def get_role_servers_from_role_id(roleid): + def get_role_servers_from_role_id(roleid: t.Union[str, int]): return RoleServers.select().where(RoleServers.role_id == roleid) @staticmethod - def get_servers_from_role(role_id): + def get_servers_from_role(role_id: t.Union[str, int]): return ( RoleServers.select() .join(Servers, JOIN.INNER) .where(RoleServers.role_id == role_id) ) + @staticmethod + def get_server_ids_from_role(role_id: t.Union[str, int]) -> t.List[int]: + # FIXME: somehow retrieve only the server ids, not the whole servers + return [ + role_servers.server_id.server_id + for role_servers in ( + RoleServers.select(RoleServers.server_id).where( + RoleServers.role_id == role_id + ) + ) + ] + @staticmethod def get_roles_from_server(server_id): return ( diff --git a/app/classes/models/servers.py b/app/classes/models/servers.py index 41341c7a..cd91396a 100644 --- a/app/classes/models/servers.py +++ b/app/classes/models/servers.py @@ -1,5 +1,6 @@ import logging import datetime +import typing as t from peewee import ( ForeignKeyField, CharField, @@ -9,6 +10,7 @@ from peewee import ( IntegerField, FloatField, ) +from playhouse.shortcuts import model_to_dict from app.classes.shared.main_models import DatabaseShortcuts from app.classes.models.base_model import BaseModel @@ -162,6 +164,24 @@ class HelperServers: except IndexError: return {} + @staticmethod + def get_server_columns( + server_id: t.Union[str, int], column_names: t.List[str] + ) -> t.List[t.Any]: + columns = [getattr(Servers, column) for column in column_names] + return model_to_dict( + Servers.select(*columns).where(Servers.server_id == server_id).get(), + only=columns, + ) + + @staticmethod + def get_server_column(server_id: t.Union[str, int], column_name: str) -> t.Any: + column = getattr(Servers, column_name) + return model_to_dict( + Servers.select(column).where(Servers.server_id == server_id).get(), + only=[column], + )[column_name] + # ********************************************************************************** # Servers Methods # ********************************************************************************** diff --git a/app/classes/models/users.py b/app/classes/models/users.py index d17c3561..5370d430 100644 --- a/app/classes/models/users.py +++ b/app/classes/models/users.py @@ -100,9 +100,13 @@ class HelperUsers: return query @staticmethod - def get_all_user_ids(): - query = Users.select(Users.user_id).where(Users.username != "system") - return query + def get_all_user_ids() -> t.List[int]: + return [ + user.user_id + for user in Users.select(Users.user_id) + .where(Users.username != "system") + .execute() + ] @staticmethod def get_user_lang_by_id(user_id): @@ -148,6 +152,24 @@ class HelperUsers: # logger.debug("user: ({}) {}".format(user_id, {})) return {} + @staticmethod + def get_user_columns( + user_id: t.Union[str, int], column_names: t.List[str] + ) -> t.List[t.Any]: + columns = [getattr(Users, column) for column in column_names] + return model_to_dict( + Users.select(*columns).where(Users.user_id == user_id).get(), + only=columns, + ) + + @staticmethod + def get_user_column(user_id: t.Union[str, int], column_name: str) -> t.Any: + column = getattr(Users, column_name) + return model_to_dict( + Users.select(column).where(Users.user_id == user_id).get(), + only=[column], + )[column_name] + @staticmethod def check_system_user(user_id): try: @@ -284,11 +306,10 @@ class HelperUsers: @staticmethod def get_user_roles_names(user_id): - roles_list = [] - roles = UserRoles.select().where(UserRoles.user_id == user_id) - for r in roles: - roles_list.append(HelperRoles.get_role(r.role_id)["role_name"]) - return roles_list + roles = UserRoles.select(UserRoles.role_id).where(UserRoles.user_id == user_id) + return [ + HelperRoles.get_role_column(role.role_id, "role_name") for role in roles + ] @staticmethod def add_role_to_user(user_id, role_id): diff --git a/app/classes/web/panel_handler.py b/app/classes/web/panel_handler.py index 059f7d50..df9940c0 100644 --- a/app/classes/web/panel_handler.py +++ b/app/classes/web/panel_handler.py @@ -29,11 +29,11 @@ logger = logging.getLogger(__name__) class PanelHandler(BaseHandler): def get_user_roles(self) -> Dict[str, list]: user_roles = {} - for user in self.controller.users.get_all_users(): - user_roles_list = self.controller.users.get_user_roles_names(user.user_id) + for user_id in self.controller.users.get_all_user_ids(): + user_roles_list = self.controller.users.get_user_roles_names(user_id) # user_servers = # self.controller.servers.get_authorized_servers(user.user_id) - user_roles[user.user_id] = user_roles_list + user_roles[user_id] = user_roles_list return user_roles def get_role_servers(self) -> set: diff --git a/app/classes/web/routes/api/api_handlers.py b/app/classes/web/routes/api/api_handlers.py index bd2e72d0..e5a91046 100644 --- a/app/classes/web/routes/api/api_handlers.py +++ b/app/classes/web/routes/api/api_handlers.py @@ -1,7 +1,13 @@ +from app.classes.web.routes.api.index_handler import ApiIndexHandler +from app.classes.web.routes.api.not_found import ApiNotFoundHandler from app.classes.web.routes.api.auth.invalidate_tokens import ( ApiAuthInvalidateTokensHandler, ) from app.classes.web.routes.api.auth.login import ApiAuthLoginHandler +from app.classes.web.routes.api.roles.index import ApiRolesIndexHandler +from app.classes.web.routes.api.roles.role.index import ApiRolesRoleIndexHandler +from app.classes.web.routes.api.roles.role.servers import ApiRolesRoleServersHandler +from app.classes.web.routes.api.roles.role.users import ApiRolesRoleUsersHandler from app.classes.web.routes.api.servers.index import ApiServersIndexHandler from app.classes.web.routes.api.servers.server.action import ( ApiServersServerActionHandler, @@ -22,34 +28,60 @@ from app.classes.web.routes.api.users.user.public import ApiUsersUserPublicHandl def api_handlers(handler_args): return [ # Auth routes - (r"/api/v2/auth/login", ApiAuthLoginHandler, handler_args), + (r"/api/v2/auth/login/?", ApiAuthLoginHandler, handler_args), ( - r"/api/v2/auth/invalidate_tokens", + r"/api/v2/auth/invalidate_tokens/?", ApiAuthInvalidateTokensHandler, handler_args, ), # User routes - (r"/api/v2/users", ApiUsersIndexHandler, handler_args), - (r"/api/v2/users/([a-z0-9_]+)", ApiUsersUserIndexHandler, handler_args), - (r"/api/v2/users/(@me)", ApiUsersUserIndexHandler, handler_args), - (r"/api/v2/users/([a-z0-9_]+)/pfp", ApiUsersUserPfpHandler, handler_args), - (r"/api/v2/users/(@me)/pfp", ApiUsersUserPfpHandler, handler_args), - (r"/api/v2/users/([a-z0-9_]+)/public", ApiUsersUserPublicHandler, handler_args), - (r"/api/v2/users/(@me)/public", ApiUsersUserPublicHandler, handler_args), - # Server routes - (r"/api/v2/servers", ApiServersIndexHandler, handler_args), - (r"/api/v2/servers/([0-9]+)", ApiServersServerIndexHandler, handler_args), - (r"/api/v2/servers/([0-9]+)/stats", ApiServersServerStatsHandler, handler_args), + (r"/api/v2/users/?", ApiUsersIndexHandler, handler_args), + (r"/api/v2/users/([a-z0-9_]+)/?", ApiUsersUserIndexHandler, handler_args), + (r"/api/v2/users/(@me)/?", ApiUsersUserIndexHandler, handler_args), + (r"/api/v2/users/([a-z0-9_]+)/pfp/?", ApiUsersUserPfpHandler, handler_args), + (r"/api/v2/users/(@me)/pfp/?", ApiUsersUserPfpHandler, handler_args), ( - r"/api/v2/servers/([0-9]+)/action/([a-z_]+)", + r"/api/v2/users/([a-z0-9_]+)/public/?", + ApiUsersUserPublicHandler, + handler_args, + ), + (r"/api/v2/users/(@me)/public/?", ApiUsersUserPublicHandler, handler_args), + # Server routes + (r"/api/v2/servers/?", ApiServersIndexHandler, handler_args), + (r"/api/v2/servers/([0-9]+)/?", ApiServersServerIndexHandler, handler_args), + ( + r"/api/v2/servers/([0-9]+)/stats/?", + ApiServersServerStatsHandler, + handler_args, + ), + ( + r"/api/v2/servers/([0-9]+)/action/([a-z_]+)/?", ApiServersServerActionHandler, handler_args, ), - (r"/api/v2/servers/([0-9]+)/logs", ApiServersServerLogsHandler, handler_args), - (r"/api/v2/servers/([0-9]+)/users", ApiServersServerUsersHandler, handler_args), + (r"/api/v2/servers/([0-9]+)/logs/?", ApiServersServerLogsHandler, handler_args), ( - r"/api/v2/servers/([0-9]+)/public", + r"/api/v2/servers/([0-9]+)/users/?", + ApiServersServerUsersHandler, + handler_args, + ), + ( + r"/api/v2/servers/([0-9]+)/public/?", ApiServersServerPublicHandler, handler_args, ), + (r"/api/v2/roles/?", ApiRolesIndexHandler, handler_args), + (r"/api/v2/roles/([a-z0-9_]+)/?", ApiRolesRoleIndexHandler, handler_args), + ( + r"/api/v2/roles/([a-z0-9_]+)/servers/?", + ApiRolesRoleServersHandler, + handler_args, + ), + ( + r"/api/v2/roles/([a-z0-9_]+)/users/?", + ApiRolesRoleUsersHandler, + handler_args, + ), + (r"/api/v2/?", ApiIndexHandler, handler_args), + (r"/api/v2/(.*)", ApiNotFoundHandler, handler_args), ] diff --git a/app/classes/web/routes/api/index_handler.py b/app/classes/web/routes/api/index_handler.py new file mode 100644 index 00000000..c8168b46 --- /dev/null +++ b/app/classes/web/routes/api/index_handler.py @@ -0,0 +1,17 @@ +from app.classes.web.base_api_handler import BaseApiHandler + +WIKI_API_LINK = "https://wiki.craftycontrol.com/en/4/docs/API V2" + + +class ApiIndexHandler(BaseApiHandler): + def get(self): + self.finish_json( + 200, + { + "status": "ok", + "data": { + "version": self.controller.helper.get_version_string(), + "message": f"Please see the API documentation at {WIKI_API_LINK}", + }, + }, + ) diff --git a/app/classes/web/routes/api/not_found.py b/app/classes/web/routes/api/not_found.py new file mode 100644 index 00000000..20cd483d --- /dev/null +++ b/app/classes/web/routes/api/not_found.py @@ -0,0 +1,9 @@ +from app.classes.web.base_api_handler import BaseApiHandler + + +class ApiNotFoundHandler(BaseApiHandler): + def get(self, page: str): + self.finish_json( + 404, + {"status": "error", "error": "API_HANDLER_NOT_FOUND", "page": page}, + ) diff --git a/app/classes/web/routes/api/roles/index.py b/app/classes/web/routes/api/roles/index.py index e69de29b..590183e5 100644 --- a/app/classes/web/routes/api/roles/index.py +++ b/app/classes/web/routes/api/roles/index.py @@ -0,0 +1,33 @@ +from playhouse.shortcuts import model_to_dict +from app.classes.web.base_api_handler import BaseApiHandler + + +class ApiRolesIndexHandler(BaseApiHandler): + def get(self): + auth_data = self.authenticate_user() + if not auth_data: + return + ( + _, + _, + _, + superuser, + _, + ) = auth_data + + # GET /api/v2/roles?ids=true + get_only_ids = self.get_query_argument("ids", None) == "true" + + if not superuser: + return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) + + # TODO: permissions + self.finish_json( + 200, + { + "status": "ok", + "data": self.controller.roles.get_all_role_ids() + if get_only_ids + else [model_to_dict(r) for r in self.controller.roles.get_all_roles()], + }, + ) diff --git a/app/classes/web/routes/api/roles/role/index.py b/app/classes/web/routes/api/roles/role/index.py index e69de29b..7f4573d1 100644 --- a/app/classes/web/routes/api/roles/role/index.py +++ b/app/classes/web/routes/api/roles/role/index.py @@ -0,0 +1,24 @@ +from app.classes.web.base_api_handler import BaseApiHandler + + +class ApiRolesRoleIndexHandler(BaseApiHandler): + def get(self, role_id: str): + auth_data = self.authenticate_user() + if not auth_data: + return + ( + _, + _, + _, + superuser, + _, + ) = auth_data + + if not superuser: + return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) + + # TODO: permissions + self.finish_json( + 200, + {"status": "ok", "data": self.controller.roles.get_role(role_id)}, + ) diff --git a/app/classes/web/routes/api/roles/role/servers.py b/app/classes/web/routes/api/roles/role/servers.py new file mode 100644 index 00000000..97052a6a --- /dev/null +++ b/app/classes/web/routes/api/roles/role/servers.py @@ -0,0 +1,27 @@ +from app.classes.models.server_permissions import PermissionsServers +from app.classes.web.base_api_handler import BaseApiHandler + + +class ApiRolesRoleServersHandler(BaseApiHandler): + def get(self, role_id: str): + auth_data = self.authenticate_user() + if not auth_data: + return + ( + _, + _, + _, + superuser, + _, + ) = auth_data + + if not superuser: + return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) + + self.finish_json( + 200, + { + "status": "ok", + "data": PermissionsServers.get_server_ids_from_role(role_id), + }, + ) diff --git a/app/classes/web/routes/api/roles/role/users.py b/app/classes/web/routes/api/roles/role/users.py index e69de29b..ac2227ac 100644 --- a/app/classes/web/routes/api/roles/role/users.py +++ b/app/classes/web/routes/api/roles/role/users.py @@ -0,0 +1,36 @@ +from app.classes.web.base_api_handler import BaseApiHandler + + +class ApiRolesRoleUsersHandler(BaseApiHandler): + def get(self, role_id: str): + auth_data = self.authenticate_user() + if not auth_data: + return + ( + _, + _, + _, + superuser, + _, + ) = auth_data + + if not superuser: + return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"}) + + all_user_ids = self.controller.users.get_all_user_ids() + + user_roles = {} + for user_id in all_user_ids: + user_roles_list = self.controller.users.get_user_roles_names(user_id) + user_roles[user_id] = user_roles_list + + role = self.controller.roles.get_role(role_id) + + user_ids = [] + + for user_id in all_user_ids: + for role_user in user_roles[user_id]: + if role_user == role["role_name"]: + user_ids.append(user_id) + + self.finish_json(200, {"status": "ok", "data": user_ids}) diff --git a/app/classes/web/routes/api/users/index.py b/app/classes/web/routes/api/users/index.py index d129eccc..065ef117 100644 --- a/app/classes/web/routes/api/users/index.py +++ b/app/classes/web/routes/api/users/index.py @@ -28,10 +28,7 @@ class ApiUsersIndexHandler(BaseApiHandler): if EnumPermissionsCrafty.USER_CONFIG in exec_user_crafty_permissions: if get_only_ids: - data = [ - user.user_id - for user in self.controller.users.get_all_user_ids().execute() - ] + data = self.controller.users.get_all_user_ids() else: data = [ {key: getattr(user_res, key) for key in PUBLIC_USER_ATTRS} diff --git a/app/classes/web/routes/api/users/user/index.py b/app/classes/web/routes/api/users/user/index.py index 3fa41284..0ed41fbc 100644 --- a/app/classes/web/routes/api/users/user/index.py +++ b/app/classes/web/routes/api/users/user/index.py @@ -212,6 +212,7 @@ class ApiUsersUserIndexHandler(BaseApiHandler): ) # TODO: make this more efficient + # TODO: add permissions and roles because I forgot user_obj = HelperUsers.get_user_model(user_id) self.controller.management.add_to_audit_log(