mirror of
https://gitlab.com/crafty-controller/crafty-4.git
synced 2024-08-30 18:23:09 +00:00
Add login photo to API v2
This commit is contained in:
parent
61699d6a27
commit
e79f33fcc4
@ -1,6 +1,9 @@
|
||||
import os
|
||||
import json
|
||||
from jsonschema import ValidationError, validate
|
||||
import orjson
|
||||
from playhouse.shortcuts import model_to_dict
|
||||
from app.classes.shared.file_helpers import FileHelpers
|
||||
from app.classes.web.base_api_handler import BaseApiHandler
|
||||
|
||||
config_json_schema = {
|
||||
@ -33,6 +36,24 @@ config_json_schema = {
|
||||
"additionalProperties": False,
|
||||
"minProperties": 1,
|
||||
}
|
||||
customize_json_schema = {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"photo": {"type": "string"},
|
||||
"opacity": {"type": "string"},
|
||||
},
|
||||
"additionalProperties": False,
|
||||
"minProperties": 1,
|
||||
}
|
||||
|
||||
photo_delete_schema = {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"photo": {"type": "string"},
|
||||
},
|
||||
"additionalProperties": False,
|
||||
"minProperties": 1,
|
||||
}
|
||||
|
||||
|
||||
class ApiCraftyConfigIndexHandler(BaseApiHandler):
|
||||
@ -111,3 +132,181 @@ class ApiCraftyConfigIndexHandler(BaseApiHandler):
|
||||
200,
|
||||
{"status": "ok"},
|
||||
)
|
||||
|
||||
|
||||
class ApiCraftyCustomizeIndexHandler(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, customize_json_schema)
|
||||
except ValidationError as e:
|
||||
return self.finish_json(
|
||||
400,
|
||||
{
|
||||
"status": "error",
|
||||
"error": "INVALID_JSON_SCHEMA",
|
||||
"error_data": str(e),
|
||||
},
|
||||
)
|
||||
if not self.helper.validate_traversal(
|
||||
os.path.join(
|
||||
self.controller.project_root,
|
||||
"app/frontend/static/assets/images/auth/",
|
||||
),
|
||||
os.path.join(
|
||||
self.controller.project_root,
|
||||
f"app/frontend/static/assets/images/auth/{data['photo']}",
|
||||
),
|
||||
):
|
||||
return self.finish_json(
|
||||
400,
|
||||
{
|
||||
"status": "error",
|
||||
"error": "TRAVERSAL DETECTED",
|
||||
"error_data": "TRIED TO REACH FILES THAT ARE"
|
||||
" NOT SUPPOSED TO BE ACCESSIBLE",
|
||||
},
|
||||
)
|
||||
self.controller.management.add_to_audit_log(
|
||||
user["user_id"],
|
||||
f"customized login photo: {data['photo']}/{data['opacity']}",
|
||||
server_id=0,
|
||||
source_ip=self.get_remote_ip(),
|
||||
)
|
||||
self.controller.management.set_login_opacity(int(data["opacity"]))
|
||||
if data["photo"] == "login_1.jpg":
|
||||
self.controller.management.set_login_image("login_1.jpg")
|
||||
self.controller.cached_login = f"{data['photo']}"
|
||||
else:
|
||||
self.controller.management.set_login_image(f"custom/{data['photo']}")
|
||||
self.controller.cached_login = f"custom/{data['photo']}"
|
||||
self.finish_json(
|
||||
200,
|
||||
{
|
||||
"status": "ok",
|
||||
"data": {"photo": data["photo"], "opacity": data["opacity"]},
|
||||
},
|
||||
)
|
||||
|
||||
def delete(self):
|
||||
auth_data = self.authenticate_user()
|
||||
if not auth_data:
|
||||
return
|
||||
|
||||
if not auth_data[4]["superuser"]:
|
||||
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
|
||||
|
||||
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, photo_delete_schema)
|
||||
except ValidationError as e:
|
||||
return self.finish_json(
|
||||
400,
|
||||
{
|
||||
"status": "error",
|
||||
"error": "INVALID_JSON_SCHEMA",
|
||||
"error_data": str(e),
|
||||
},
|
||||
)
|
||||
if not self.helper.validate_traversal(
|
||||
os.path.join(
|
||||
self.controller.project_root,
|
||||
"app",
|
||||
"frontend",
|
||||
"/static/assets/images/auth/",
|
||||
),
|
||||
os.path.join(
|
||||
self.controller.project_root,
|
||||
"app",
|
||||
"frontend",
|
||||
"/static/assets/images/auth/",
|
||||
data["photo"],
|
||||
),
|
||||
):
|
||||
return self.finish_json(
|
||||
400,
|
||||
{
|
||||
"status": "error",
|
||||
"error": "TRAVERSAL DETECTED",
|
||||
"error_data": "TRIED TO REACH FILES THAT ARE"
|
||||
" NOT SUPPOSED TO BE ACCESSIBLE",
|
||||
},
|
||||
)
|
||||
if data["photo"] == "login_1.jpg":
|
||||
return self.finish_json(
|
||||
400,
|
||||
{
|
||||
"status": "error",
|
||||
"error": "INVALID FILE",
|
||||
"error_data": "CANNOT DELETE DEFAULT",
|
||||
},
|
||||
)
|
||||
FileHelpers.del_file(
|
||||
os.path.join(
|
||||
self.controller.project_root,
|
||||
f"app/frontend/static/assets/images/auth/custom/{data['photo']}",
|
||||
)
|
||||
)
|
||||
current = self.controller.cached_login
|
||||
split = current.split("/")
|
||||
if len(split) == 1:
|
||||
current_photo = current
|
||||
else:
|
||||
current_photo = split[1]
|
||||
if current_photo == data["photo"]:
|
||||
self.controller.management.set_login_image("login_1.jpg")
|
||||
self.controller.cached_login = "login_1.jpg"
|
||||
return self.finish_json(200, {"status": "ok"})
|
||||
|
@ -297,33 +297,50 @@
|
||||
});
|
||||
});
|
||||
|
||||
$('.delete-photo').click(function () {
|
||||
var token = getCookie("_xsrf")
|
||||
$('.delete-photo').click(async function () {
|
||||
let photo = $('#photo').find(":selected").val();
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
headers: { 'X-XSRFToken': token },
|
||||
url: '/ajax/delete_photo?photo=' + encodeURIComponent(photo),
|
||||
success: function (data) {
|
||||
location.reload();
|
||||
},
|
||||
});
|
||||
var token = getCookie("_xsrf")
|
||||
let res = await fetch(`/api/v2/crafty/config/customize`, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'X-XSRFToken': token
|
||||
},
|
||||
body: JSON.stringify({"photo": photo}),
|
||||
});
|
||||
let responseData = await res.json();
|
||||
if (responseData.status === "ok") {
|
||||
window.location.reload();
|
||||
} else {
|
||||
|
||||
bootbox.alert({
|
||||
title: responseData.status,
|
||||
message: responseData.error
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
$('.select-photo').click(function () {
|
||||
var token = getCookie("_xsrf")
|
||||
$('.select-photo').click(async function () {
|
||||
let photo = $('#photo').find(":selected").val();
|
||||
let opacity = $('#modal_opacity').val();
|
||||
let enc_photo = encodeURIComponent(photo);
|
||||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
headers: { 'X-XSRFToken': token },
|
||||
url: '/ajax/select_photo?photo=' + enc_photo + '&opacity=' + opacity,
|
||||
success: function (data) {
|
||||
console.log(JSON.stringify({"photo": photo, "opacity": opacity}))
|
||||
var token = getCookie("_xsrf")
|
||||
let res = await fetch(`/api/v2/crafty/config/customize`, {
|
||||
method: 'PATCH',
|
||||
headers: {
|
||||
'X-XSRFToken': token
|
||||
},
|
||||
body: JSON.stringify({"photo": photo, "opacity": opacity}),
|
||||
});
|
||||
let responseData = await res.json();
|
||||
if (responseData.status === "ok") {
|
||||
window.location.reload();
|
||||
},
|
||||
});
|
||||
} else {
|
||||
|
||||
bootbox.alert({
|
||||
title: responseData.status,
|
||||
message: responseData.error
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
$(document).ready(function () {
|
||||
|
Loading…
Reference in New Issue
Block a user