mirror of
https://gitlab.com/crafty-controller/crafty-4.git
synced 2024-08-30 18:23:09 +00:00
Use API for config.json
This commit is contained in:
@ -5,6 +5,7 @@ from datetime import datetime
|
|||||||
import platform
|
import platform
|
||||||
import shutil
|
import shutil
|
||||||
import time
|
import time
|
||||||
|
import json
|
||||||
import logging
|
import logging
|
||||||
import threading
|
import threading
|
||||||
from peewee import DoesNotExist
|
from peewee import DoesNotExist
|
||||||
@ -84,6 +85,13 @@ class Controller:
|
|||||||
def set_project_root(self, root_dir):
|
def set_project_root(self, root_dir):
|
||||||
self.project_root = root_dir
|
self.project_root = root_dir
|
||||||
|
|
||||||
|
def set_config_json(self, data):
|
||||||
|
keys = list(data.keys())
|
||||||
|
keys.sort()
|
||||||
|
sorted_data = {i: data[i] for i in keys}
|
||||||
|
with open(self.helper.settings_file, "w", encoding="utf-8") as f:
|
||||||
|
json.dump(sorted_data, f, indent=4)
|
||||||
|
|
||||||
def package_support_logs(self, exec_user):
|
def package_support_logs(self, exec_user):
|
||||||
if exec_user["preparing"]:
|
if exec_user["preparing"]:
|
||||||
return
|
return
|
||||||
|
@ -49,6 +49,7 @@ from app.classes.web.routes.api.users.user.permissions import (
|
|||||||
)
|
)
|
||||||
from app.classes.web.routes.api.users.user.pfp import ApiUsersUserPfpHandler
|
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.users.user.public import ApiUsersUserPublicHandler
|
||||||
|
from app.classes.web.routes.api.crafty.config.index import ApiCraftyConfigIndexHandler
|
||||||
|
|
||||||
|
|
||||||
def api_handlers(handler_args):
|
def api_handlers(handler_args):
|
||||||
@ -64,6 +65,11 @@ def api_handlers(handler_args):
|
|||||||
ApiAuthInvalidateTokensHandler,
|
ApiAuthInvalidateTokensHandler,
|
||||||
handler_args,
|
handler_args,
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
r"/api/v2/crafty/config/?",
|
||||||
|
ApiCraftyConfigIndexHandler,
|
||||||
|
handler_args,
|
||||||
|
),
|
||||||
# User routes
|
# User routes
|
||||||
(
|
(
|
||||||
r"/api/v2/users/?",
|
r"/api/v2/users/?",
|
||||||
|
113
app/classes/web/routes/api/crafty/config/index.py
Normal file
113
app/classes/web/routes/api/crafty/config/index.py
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
from jsonschema import ValidationError, validate
|
||||||
|
import orjson
|
||||||
|
from playhouse.shortcuts import model_to_dict
|
||||||
|
from app.classes.web.base_api_handler import BaseApiHandler
|
||||||
|
|
||||||
|
config_json_schema = {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"http_port": {"type": "integer"},
|
||||||
|
"https_port": {"type": "integer"},
|
||||||
|
"language": {
|
||||||
|
"type": "string",
|
||||||
|
},
|
||||||
|
"cookie_expire": {"type": "integer"},
|
||||||
|
"show_errors": {"type": "boolean"},
|
||||||
|
"history_max_age": {"type": "integer"},
|
||||||
|
"stats_update_frequency_seconds": {"type": "integer"},
|
||||||
|
"delete_default_json": {"type": "boolean"},
|
||||||
|
"show_contribute_link": {"type": "boolean"},
|
||||||
|
"virtual_terminal_lines": {"type": "integer"},
|
||||||
|
"max_log_lines": {"type": "integer"},
|
||||||
|
"max_audit_entries": {"type": "integer"},
|
||||||
|
"disabled_language_files": {"type": "array"},
|
||||||
|
"stream_size_GB": {"type": "integer"},
|
||||||
|
"keywords": {"type": "string"},
|
||||||
|
"allow_nsfw_profile_pictures": {"type": "boolean"},
|
||||||
|
"enable_user_self_delete": {"type": "boolean"},
|
||||||
|
"reset_secrets_on_next_boot": {"type": "boolean"},
|
||||||
|
"monitored_mounts": {"type": "array"},
|
||||||
|
"dir_size_poll_freq_minutes": {"type": "integer"},
|
||||||
|
"crafty_logs_delete_after_days": {"type": "integer"},
|
||||||
|
},
|
||||||
|
"additionalProperties": False,
|
||||||
|
"minProperties": 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class ApiCraftyConfigIndexHandler(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"})
|
||||||
|
|
||||||
|
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()],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
def patch(self):
|
||||||
|
auth_data = self.authenticate_user()
|
||||||
|
if not auth_data:
|
||||||
|
return
|
||||||
|
(
|
||||||
|
_,
|
||||||
|
_,
|
||||||
|
_,
|
||||||
|
superuser,
|
||||||
|
user,
|
||||||
|
) = auth_data
|
||||||
|
|
||||||
|
if not superuser:
|
||||||
|
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
|
||||||
|
|
||||||
|
try:
|
||||||
|
data = orjson.loads(self.request.body)
|
||||||
|
except orjson.decoder.JSONDecodeError as e:
|
||||||
|
return self.finish_json(
|
||||||
|
400, {"status": "error", "error": "INVALID_JSON", "error_data": str(e)}
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
validate(data, config_json_schema)
|
||||||
|
except ValidationError as e:
|
||||||
|
return self.finish_json(
|
||||||
|
400,
|
||||||
|
{
|
||||||
|
"status": "error",
|
||||||
|
"error": "INVALID_JSON_SCHEMA",
|
||||||
|
"error_data": str(e),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
self.controller.set_config_json(data)
|
||||||
|
|
||||||
|
self.controller.management.add_to_audit_log(
|
||||||
|
user["user_id"],
|
||||||
|
"edited config.json",
|
||||||
|
server_id=0,
|
||||||
|
source_ip=self.get_remote_ip(),
|
||||||
|
)
|
||||||
|
|
||||||
|
self.finish_json(
|
||||||
|
200,
|
||||||
|
{"status": "ok"},
|
||||||
|
)
|
@ -50,7 +50,6 @@
|
|||||||
<!-- Page Title Header Ends-->
|
<!-- Page Title Header Ends-->
|
||||||
|
|
||||||
<form id="config-form" class="forms-sample" method="post" action="/panel/config_json">
|
<form id="config-form" class="forms-sample" method="post" action="/panel/config_json">
|
||||||
{% raw xsrf_form_html() %}
|
|
||||||
|
|
||||||
{% for item in data['config-json'].items() %}
|
{% for item in data['config-json'].items() %}
|
||||||
{% if item[0] == "reset_secrets_on_next_boot" %}
|
{% if item[0] == "reset_secrets_on_next_boot" %}
|
||||||
@ -156,36 +155,65 @@
|
|||||||
|
|
||||||
{% block js %}
|
{% block js %}
|
||||||
<script>
|
<script>
|
||||||
$("#config-form").submit(function (e) {
|
function replacer(key, value) {
|
||||||
let uuid = uuidv4();
|
if (key == "disabled_language_files") {
|
||||||
var token = getCookie("_xsrf")
|
if (value == 0){
|
||||||
|
return []
|
||||||
|
} else {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (typeof value == "boolean") {
|
||||||
|
return value
|
||||||
|
} else {
|
||||||
|
return (isNaN(value) ? value : +value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$("#config-form").on("submit", async function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
$("#submit-status").html('<i class="fa fa-spinner fa-spin"></i>');
|
$("#submit-status").html('<i class="fa fa-spinner fa-spin"></i>');
|
||||||
/* Convert multiple select to text list */
|
var token = getCookie("_xsrf")
|
||||||
let selected_Lang = $('#lang_select').val();
|
let configForm = document.getElementById("config-form");
|
||||||
$('#disabled_lang').val(selected_Lang);
|
|
||||||
|
|
||||||
let mounts = $('#mount_select').val();
|
let formData = new FormData(configForm);
|
||||||
$('#monitored_mounts').val(mounts);
|
formData.delete("disabled_lang");
|
||||||
|
formData.delete("lang_select");
|
||||||
|
|
||||||
let class_list = document.getElementsByClassName("list");
|
//Create an object from the form data entries
|
||||||
let form_json = convertFormToJSON($("#config-form"));
|
let formDataObject = Object.fromEntries(formData.entries());
|
||||||
for (let i = 0; i < class_list.length; i++) {
|
//We need to make sure these are sent regardless of whether or not they're checked
|
||||||
let str = String($(class_list.item(i)).val())
|
formDataObject.disabled_language_files = $('#lang_select').val();
|
||||||
form_json[$(class_list.item(i)).attr("name")] = uuid + "," + str.replace(/\s/g, '');
|
formDataObject.monitored_mounts = $('#mount_select').val();
|
||||||
};
|
$('#config-form input[type="radio"]:checked').each(function() {
|
||||||
form_json['uuid'] = uuid;
|
if ($(this).val() == 'True'){
|
||||||
$.ajax({
|
formDataObject[this.name] = true;
|
||||||
type: "POST",
|
}else{
|
||||||
headers: { 'X-XSRFToken': token },
|
formDataObject[this.name] = false;
|
||||||
dataType: "text",
|
}
|
||||||
url: '/panel/config_json',
|
|
||||||
data: form_json,
|
|
||||||
success: function (data) {
|
|
||||||
$("#submit-status").html('<i class="fa fa-check"></i>');
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
console.log(formDataObject);
|
||||||
|
// Format the plain form data as JSON
|
||||||
|
let formDataJsonString = JSON.stringify(formDataObject, replacer);
|
||||||
|
|
||||||
|
console.log(formDataJsonString);
|
||||||
|
|
||||||
|
let res = await fetch(`/api/v2/crafty/config/`, {
|
||||||
|
method: 'PATCH',
|
||||||
|
headers: {
|
||||||
|
'X-XSRFToken': token
|
||||||
|
},
|
||||||
|
body: formDataJsonString,
|
||||||
|
});
|
||||||
|
let responseData = await res.json();
|
||||||
|
if (responseData.status === "ok") {
|
||||||
|
$("#submit-status").html('<i class="fa fa-check"></i>');
|
||||||
|
} else {
|
||||||
|
|
||||||
|
bootbox.alert({
|
||||||
|
title: responseData.error,
|
||||||
|
message: responseData.error_data
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function uuidv4() {
|
function uuidv4() {
|
||||||
|
Reference in New Issue
Block a user