Use API to make/edit roles

This commit is contained in:
amcmanu3 2023-08-16 13:34:52 -04:00
parent 36e500fda5
commit 6f535a11b0
4 changed files with 129 additions and 128 deletions

View File

@ -1538,17 +1538,6 @@ class PanelHandler(BaseHandler):
if api_key is not None:
superuser = superuser and api_key.superuser
server_id = self.get_argument("id", None)
permissions = {
"Commands": EnumPermissionsServer.COMMANDS,
"Terminal": EnumPermissionsServer.TERMINAL,
"Logs": EnumPermissionsServer.LOGS,
"Schedule": EnumPermissionsServer.SCHEDULE,
"Backup": EnumPermissionsServer.BACKUP,
"Files": EnumPermissionsServer.FILES,
"Config": EnumPermissionsServer.CONFIG,
"Players": EnumPermissionsServer.PLAYERS,
}
if superuser:
# defined_servers = self.controller.servers.list_defined_servers()
exec_user_role = {"Super User"}
@ -1874,97 +1863,6 @@ class PanelHandler(BaseHandler):
)
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))
role = self.controller.roles.get_role(role_id)
if (
EnumPermissionsCrafty.ROLES_CONFIG not in exec_user_crafty_permissions
and exec_user["user_id"] != role["manager"]
and not exec_user["superuser"]
):
self.redirect(
"/panel/error?error=Unauthorized access: not a role editor"
)
return
if role_name is None or role_name == "":
self.redirect("/panel/error?error=Invalid username")
return
if role_id is None:
self.redirect("/panel/error?error=Invalid Role ID")
return
# does this user id exist?
if not self.controller.roles.role_id_exists(role_id):
self.redirect("/panel/error?error=Invalid Role ID")
return
if exec_user["superuser"]:
manager = self.get_argument("manager", None)
if manager == "":
manager = None
else:
manager = role["manager"]
servers = self.get_role_servers()
self.controller.roles.update_role_advanced(
role_id, role_name, servers, manager
)
self.controller.management.add_to_audit_log(
exec_user["user_id"],
f"edited role {role_name} (RID:{role_id}) with servers {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))
if exec_user["superuser"]:
manager = self.get_argument("manager", None)
if manager == "":
manager = None
else:
manager = exec_user["user_id"]
if EnumPermissionsCrafty.ROLES_CONFIG not in exec_user_crafty_permissions:
self.redirect(
"/panel/error?error=Unauthorized access: not a role editor"
)
return
if (
not self.controller.crafty_perms.can_add_role(exec_user["user_id"])
and not exec_user["superuser"]
):
self.redirect(
"/panel/error?error=Unauthorized access: quantity limit reached"
)
return
if role_name is None or role_name == "":
self.redirect("/panel/error?error=Invalid role name")
return
# does this user id exist?
if self.controller.roles.get_roleid_by_name(role_name) is not None:
self.redirect("/panel/error?error=Role exists")
return
servers = self.get_role_servers()
role_id = self.controller.roles.add_role_advanced(
role_name, servers, manager
)
self.controller.management.add_to_audit_log(
exec_user["user_id"],
f"created role {role_name} (RID:{role_id})",
server_id=0,
source_ip=self.get_remote_ip(),
)
self.redirect("/panel/panel_config")
else:
self.set_status(404)
page_data = {

View File

@ -28,9 +28,39 @@ create_role_schema = {
"required": ["server_id", "permissions"],
},
},
"manager": {"type": ["integer", "null"]},
},
"required": ["name"],
"additionalProperties": False,
"minProperties": 1,
}
basic_create_role_schema = {
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 1,
},
"servers": {
"type": "array",
"items": {
"type": "object",
"properties": {
"server_id": {
"type": "integer",
"minimum": 1,
},
"permissions": {
"type": "string",
"pattern": "^[01]{8}$", # 8 bits, see EnumPermissionsServer
},
},
"required": ["server_id", "permissions"],
},
},
},
"additionalProperties": False,
"minProperties": 1,
}
@ -86,7 +116,10 @@ class ApiRolesIndexHandler(BaseApiHandler):
)
try:
validate(data, create_role_schema)
if auth_data[4]["superuser"]:
validate(data, create_role_schema)
else:
validate(data, basic_create_role_schema)
except ValidationError as e:
return self.finish_json(
400,
@ -98,6 +131,9 @@ class ApiRolesIndexHandler(BaseApiHandler):
)
role_name = data["name"]
manager = data.get("manager", None)
if manager == self.controller.users.get_id_by_name("SYSTEM") or manager == 0:
manager = None
# Get the servers
servers_dict = {server["server_id"]: server for server in data["servers"]}
@ -116,9 +152,7 @@ class ApiRolesIndexHandler(BaseApiHandler):
400, {"status": "error", "error": "ROLE_NAME_ALREADY_EXISTS"}
)
role_id = self.controller.roles.add_role_advanced(
role_name, servers, user["user_id"]
)
role_id = self.controller.roles.add_role_advanced(role_name, servers, manager)
self.controller.management.add_to_audit_log(
user["user_id"],

View File

@ -153,9 +153,18 @@ class ApiRolesRoleIndexHandler(BaseApiHandler):
},
)
manager = data.get(
"manager", self.controller.roles.get_role(role_id)["manager"]
)
if manager == self.controller.users.get_id_by_name("system") or manager == 0:
manager = None
try:
self.controller.roles.update_role_advanced(
role_id, data.get("role_name", None), data.get("servers", None)
role_id,
data.get("name", None),
data.get("servers", None),
manager,
)
except DoesNotExist:
return self.finish_json(404, {"status": "error", "error": "ROLE_NOT_FOUND"})

View File

@ -50,9 +50,6 @@
<div class="">
<div class="">
<form id="role_form" class="forms-sample" method="post" action="{{ '/panel/add_role' if data['new_role'] else '/panel/edit_role' }}">
{% raw xsrf_form_html() %}
<input type="hidden" name="id" value="{{ data['role']['role_id'] }}">
<input type="hidden" name="subpage" value="config">
<div class="card">
<div class="card-header header-sm d-flex justify-content-between align-items-center">
@ -61,7 +58,7 @@
<div class="card-body">
<div class="form-group">
<label for="role_name">{{ translate('rolesConfig', 'roleName', data['lang']) }} <small class="text-muted ml-1"> - {{ translate('rolesConfig', 'roleDesc', data['lang']) }}</small> </label>
<input type="text" class="form-control" name="role_name" id="role_name" value="{{ data['role']['role_name'] }}" placeholder="Role Name" >
<input type="text" class="form-control" name="name" id="role_name" value="{{ data['role']['role_name'] }}" placeholder="Role Name" >
</div>
<br />
@ -188,11 +185,11 @@
<tr>
<td>{{ server['server_name'] }}</td>
<td>
<input type="checkbox" class="" onclick="enable_disable(event)" data-id="{{server['server_id']}}"
<input type="checkbox" class="access" onclick="enable_disable(event)" data-id="{{server['server_id']}}"
id="server_{{ server['server_id'] }}_access"
name="server_{{ server['server_id'] }}_access"
{{ 'checked' if server['server_id'] in data['role']['servers'] else '' }}
autocomplete="off" value="1">
autocomplete="off" value="1" form="dummy">
</td>
{% for permission in data['permissions_all'] %}
{% if server['server_id'] in data['role']['servers'] %}
@ -201,14 +198,14 @@
id="permission_{{ server['server_id'] }}_{{ permission.name }}"
name="permission_{{ server['server_id'] }}_{{ permission.name }}"
{{ 'checked' if permission in data['permissions_dict'].get(server['server_id'], []) else '' }}
autocomplete="off" value="1">
autocomplete="off" value="1" form="dummy">
</td>
{% else %}
<td>
<input type="checkbox" class="{{server['server_id']}}_perms"
id="permission_{{ server['server_id'] }}_{{ permission.name }}"
name="permission_{{ server['server_id'] }}_{{ permission.name }}"
autocomplete="off" value="1" disabled>
autocomplete="off" value="1" disabled form="dummy">
</td>
{% end %}
{% end %}
@ -284,7 +281,7 @@
<a class="btn btn-sm btn-danger disabled"><i class="fas fa-trash"></i>{{ translate('rolesConfig', 'delRole', data['lang']) }}</a><br />
<small>{{ translate('rolesConfig', 'doesNotExist', data['lang']) }}</small>
{% else %}
<a href="/panel/remove_role?id={{ data['role']['role_id'] }}" class="btn btn-sm btn-danger"><i class="fas fa-trash"></i>{{ translate('rolesConfig', 'delRole', data['lang']) }}</a>
<button onclick="del_role()" class="btn btn-sm btn-danger"><i class="fas fa-trash"></i>{{ translate('rolesConfig', 'delRole', data['lang']) }}</button>
{% end %}
</div>
</div>
@ -341,24 +338,87 @@
console.log( "ready!" );
});
const roleId = new URLSearchParams(document.location.search).get('id');
function replacer(key, value) {
if (key === "permissions"){
return value;
}
if (key === "servers" && value.length === 0){
return value;
}
if (typeof value == "boolean") {
console.log(value);
return value
} else {
return (isNaN(value) ? value : +value);
}
}
$("#config_form").on("submit", async function (e) {
async function del_role(){
var token = getCookie("_xsrf")
let res = await fetch(`/api/v2/roles/${roleId}`, {
method: "DELETE",
headers: {
'X-XSRFToken': token
},
});
let responseData = await res.json();
if (responseData.status === "ok") {
window.location.href = "/panel/panel_config";
} else {
bootbox.alert({
title: responseData.error,
message: responseData.error_data
});
}
}
$("#role_form").on("submit", async function (e) {
e.preventDefault();
var token = getCookie("_xsrf")
let configForm = document.getElementById("config_form");
let roleForm = document.getElementById("role_form");
let formData = new FormData(configForm);
let server_ids = $('.access').map(function() {
if ($(this).is(':checked')){
return $(this).data('id');
}
}).get();
let servers = []
for(i=0; i < server_ids.length; i++){
arrchecked = $(`.${server_ids[i]}_perms`).map(function() {
if(this.checked){
return "1";
}else{
return "0"
}
}).get();
servers.push({"server_id": server_ids[i], "permissions": arrchecked.join("")});
}
console.log(servers)
let formData = new FormData(roleForm);
//Create an object from the form data entries
let formDataObject = Object.fromEntries(formData.entries());
let send_object = Object()
send_object.servers = []
send_object.name = formDataObject.role_name
formDataObject.servers = servers;
console.log(formDataObject);
//We need to make sure these are sent regardless of whether or not they're checked
// Format the plain form data as JSON
let formDataJsonString = JSON.stringify(formDataObject, replacer);
let res = await fetch(`/api/v2/roles/${roleId}`, {
method: 'PATCH',
console.log(formDataJsonString);
if (roleId){
url = `/api/v2/roles/${roleId}`
method = 'PATCH'
}else{
url = `/api/v2/roles/`
method = 'POST'
}
let res = await fetch(url, {
method: method,
headers: {
'X-XSRFToken': token
},
@ -366,14 +426,14 @@
});
let responseData = await res.json();
if (responseData.status === "ok") {
window.location.reload();
window.location.href = "/panel/panel_config";
} else {
bootbox.alert({
title: responseData.error,
message: responseData.error_data
});
}
});
}
});