Add get/delete functions for api keys

This commit is contained in:
amcmanu3 2023-09-04 11:42:07 -04:00
parent 2f69464e7a
commit a6b7b84b3b
3 changed files with 179 additions and 84 deletions

View File

@ -96,6 +96,11 @@ def api_handlers(handler_args):
ApiUsersUserKeyHandler,
handler_args,
),
(
r"/api/v2/users/([0-9]+)/key/([0-9]+)/?",
ApiUsersUserKeyHandler,
handler_args,
),
(
r"/api/v2/users/([0-9]+)/?",
ApiUsersUserIndexHandler,

View File

@ -9,7 +9,7 @@ logger = logging.getLogger(__name__)
class ApiUsersUserKeyHandler(BaseApiHandler):
def get(self, _user_id: str, key_id: int):
def get(self, user_id: str, key_id=None):
auth_data = self.authenticate_user()
if not auth_data:
return
@ -20,38 +20,72 @@ class ApiUsersUserKeyHandler(BaseApiHandler):
_,
_user,
) = auth_data
if key_id:
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
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"]
):
return self.finish_json(
400,
{
"status": "error",
"error": "NOT AUTHORIZED",
"error_data": "TRIED TO EDIT KEY WIHTOUT AUTH",
},
)
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."
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(),
)
data_key = self.controller.authentication.generate(
key.user_id_id, {"token_id": key.token_id}
)
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}
),
}
)
return self.finish_json(
200,
{"status": "ok", "data": data_key},
)
else:
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",
},
)
keys = []
for key in self.controller.users.get_user_api_keys(str(user_id)):
keys.append(
{
"id": key.token_id,
"name": key.name,
"server_permissions": key.server_permissions,
"crafty_permissions": key.crafty_permissions,
"superuser": key.superuser,
}
)
self.finish_json(
200,
{
"status": "ok",
"data": keys,
},
)
def patch(self, user_id: str):
user_key_schema = {
@ -144,3 +178,61 @@ class ApiUsersUserKeyHandler(BaseApiHandler):
source_ip=self.get_remote_ip(),
)
self.finish_json(200, {"status": "ok", "data": {"id": key_id}})
def delete(self, _user_id: str, key_id: str):
auth_data = self.authenticate_user()
if not auth_data:
return
(
_,
_exec_user_crafty_permissions,
_,
_,
_user,
) = auth_data
if key_id:
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
# does this user id exist?
target_key = self.controller.users.get_user_api_key(key_id)
if not target_key:
return self.finish_json(
400,
{
"status": "error",
"error": "INVALID KEY",
"error_data": "INVALID KEY ID",
},
)
if (
target_key.user_id != 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",
},
)
self.controller.users.delete_user_api_key(key_id)
self.controller.management.add_to_audit_log(
auth_data[4]["user_id"],
f"Removed API key {target_key} "
f"(ID: {key_id}) from user {auth_data[4]['user_id']}",
server_id=0,
source_ip=self.get_remote_ip(),
)
return self.finish_json(
200,
{"status": "ok", "data": {"id": key_id}},
)

View File

@ -86,17 +86,14 @@
apikey.server_permissions }}
{{ translate('apiKeys', 'crafty', data['lang']) }} {{
apikey.crafty_permissions }}</td>
<td>
<button class="btn btn-danger delete-api-key"
<td><button class="btn btn-danger delete-api-key"
data-key-id="{{ apikey.token_id }}"
data-key-name="{{ apikey.name }}">{{
translate('panelConfig', 'delete', data['lang'])
}}</button>
data-key-name="{{ apikey.name }}">{{translate('panelConfig',
'delete', data['lang'])}}</button>
<button class="btn btn-outline-primary get-a-token"
data-key-id="{{ apikey.token_id }}"
data-key-name="{{ apikey.name }}">{{
translate('apiKeys', 'getToken', data['lang']) }}
</button>
data-key-name="{{ apikey.name }}">{{translate('apiKeys',
'getToken', data['lang'])}}</button>
</td>
</tr>
{% end %}
@ -265,55 +262,56 @@
});
}
});
console.log("ready!");
$('.delete-api-key').click(function () {
var keyId = $(this).data("key-id");
var keyName = $(this).data("key-name");
bootbox.confirm({
title: `Remove API key ${keyName}?`,
message: "Do you want to delete this API key? This cannot be undone.",
buttons: {
cancel: {
label: '<i class="fas fa-times"></i> {{ translate("panelConfig", "cancel", data['lang']) }}'
},
confirm: {
label: '<i class="fas fa-check"></i> {{ translate("serverBackups", "confirm", data['lang']) }}'
}
},
callback: function (result) {
if (result) {
var token = getCookie("_xsrf")
$.ajax({
type: "DELETE",
headers: { 'X-XSRFToken': token },
url: '/panel/remove_apikey?id=' + keyId,
success: function (data) {
location.reload();
},
});
}
}
});
})
$('.get-a-token').click(function () {
var keyId = $(this).data("key-id");
var keyName = $(this).data("key-name");
var token = getCookie("_xsrf")
$.ajax({
type: "POST",
headers: { 'X-XSRFToken': token },
url: '/panel/get_token?id=' + keyId,
success: function (data) {
bootbox.alert({
title: `API token for ${keyName}`,
message: `Here is an API token for ${keyName}:\n<pre style="white-space: pre-wrap;color:white;word-break:break-all;background: grey;border-radius: 5px;">${data}</pre>`
});
},
});
})
});
$(document).ready(function () {
console.log("ready!");
$('.delete-api-key').click(async function () {
let keyId = $(this).data("key-id");
let keyName = $(this).data("key-name");
let token = getCookie("_xsrf");
let res = await fetch(`/api/v2/users/${userId}/key/${keyId}`, {
method: 'DELETE',
headers: {
'X-XSRFToken': token
},
});
let responseData = await res.json();
if (responseData.status === "ok") {
location.reload()
} else {
bootbox.alert({
title: responseData.error,
message: responseData.error_data
});
}
})
$('.get-a-token').click(async function () {
let keyId = $(this).data("key-id");
let keyName = $(this).data("key-name");
let token = getCookie("_xsrf");
let res = await fetch(`/api/v2/users/${userId}/key/${keyId}`, {
method: 'GET',
headers: {
'X-XSRFToken': token
},
});
let responseData = await res.json();
if (responseData.status === "ok") {
bootbox.alert({
title: `API token for ${keyName}`,
message: `Here is an API token for ${keyName}:\n<pre style="white-space: pre-wrap;color:white;word-break:break-all;background: grey;border-radius: 5px;">${responseData.data}</pre>`
});
} else {
bootbox.alert({
title: responseData.error,
message: responseData.error_data
});
}
});
});
</script>