mirror of
https://gitlab.com/crafty-controller/crafty-4.git
synced 2025-01-19 01:35:28 +01:00
Add create new API key from api v2
This commit is contained in:
parent
cd4bd681d9
commit
6a4a9f77d9
@ -1525,139 +1525,7 @@ class PanelHandler(BaseHandler):
|
||||
role = self.controller.roles.get_role(r)
|
||||
exec_user_role.add(role["role_name"])
|
||||
|
||||
if page == "edit_user":
|
||||
if bleach.clean(self.get_argument("username", None)).lower() == "system":
|
||||
self.redirect(
|
||||
"/panel/error?error=Unauthorized access: "
|
||||
"system user is not editable"
|
||||
)
|
||||
user_id = bleach.clean(self.get_argument("id", None))
|
||||
user = self.controller.users.get_user_by_id(user_id)
|
||||
username = bleach.clean(self.get_argument("username", None).lower())
|
||||
theme = bleach.clean(self.get_argument("theme", "default"))
|
||||
if (
|
||||
username != self.controller.users.get_user_by_id(user_id)["username"]
|
||||
and username in self.controller.users.get_all_usernames()
|
||||
):
|
||||
self.redirect(
|
||||
"/panel/error?error=Duplicate User: Useranme already exists."
|
||||
)
|
||||
password0 = bleach.clean(self.get_argument("password0", None))
|
||||
password1 = bleach.clean(self.get_argument("password1", None))
|
||||
email = bleach.clean(self.get_argument("email", "default@example.com"))
|
||||
enabled = int(float(self.get_argument("enabled", "0")))
|
||||
try:
|
||||
hints = int(bleach.clean(self.get_argument("hints")))
|
||||
hints = True
|
||||
except:
|
||||
hints = False
|
||||
lang = bleach.clean(
|
||||
self.get_argument("language"), self.helper.get_setting("language")
|
||||
)
|
||||
|
||||
if superuser:
|
||||
# Checks if user is trying to change super user status of self.
|
||||
# We don't want that. Automatically make them stay super user
|
||||
# since we know they are.
|
||||
if str(exec_user["user_id"]) != str(user_id):
|
||||
superuser = int(bleach.clean(self.get_argument("superuser", "0")))
|
||||
else:
|
||||
superuser = 1
|
||||
else:
|
||||
superuser = 0
|
||||
|
||||
if exec_user["superuser"]:
|
||||
manager = self.get_argument("manager")
|
||||
if manager == "":
|
||||
manager = None
|
||||
else:
|
||||
manager = int(manager)
|
||||
else:
|
||||
manager = user["manager"]
|
||||
|
||||
if (
|
||||
not exec_user["superuser"]
|
||||
and int(exec_user["user_id"]) != user["manager"]
|
||||
):
|
||||
if username is None or username == "":
|
||||
self.redirect("/panel/error?error=Invalid username")
|
||||
return
|
||||
if user_id is None:
|
||||
self.redirect("/panel/error?error=Invalid User ID")
|
||||
return
|
||||
if (
|
||||
EnumPermissionsCrafty.USER_CONFIG
|
||||
not in exec_user_crafty_permissions
|
||||
):
|
||||
if str(user_id) != str(exec_user["user_id"]):
|
||||
self.redirect(
|
||||
"/panel/error?error=Unauthorized access: not a user editor"
|
||||
)
|
||||
return
|
||||
|
||||
user_data = {
|
||||
"username": username,
|
||||
"password": password0,
|
||||
"email": email,
|
||||
"lang": lang,
|
||||
"hints": hints,
|
||||
"theme": theme,
|
||||
}
|
||||
self.controller.users.update_user(user_id, user_data=user_data)
|
||||
|
||||
self.controller.management.add_to_audit_log(
|
||||
exec_user["user_id"],
|
||||
f"Edited user {username} (UID:{user_id}) password",
|
||||
server_id=0,
|
||||
source_ip=self.get_remote_ip(),
|
||||
)
|
||||
self.redirect("/panel/panel_config")
|
||||
return
|
||||
# does this user id exist?
|
||||
if not self.controller.users.user_id_exists(user_id):
|
||||
self.redirect("/panel/error?error=Invalid User ID")
|
||||
return
|
||||
else:
|
||||
if password0 != password1:
|
||||
self.redirect("/panel/error?error=Passwords must match")
|
||||
return
|
||||
|
||||
roles = self.get_user_role_memberships()
|
||||
permissions_mask, server_quantity = self.get_perms_quantity()
|
||||
|
||||
# if email is None or "":
|
||||
# email = "default@example.com"
|
||||
|
||||
user_data = {
|
||||
"username": username,
|
||||
"manager": manager,
|
||||
"password": password0,
|
||||
"email": email,
|
||||
"enabled": enabled,
|
||||
"roles": roles,
|
||||
"lang": lang,
|
||||
"superuser": superuser,
|
||||
"hints": hints,
|
||||
"theme": theme,
|
||||
}
|
||||
user_crafty_data = {
|
||||
"permissions_mask": permissions_mask,
|
||||
"server_quantity": server_quantity,
|
||||
}
|
||||
self.controller.users.update_user(
|
||||
user_id, user_data=user_data, user_crafty_data=user_crafty_data
|
||||
)
|
||||
|
||||
self.controller.management.add_to_audit_log(
|
||||
exec_user["user_id"],
|
||||
f"Edited user {username} (UID:{user_id}) with roles {roles} "
|
||||
f"and permissions {permissions_mask}",
|
||||
server_id=0,
|
||||
source_ip=self.get_remote_ip(),
|
||||
)
|
||||
self.redirect("/panel/panel_config")
|
||||
|
||||
elif page == "edit_user_apikeys":
|
||||
if page == "edit_user_apikeys":
|
||||
user_id = self.get_argument("id", None)
|
||||
name = self.get_argument("name", None)
|
||||
superuser = self.get_argument("superuser", None) == "1"
|
||||
@ -1737,100 +1605,6 @@ class PanelHandler(BaseHandler):
|
||||
)
|
||||
self.finish()
|
||||
|
||||
elif page == "add_user":
|
||||
username = bleach.clean(self.get_argument("username", None).lower())
|
||||
if username.lower() == "system":
|
||||
self.redirect(
|
||||
"/panel/error?error=Unauthorized access: "
|
||||
"username system is reserved for the Crafty system."
|
||||
" Please choose a different username."
|
||||
)
|
||||
return
|
||||
password0 = bleach.clean(self.get_argument("password0", None))
|
||||
password1 = bleach.clean(self.get_argument("password1", None))
|
||||
email = bleach.clean(self.get_argument("email", "default@example.com"))
|
||||
enabled = int(float(self.get_argument("enabled", "0")))
|
||||
theme = bleach.clean(self.get_argument("theme"), "default")
|
||||
hints = True
|
||||
lang = bleach.clean(
|
||||
self.get_argument("lang", self.helper.get_setting("language"))
|
||||
)
|
||||
# We don't want a non-super user to be able to create a super user.
|
||||
if superuser:
|
||||
new_superuser = int(bleach.clean(self.get_argument("superuser", "0")))
|
||||
else:
|
||||
new_superuser = 0
|
||||
|
||||
if EnumPermissionsCrafty.USER_CONFIG not in exec_user_crafty_permissions:
|
||||
self.redirect(
|
||||
"/panel/error?error=Unauthorized access: not a user editor"
|
||||
)
|
||||
return
|
||||
|
||||
if (
|
||||
not self.controller.crafty_perms.can_add_user(exec_user["user_id"])
|
||||
and not exec_user["superuser"]
|
||||
):
|
||||
self.redirect(
|
||||
"/panel/error?error=Unauthorized access: quantity limit reached"
|
||||
)
|
||||
return
|
||||
if username is None or username == "":
|
||||
self.redirect("/panel/error?error=Invalid username")
|
||||
return
|
||||
|
||||
if exec_user["superuser"]:
|
||||
manager = self.get_argument("manager")
|
||||
if manager == "":
|
||||
manager = None
|
||||
else:
|
||||
manager = int(manager)
|
||||
else:
|
||||
manager = int(exec_user["user_id"])
|
||||
# does this user id exist?
|
||||
if self.controller.users.get_id_by_name(username) is not None:
|
||||
self.redirect("/panel/error?error=User exists")
|
||||
return
|
||||
|
||||
if password0 != password1:
|
||||
self.redirect("/panel/error?error=Passwords must match")
|
||||
return
|
||||
|
||||
roles = self.get_user_role_memberships()
|
||||
permissions_mask, server_quantity = self.get_perms_quantity()
|
||||
|
||||
user_id = self.controller.users.add_user(
|
||||
username,
|
||||
manager=manager,
|
||||
password=password0,
|
||||
email=email,
|
||||
enabled=enabled,
|
||||
superuser=new_superuser,
|
||||
theme=theme,
|
||||
)
|
||||
user_data = {"roles": roles, "lang": lang, "hints": True}
|
||||
user_crafty_data = {
|
||||
"permissions_mask": permissions_mask,
|
||||
"server_quantity": server_quantity,
|
||||
}
|
||||
self.controller.users.update_user(
|
||||
user_id, user_data=user_data, user_crafty_data=user_crafty_data
|
||||
)
|
||||
|
||||
self.controller.management.add_to_audit_log(
|
||||
exec_user["user_id"],
|
||||
f"Added user {username} (UID:{user_id})",
|
||||
server_id=0,
|
||||
source_ip=self.get_remote_ip(),
|
||||
)
|
||||
self.controller.management.add_to_audit_log(
|
||||
exec_user["user_id"],
|
||||
f"Edited user {username} (UID:{user_id}) with roles {roles}",
|
||||
server_id=0,
|
||||
source_ip=self.get_remote_ip(),
|
||||
)
|
||||
self.redirect("/panel/panel_config")
|
||||
|
||||
else:
|
||||
self.set_status(404)
|
||||
page_data = {
|
||||
|
@ -49,6 +49,7 @@ from app.classes.web.routes.api.users.user.index import ApiUsersUserIndexHandler
|
||||
from app.classes.web.routes.api.users.user.permissions import (
|
||||
ApiUsersUserPermissionsHandler,
|
||||
)
|
||||
from app.classes.web.routes.api.users.user.api import ApiUsersUserKeyHandler
|
||||
from app.classes.web.routes.api.users.user.pfp import ApiUsersUserPfpHandler
|
||||
from app.classes.web.routes.api.users.user.public import ApiUsersUserPublicHandler
|
||||
from app.classes.web.routes.api.crafty.config.index import ApiCraftyConfigIndexHandler
|
||||
@ -90,6 +91,11 @@ def api_handlers(handler_args):
|
||||
ApiUsersIndexHandler,
|
||||
handler_args,
|
||||
),
|
||||
(
|
||||
r"/api/v2/users/([0-9]+)/key/?",
|
||||
ApiUsersUserKeyHandler,
|
||||
handler_args,
|
||||
),
|
||||
(
|
||||
r"/api/v2/users/([0-9]+)/?",
|
||||
ApiUsersUserIndexHandler,
|
||||
|
146
app/classes/web/routes/api/users/user/api.py
Normal file
146
app/classes/web/routes/api/users/user/api.py
Normal file
@ -0,0 +1,146 @@
|
||||
import json
|
||||
import logging
|
||||
|
||||
from jsonschema import ValidationError, validate
|
||||
from app.classes.web.base_api_handler import BaseApiHandler
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ApiUsersUserKeyHandler(BaseApiHandler):
|
||||
def get(self, _user_id: str, key_id: int):
|
||||
auth_data = self.authenticate_user()
|
||||
if not auth_data:
|
||||
return
|
||||
(
|
||||
_,
|
||||
_exec_user_crafty_permissions,
|
||||
_,
|
||||
_,
|
||||
_user,
|
||||
) = auth_data
|
||||
|
||||
key = self.controller.users.get_user_api_key(key_id)
|
||||
# does this user id exist?
|
||||
if key is None:
|
||||
self.redirect("/panel/error?error=Invalid Key ID")
|
||||
return
|
||||
|
||||
if (
|
||||
str(key.user_id) != str(auth_data[4]["user_id"])
|
||||
and not auth_data[4]["superuser"]
|
||||
):
|
||||
self.redirect(
|
||||
"/panel/error?error=You are not authorized to access this key."
|
||||
)
|
||||
return
|
||||
|
||||
self.controller.management.add_to_audit_log(
|
||||
auth_data[4]["user_id"],
|
||||
f"Generated a new API token for the key {key.name} "
|
||||
f"from user with UID: {key.user_id}",
|
||||
server_id=0,
|
||||
source_ip=self.get_remote_ip(),
|
||||
)
|
||||
|
||||
self.finish_json(
|
||||
{
|
||||
"status": "ok",
|
||||
"data": self.controller.authentication.generate(
|
||||
key.user_id_id, {"token_id": key.token_id}
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
def patch(self, user_id: str):
|
||||
user_key_schema = {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {"type": "string", "minLength": 3},
|
||||
"server_permissions_mask": {
|
||||
"type": "string",
|
||||
"pattern": "^[01]{8}$", # 8 bits, see EnumPermissionsServer
|
||||
},
|
||||
"crafty_permissions_mask": {
|
||||
"type": "string",
|
||||
"pattern": "^[01]{3}$", # 8 bits, see EnumPermissionsCrafty
|
||||
},
|
||||
"superuser": {"type": "boolean"},
|
||||
},
|
||||
"additionalProperties": False,
|
||||
"minProperties": 1,
|
||||
}
|
||||
auth_data = self.authenticate_user()
|
||||
if not auth_data:
|
||||
return
|
||||
(
|
||||
_,
|
||||
_exec_user_crafty_permissions,
|
||||
_,
|
||||
_superuser,
|
||||
user,
|
||||
) = auth_data
|
||||
|
||||
try:
|
||||
data = json.loads(self.request.body)
|
||||
except json.decoder.JSONDecodeError as e:
|
||||
return self.finish_json(
|
||||
400, {"status": "error", "error": "INVALID_JSON", "error_data": str(e)}
|
||||
)
|
||||
|
||||
try:
|
||||
validate(data, user_key_schema)
|
||||
except ValidationError as e:
|
||||
return self.finish_json(
|
||||
400,
|
||||
{
|
||||
"status": "error",
|
||||
"error": "INVALID_JSON_SCHEMA",
|
||||
"error_data": str(e),
|
||||
},
|
||||
)
|
||||
|
||||
if user_id == "@me":
|
||||
user_id = user["user_id"]
|
||||
# does this user id exist?
|
||||
if not self.controller.users.user_id_exists(user_id):
|
||||
return self.finish_json(
|
||||
400,
|
||||
{
|
||||
"status": "error",
|
||||
"error": "USER NOT FOUND",
|
||||
"error_data": "USER_NOT_FOUND",
|
||||
},
|
||||
)
|
||||
|
||||
if (
|
||||
str(user_id) != str(auth_data[4]["user_id"])
|
||||
and not auth_data[4]["superuser"]
|
||||
):
|
||||
return self.finish_json(
|
||||
400,
|
||||
{
|
||||
"status": "error",
|
||||
"error": "NOT AUTHORIZED",
|
||||
"error_data": "TRIED TO EDIT KEY WIHTOUT AUTH",
|
||||
},
|
||||
)
|
||||
|
||||
key_id = self.controller.users.add_user_api_key(
|
||||
data["name"],
|
||||
user_id,
|
||||
data["superuser"],
|
||||
data["server_permissions_mask"],
|
||||
data["crafty_permissions_mask"],
|
||||
)
|
||||
|
||||
self.controller.management.add_to_audit_log(
|
||||
auth_data[4]["user_id"],
|
||||
f"Added API key {data['name']} with crafty permissions "
|
||||
f"{data['crafty_permissions_mask']}"
|
||||
f" and {data['server_permissions_mask']} for user with UID: {user_id}",
|
||||
server_id=0,
|
||||
source_ip=self.get_remote_ip(),
|
||||
)
|
||||
self.finish_json(200, {"status": "ok", "data": {"id": key_id}})
|
@ -115,10 +115,7 @@
|
||||
'createNew', data['lang']) }}</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form id="user_form" class="forms-sample" method="post"
|
||||
action="/panel/edit_user_apikeys">
|
||||
{% raw xsrf_form_html() %}
|
||||
<input type="hidden" name="id" value="{{ data['user']['user_id'] }}">
|
||||
<form id="user_api_form" class="forms-sample">
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="username">{{ translate('apiKeys', 'name',
|
||||
@ -142,7 +139,7 @@
|
||||
}}</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="checkbox" class=""
|
||||
<input type="checkbox" class="server_perm"
|
||||
id="permission_{{ permission.name }}"
|
||||
name="permission_{{ permission.name }}" value="1">
|
||||
</td>
|
||||
@ -154,7 +151,7 @@
|
||||
}}</label>
|
||||
</td>
|
||||
<td>
|
||||
<input type="checkbox" class=""
|
||||
<input type="checkbox" class="crafty_perm"
|
||||
id="permission_{{ permission.name }}"
|
||||
name="permission_{{ permission.name }}" value="1">
|
||||
</td>
|
||||
@ -201,8 +198,74 @@
|
||||
var r = document.cookie.match("\\b" + name + "=([^;]*)\\b");
|
||||
return r ? r[1] : undefined;
|
||||
}
|
||||
|
||||
const userId = new URLSearchParams(document.location.search).get('id')
|
||||
$(document).ready(function () {
|
||||
$("#user_api_form").on("submit", async function (e) {
|
||||
e.preventDefault();
|
||||
var token = getCookie("_xsrf")
|
||||
let apiForm = document.getElementById("user_api_form");
|
||||
|
||||
let formData = new FormData(apiForm);
|
||||
|
||||
//Create an object from the form data entries
|
||||
let formDataObject = Object.fromEntries(formData.entries());
|
||||
//We need to make sure these are sent regardless of whether or not they're checked
|
||||
formDataObject.disabled_language_files = $('#lang_select').val();
|
||||
$('#user_api_form input[type="checkbox"]:checked').each(function () {
|
||||
if ($(this).val() == 'True') {
|
||||
formDataObject[this.name] = true;
|
||||
} else {
|
||||
formDataObject[this.name] = false;
|
||||
}
|
||||
});
|
||||
let server_permissions = $('.server_perm').map(function () {
|
||||
if (this.checked) {
|
||||
return "1";
|
||||
} else {
|
||||
return "0"
|
||||
}
|
||||
}).get();
|
||||
server_permissions = server_permissions.join("");
|
||||
|
||||
let crafty_permissions = $('.crafty_perm').map(function () {
|
||||
if (this.checked) {
|
||||
return "1";
|
||||
} else {
|
||||
return "0"
|
||||
}
|
||||
}).get();
|
||||
crafty_permissions = crafty_permissions.join("");
|
||||
console.log(server_permissions);
|
||||
console.log(crafty_permissions);
|
||||
console.log(formDataObject);
|
||||
// Format the plain form data as JSON
|
||||
let formDataJsonString = JSON.stringify({
|
||||
"name": formDataObject.name,
|
||||
"server_permissions_mask": server_permissions,
|
||||
"crafty_permissions_mask": crafty_permissions,
|
||||
"superuser": $("#superuser").prop('checked'),
|
||||
});
|
||||
console.log(formDataJsonString);
|
||||
|
||||
let res = await fetch(`/api/v2/users/${userId}/key/`, {
|
||||
method: 'PATCH',
|
||||
headers: {
|
||||
'X-XSRFToken': token
|
||||
},
|
||||
body: formDataJsonString,
|
||||
});
|
||||
let responseData = await res.json();
|
||||
if (responseData.status === "ok") {
|
||||
location.reload();
|
||||
} else {
|
||||
|
||||
bootbox.alert({
|
||||
title: responseData.error,
|
||||
message: responseData.error_data
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
console.log("ready!");
|
||||
$('.delete-api-key').click(function () {
|
||||
var keyId = $(this).data("key-id");
|
||||
|
Loading…
x
Reference in New Issue
Block a user