diff --git a/app/classes/shared/models.py b/app/classes/shared/models.py index 063b45d2..e7719051 100644 --- a/app/classes/shared/models.py +++ b/app/classes/shared/models.py @@ -33,6 +33,7 @@ class Users(BaseModel): user_id = AutoField() created = DateTimeField(default=datetime.datetime.now) last_login = DateTimeField(default=datetime.datetime.now) + last_update = DateTimeField(default=datetime.datetime.now) last_ip = CharField(default="") username = CharField(default="", unique=True, index=True) password = CharField(default="") @@ -47,6 +48,7 @@ class Users(BaseModel): class Roles(BaseModel): role_id = AutoField() created = DateTimeField(default=datetime.datetime.now) + last_update = DateTimeField(default=datetime.datetime.now) role_name = CharField(default="", unique=True, index=True) class Meta: @@ -365,6 +367,7 @@ class db_shortcuts: up_data['password'] = helper.encode_pass(user_data['password']) elif base_data[key] != user_data[key]: up_data[key] = user_data[key] + up_data['last_update'] = helper.get_time_as_string() logger.debug("user: {} +role:{} -role:{} +server:{} -server{}".format(user_data, added_roles, removed_roles, added_servers, removed_servers)) with database.atomic(): for role in added_roles: @@ -379,8 +382,6 @@ class db_shortcuts: if up_data: Users.update(up_data).where(Users.user_id == user_id).execute() - - @staticmethod def add_user(username, password=None, api_token=None, enabled=True, superuser=False): if password is not None: @@ -397,7 +398,8 @@ class db_shortcuts: Users.password: pw_enc, Users.api_token: api_token, Users.enabled: enabled, - Users.superuser: superuser + Users.superuser: superuser, + Users.created: helper.get_time_as_string() }).execute() return user_id @@ -414,14 +416,70 @@ class db_shortcuts: @staticmethod def get_roleid_by_name(role_name): - return (Roles.get(Roles.role_name == role_name)).role_id + try: + return (Roles.get(Roles.role_name == role_name)).role_id + except DoesNotExist: + return None @staticmethod def get_role(role_id): - query = model_to_dict(Roles.get(Roles.role_id == role_id)) - Roles['roles_flat'] = [] - Roles['allowed_servers_flat'] = [] - return query + role = model_to_dict(Roles.get(Roles.role_id == role_id)) + + if role: + servers_query = Role_Servers.select().join(Servers, JOIN.INNER).where(Role_Servers.role_id == 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 + logger.debug("role: ({}) {}".format(role_id, role)) + return role + else: + logger.debug("role: ({}) {}".format(role_id, {})) + return {} + + @staticmethod + def update_role(role_id, role_data={}): + base_data = db_helper.get_role(role_id) + up_data = {} + added_servers = set() + removed_servers = set() + for key in role_data: + 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']) + elif base_data[key] != role_data[key]: + up_data[key] = role_data[key] + up_data['last_update'] = helper.get_time_as_string() + logger.debug("role: {} +server:{} -server{}".format(role_data, added_servers, removed_servers)) + with database.atomic(): + for server in added_servers: + Role_Servers.get_or_create(role_id=role_id, server_id=server) + # TODO: This is horribly inefficient and we should be using bulk queries but im going for functionality at this point + Role_Servers.delete().where(Role_Servers.role_id == role_id).where(Role_Servers.server_id.in_(removed_servers)).execute() + if up_data: + Roles.update(up_data).where(Roles.role_id == role_id).execute() + + @staticmethod + def add_role(role_name): + role_id = Roles.insert({ + Roles.role_name: role_name.lower(), + Roles.created: helper.get_time_as_string() + }).execute() + return role_id + + @staticmethod + def remove_role(role_id): + role = Roles.get(Roles.role_id == role_id) + return role.delete_instance() + + @staticmethod + def role_id_exists(role_id): + if not db_shortcuts.get_role(role_id): + return False + return True @staticmethod def get_unactioned_commands(): diff --git a/app/classes/web/panel_handler.py b/app/classes/web/panel_handler.py index 716f8f75..3d31a8b4 100644 --- a/app/classes/web/panel_handler.py +++ b/app/classes/web/panel_handler.py @@ -120,6 +120,7 @@ class PanelHandler(BaseHandler): elif page == 'panel_config': page_data['users'] = db_helper.get_all_users() + page_data['roles'] = db_helper.get_all_roles() exec_user = db_helper.get_user(user_data['user_id']) for user in page_data['users']: if user.user_id != exec_user['user_id']: @@ -137,22 +138,36 @@ class PanelHandler(BaseHandler): page_data['user']['created'] = "N/A" page_data['user']['last_login'] = "N/A" page_data['user']['last_ip'] = "N/A" + page_data['role']['last_update'] = "N/A" page_data['user']['roles'] = set() page_data['user']['servers'] = set() + exec_user = db_helper.get_user(user_data['user_id']) + + if not exec_user['superuser']: + self.redirect("/panel/error?error=Unauthorized access: not superuser") + return False + page_data['roles_all'] = db_helper.get_all_roles() page_data['servers_all'] = controller.list_defined_servers() template = "panel/panel_edit_user.html" elif page == "edit_user": page_data['new_user'] = False - uid = self.get_argument('id', None) - page_data['user'] = db_helper.get_user(uid) + user_id = self.get_argument('id', None) + page_data['user'] = db_helper.get_user(user_id) page_data['roles_all'] = db_helper.get_all_roles() page_data['servers_all'] = controller.list_defined_servers() exec_user = db_helper.get_user(user_data['user_id']) - + + if not exec_user['superuser']: + self.redirect("/panel/error?error=Unauthorized access: not superuser") + return False + elif user_id is None: + self.redirect("/panel/error?error=Invalid User ID") + return False + if exec_user['user_id'] != page_data['user']['user_id']: page_data['user']['api_token'] = "********" template = "panel/panel_edit_user.html" @@ -162,7 +177,7 @@ class PanelHandler(BaseHandler): user_data = json.loads(self.get_secure_cookie("user_data")) exec_user = db_helper.get_user(user_data['user_id']) - + if not exec_user['superuser']: self.redirect("/panel/error?error=Unauthorized access: not superuser") return False @@ -187,6 +202,68 @@ class PanelHandler(BaseHandler): source_ip=self.get_remote_ip()) self.redirect("/panel/panel_config") + elif page == "add_role": + page_data['new_role'] = True + page_data['role'] = {} + page_data['role']['role_name'] = "" + page_data['role']['role_id'] = -1 + page_data['role']['created'] = "N/A" + page_data['role']['last_update'] = "N/A" + page_data['role']['servers'] = set() + + exec_user = db_helper.get_user(user_data['user_id']) + + if not exec_user['superuser']: + self.redirect("/panel/error?error=Unauthorized access: not superuser") + return False + + page_data['servers_all'] = controller.list_defined_servers() + template = "panel/panel_edit_role.html" + + elif page == "edit_role": + page_data['new_role'] = False + role_id = self.get_argument('id', None) + page_data['role'] = db_helper.get_role(role_id) + page_data['servers_all'] = controller.list_defined_servers() + + exec_user = db_helper.get_user(user_data['user_id']) + + if not exec_user['superuser']: + self.redirect("/panel/error?error=Unauthorized access: not superuser") + return False + elif role_id is None: + self.redirect("/panel/error?error=Invalid Role ID") + return False + + template = "panel/panel_edit_role.html" + + elif page == "remove_role": + role_id = bleach.clean(self.get_argument('id', None)) + + user_data = json.loads(self.get_secure_cookie("user_data")) + exec_user = db_helper.get_user(user_data['user_id']) + + if not exec_user['superuser']: + self.redirect("/panel/error?error=Unauthorized access: not superuser") + return False + elif role_id is None: + self.redirect("/panel/error?error=Invalid Role ID") + return False + else: + # does this user id exist? + target_role = db_helper.get_user(role_id) + if not target_role: + self.redirect("/panel/error?error=Invalid Role ID") + return False + + db_helper.remove_role(role_id) + + db_helper.add_to_audit_log(exec_user['user_id'], + "Removed role {} (RID:{})".format(target_role['role_name'], role_id), + server_id=0, + source_ip=self.get_remote_ip()) + self.redirect("/panel/panel_config") + elif page == "activity_logs": page_data['audit_logs'] = db_helper.get_actity_log() @@ -265,7 +342,7 @@ class PanelHandler(BaseHandler): user_data = json.loads(self.get_secure_cookie("user_data")) exec_user = db_helper.get_user(user_data['user_id']) - + if not exec_user['superuser']: self.redirect("/panel/error?error=Unauthorized access: not superuser") return False @@ -286,14 +363,14 @@ class PanelHandler(BaseHandler): return False roles = set() - for server in db_helper.get_all_roles(): + for role in db_helper.get_all_roles(): argument = int(float( bleach.clean( - self.get_argument('role_{}_membership'.format(role['role_id']), '0') + self.get_argument('role_{}_membership'.format(role.role_id), '0') ) )) if argument: - servers.add(role['role_id']) + roles.add(role.role_id) servers = set() for server in controller.list_defined_servers(): @@ -347,10 +424,10 @@ class PanelHandler(BaseHandler): return False roles = set() - for server in db_helper.get_all_roles(): + for role in db_helper.get_all_roles(): argument = int(float( bleach.clean( - self.get_argument('role_{}_membership'.format(role['role_id']), '0') + self.get_argument('role_{}_membership'.format(role.role_id), '0') ) )) if argument: @@ -377,4 +454,89 @@ class PanelHandler(BaseHandler): "Edited user {} (UID:{}) with roles {} and servers {}".format(username, user_id, roles, servers), server_id=0, source_ip=self.get_remote_ip()) + self.redirect("/panel/panel_config") + + elif page == "edit_role": + role_id = bleach.clean(self.get_argument('id', None)) + role_name = bleach.clean(self.get_argument('role_name', None)) + + user_data = json.loads(self.get_secure_cookie("user_data")) + exec_user = db_helper.get_user(user_data['user_id']) + + if not exec_user['superuser']: + self.redirect("/panel/error?error=Unauthorized access: not superuser") + return False + elif role_name is None or role_name == "": + self.redirect("/panel/error?error=Invalid username") + return False + elif role_id is None: + self.redirect("/panel/error?error=Invalid Role ID") + return False + else: + # does this user id exist? + if not db_helper.role_id_exists(role_id): + self.redirect("/panel/error?error=Invalid Role ID") + return False + + servers = set() + for server in controller.list_defined_servers(): + argument = int(float( + bleach.clean( + self.get_argument('server_{}_access'.format(server['server_id']), '0') + ) + )) + if argument: + servers.add(server['server_id']) + + role_data = { + "role_name": role_name, + "servers": servers + } + db_helper.update_role(role_id, role_data=role_data) + + db_helper.add_to_audit_log(exec_user['user_id'], + "Edited role {} (RID:{}) with servers {}".format(role_name, role_id, servers), + server_id=0, + source_ip=self.get_remote_ip()) + self.redirect("/panel/panel_config") + + + elif page == "add_role": + role_name = bleach.clean(self.get_argument('role_name', None)) + + user_data = json.loads(self.get_secure_cookie("user_data")) + exec_user = db_helper.get_user(user_data['user_id']) + if not exec_user['superuser']: + self.redirect("/panel/error?error=Unauthorized access: not superuser") + return False + elif role_name is None or role_name == "": + self.redirect("/panel/error?error=Invalid role name") + return False + else: + # does this user id exist? + if db_helper.get_roleid_by_name(role_name) is not None: + self.redirect("/panel/error?error=Role exists") + return False + + servers = set() + for server in controller.list_defined_servers(): + argument = int(float( + bleach.clean( + self.get_argument('server_{}_access'.format(server['server_id']), '0') + ) + )) + if argument: + servers.add(server['server_id']) + + role_id = db_helper.add_role(role_name) + db_helper.update_role(role_id, {"servers": servers}) + + db_helper.add_to_audit_log(exec_user['user_id'], + "Added role {} (RID:{})".format(role_name, role_id), + server_id=0, + source_ip=self.get_remote_ip()) + db_helper.add_to_audit_log(exec_user['user_id'], + "Edited role {} (RID:{}) with servers {}".format(role_name, role_id, servers), + server_id=0, + source_ip=self.get_remote_ip()) self.redirect("/panel/panel_config") \ No newline at end of file diff --git a/app/frontend/templates/panel/panel_config.html b/app/frontend/templates/panel/panel_config.html index 107ba8fb..37153ed2 100644 --- a/app/frontend/templates/panel/panel_config.html +++ b/app/frontend/templates/panel/panel_config.html @@ -73,11 +73,47 @@ + +
+
+
+
+

Roles

+
+ Can't see everything on mobile?
Try scrolling the table sideways.
+
+
  Add New Role
+
+
+
+ + + + + + + + + + {% for role in data['roles'] %} + + + + + + {% end %} + +
RoleAllowed ServersEdit
{{ role.role_name }}{{ [] }}
+
+
+
+
+
diff --git a/app/frontend/templates/panel/panel_edit_role.html b/app/frontend/templates/panel/panel_edit_role.html new file mode 100644 index 00000000..241f98cb --- /dev/null +++ b/app/frontend/templates/panel/panel_edit_role.html @@ -0,0 +1,159 @@ +{% extends ../base.html %} + +{% block meta %} + +{% end %} + +{% block title %}Crafty Controller - Edit Role{% end %} + +{% block content %} + +
+ + +
+
+ +
+ +
+ + +
+ +
+
+
+ + +
+
+ {% if data['new_role'] %} +
+ {% else %} + + {% end %} + {% raw xsrf_form_html() %} + + + +
+ + +
+ +
+ +
+ + + + + + + + + {% for server in data['servers_all'] %} + + + + + {% end %} + + +
Server NameAccess?
{{ server['server_name'] }} + {% if server['server_id'] in data['role']['servers'] %} + + {% else %} + + {% end %} +
+
+
+ + + +
+
+ +
+
+
+

Role Config Area

+

Here is where you can change the configuration of your role

+
+

+ Created: {{ str(data['role']['created']) }} +
+ Last updated: {{ str(data['role']['last_update']) }} +
+

+
+
+
+
+ {% if data['new_role'] %} + Delete Role
+ You cannot delete something that does not yet exist + {% else %} + Delete Role + {% end %} + +
+
+
+ +
+
+
+
+ + + +
+ + +{% end %} + +{% block js %} + + +{% end %} \ No newline at end of file diff --git a/app/frontend/templates/panel/panel_edit_user.html b/app/frontend/templates/panel/panel_edit_user.html index 9f01988a..a23cbed6 100644 --- a/app/frontend/templates/panel/panel_edit_user.html +++ b/app/frontend/templates/panel/panel_edit_user.html @@ -90,10 +90,10 @@ {{ role.role_name }} - {% if role['role_id'] in data['user']['roles'] %} - + {% if role.role_id in data['user']['roles'] %} + {% else %} - + {% end %} @@ -177,6 +177,8 @@
Last login: {{ str(data['user']['last_login']) }}
+ Last update: {{ str(data['user']['last_update']) }} +
Last IP: {{ data['user']['last_ip'] }}
API Key: {{ data['user']['api_token'] }}