mirror of
https://gitlab.com/crafty-controller/crafty-4.git
synced 2024-08-30 18:23:09 +00:00
Add more advanced role APIs
This commit is contained in:
parent
bf59e2de6c
commit
930c6936d9
@ -1,7 +1,8 @@
|
||||
import logging
|
||||
import typing as t
|
||||
|
||||
from app.classes.models.roles import HelperRoles
|
||||
from app.classes.models.server_permissions import PermissionsServers
|
||||
from app.classes.models.server_permissions import PermissionsServers, RoleServers
|
||||
from app.classes.shared.helpers import Helpers
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@ -66,6 +67,90 @@ class RolesController:
|
||||
def add_role(role_name):
|
||||
return HelperRoles.add_role(role_name)
|
||||
|
||||
class RoleServerJsonType(t.TypedDict):
|
||||
server_id: t.Union[str, int]
|
||||
permissions: str
|
||||
|
||||
@staticmethod
|
||||
def get_server_ids_and_perms_from_role(
|
||||
role_id: t.Union[str, int]
|
||||
) -> t.List[RoleServerJsonType]:
|
||||
# FIXME: somehow retrieve only the server ids, not the whole servers
|
||||
return [
|
||||
{
|
||||
"server_id": role_servers.server_id.server_id,
|
||||
"permissions": role_servers.permissions,
|
||||
}
|
||||
for role_servers in (
|
||||
RoleServers.select(
|
||||
RoleServers.server_id, RoleServers.permissions
|
||||
).where(RoleServers.role_id == role_id)
|
||||
)
|
||||
]
|
||||
|
||||
@staticmethod
|
||||
def add_role_advanced(
|
||||
name: str,
|
||||
servers: t.Iterable[RoleServerJsonType],
|
||||
) -> int:
|
||||
"""Add a role with a name and a list of servers
|
||||
|
||||
Args:
|
||||
name (str): The new role's name
|
||||
servers (t.List[RoleServerJsonType]): The new role's servers
|
||||
|
||||
Returns:
|
||||
int: The new role's ID
|
||||
"""
|
||||
role_id: t.Final[int] = HelperRoles.add_role(name)
|
||||
for server in servers:
|
||||
PermissionsServers.get_or_create(
|
||||
role_id, server["server_id"], server["permissions"]
|
||||
)
|
||||
return role_id
|
||||
|
||||
@staticmethod
|
||||
def update_role_advanced(
|
||||
role_id: t.Union[str, int],
|
||||
role_name: t.Optional[str],
|
||||
servers: t.Optional[t.Iterable[RoleServerJsonType]],
|
||||
) -> None:
|
||||
"""Update a role with a name and a list of servers
|
||||
|
||||
Args:
|
||||
role_id (t.Union[str, int]): The ID of the role to be modified
|
||||
role_name (t.Optional[str]): An optional new name for the role
|
||||
servers (t.Optional[t.Iterable[RoleServerJsonType]]): An optional list of servers for the role
|
||||
""" # pylint: disable=line-too-long
|
||||
logger.debug(f"updating role {role_id} with advanced options")
|
||||
|
||||
if servers is not None:
|
||||
base_data = RolesController.get_role_with_servers(role_id)
|
||||
|
||||
server_ids = {server["server_id"] for server in servers}
|
||||
server_permissions_map = {
|
||||
server["server_id"]: server["permissions"] for server in servers
|
||||
}
|
||||
|
||||
added_servers = server_ids.difference(set(base_data["servers"]))
|
||||
removed_servers = set(base_data["servers"]).difference(server_ids)
|
||||
logger.debug(
|
||||
f"role: {role_id} +server:{added_servers} -server{removed_servers}"
|
||||
)
|
||||
for server_id in added_servers:
|
||||
PermissionsServers.get_or_create(
|
||||
role_id, server_id, server_permissions_map[server_id]
|
||||
)
|
||||
if len(removed_servers) != 0:
|
||||
PermissionsServers.delete_roles_permissions(role_id, removed_servers)
|
||||
if role_name is not None:
|
||||
up_data = {
|
||||
"role_name": role_name,
|
||||
"last_update": Helpers.get_time_as_string(),
|
||||
}
|
||||
# TODO: do the last_update on the db side
|
||||
HelperRoles.update_role(role_id, up_data)
|
||||
|
||||
def remove_role(self, role_id):
|
||||
role_data = RolesController.get_role_with_servers(role_id)
|
||||
PermissionsServers.delete_roles_permissions(role_id, role_data["servers"])
|
||||
|
@ -76,7 +76,10 @@ class UsersController:
|
||||
},
|
||||
"roles": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"items": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
},
|
||||
},
|
||||
"hints": {"type": "boolean"},
|
||||
}
|
||||
|
@ -86,12 +86,10 @@ class HelperRoles:
|
||||
return Roles.update(up_data).where(Roles.role_id == role_id).execute()
|
||||
|
||||
def remove_role(self, role_id):
|
||||
with self.database.atomic():
|
||||
role = Roles.get(Roles.role_id == role_id)
|
||||
return role.delete_instance()
|
||||
return Roles.delete().where(Roles.role_id == role_id).execute()
|
||||
|
||||
@staticmethod
|
||||
def role_id_exists(role_id):
|
||||
def role_id_exists(role_id) -> bool:
|
||||
if not HelperRoles.get_role(role_id):
|
||||
return False
|
||||
return True
|
||||
|
@ -179,9 +179,9 @@ class PermissionsServers:
|
||||
RoleServers.save(role_server)
|
||||
|
||||
@staticmethod
|
||||
def delete_roles_permissions(role_id, removed_servers=None):
|
||||
if removed_servers is None:
|
||||
removed_servers = {}
|
||||
def delete_roles_permissions(
|
||||
role_id: t.Union[str, int], removed_servers: t.Sequence[t.Union[str, int]]
|
||||
):
|
||||
return (
|
||||
RoleServers.delete()
|
||||
.where(RoleServers.role_id == role_id)
|
||||
|
@ -190,6 +190,10 @@ class HelperServers:
|
||||
query = Servers.select()
|
||||
return DatabaseShortcuts.return_rows(query)
|
||||
|
||||
@staticmethod
|
||||
def get_all_server_ids() -> t.List[int]:
|
||||
return [server.server_id for server in Servers.select(Servers.server_id)]
|
||||
|
||||
@staticmethod
|
||||
def get_all_servers_stats():
|
||||
servers = HelperServers.get_all_defined_servers()
|
||||
|
@ -5,7 +5,7 @@ import shutil
|
||||
import time
|
||||
import logging
|
||||
import tempfile
|
||||
from typing import Union
|
||||
import typing as t
|
||||
from peewee import DoesNotExist
|
||||
|
||||
# TZLocal is set as a hidden import on win pipeline
|
||||
@ -276,7 +276,7 @@ class Controller:
|
||||
except:
|
||||
return {"percent": 0, "total_files": 0}
|
||||
|
||||
def get_server_obj(self, server_id: Union[str, int]) -> Union[bool, Server]:
|
||||
def get_server_obj(self, server_id: t.Union[str, int]) -> t.Union[bool, Server]:
|
||||
for server in self.servers_list:
|
||||
if str(server["server_id"]) == str(server_id):
|
||||
return server["server_obj"]
|
||||
@ -297,6 +297,10 @@ class Controller:
|
||||
servers = HelperServers.get_all_defined_servers()
|
||||
return servers
|
||||
|
||||
@staticmethod
|
||||
def get_all_server_ids() -> t.List[int]:
|
||||
return HelperServers.get_all_server_ids()
|
||||
|
||||
def list_running_servers(self):
|
||||
running_servers = []
|
||||
|
||||
|
@ -1,7 +1,23 @@
|
||||
from typing import Awaitable, Callable, Optional
|
||||
from app.classes.web.base_handler import BaseHandler
|
||||
|
||||
|
||||
class BaseApiHandler(BaseHandler):
|
||||
# {{{ Disable XSRF protection on API routes
|
||||
def check_xsrf_cookie(self) -> None:
|
||||
# Disable XSRF protection on API routes
|
||||
pass
|
||||
|
||||
# }}}
|
||||
|
||||
# {{{ 405 Method Not Allowed as JSON
|
||||
def _unimplemented_method(self, *_args: str, **_kwargs: str) -> None:
|
||||
self.finish_json(405, {"status": "error", "error": "METHOD_NOT_ALLOWED"})
|
||||
|
||||
head = _unimplemented_method # type: Callable[..., Optional[Awaitable[None]]]
|
||||
get = _unimplemented_method # type: Callable[..., Optional[Awaitable[None]]]
|
||||
post = _unimplemented_method # type: Callable[..., Optional[Awaitable[None]]]
|
||||
delete = _unimplemented_method # type: Callable[..., Optional[Awaitable[None]]]
|
||||
patch = _unimplemented_method # type: Callable[..., Optional[Awaitable[None]]]
|
||||
put = _unimplemented_method # type: Callable[..., Optional[Awaitable[None]]]
|
||||
options = _unimplemented_method # type: Callable[..., Optional[Awaitable[None]]]
|
||||
# }}}
|
||||
|
@ -2,7 +2,7 @@
|
||||
import time
|
||||
import datetime
|
||||
import os
|
||||
from typing import Dict, Any, Tuple
|
||||
import typing as t
|
||||
import json
|
||||
import logging
|
||||
import threading
|
||||
@ -27,7 +27,7 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class PanelHandler(BaseHandler):
|
||||
def get_user_roles(self) -> Dict[str, list]:
|
||||
def get_user_roles(self) -> t.Dict[str, list]:
|
||||
user_roles = {}
|
||||
for user_id in self.controller.users.get_all_user_ids():
|
||||
user_roles_list = self.controller.users.get_user_roles_names(user_id)
|
||||
@ -36,7 +36,7 @@ class PanelHandler(BaseHandler):
|
||||
user_roles[user_id] = user_roles_list
|
||||
return user_roles
|
||||
|
||||
def get_role_servers(self) -> set:
|
||||
def get_role_servers(self) -> t.Set[int]:
|
||||
servers = set()
|
||||
for server in self.controller.list_defined_servers():
|
||||
argument = int(
|
||||
@ -50,7 +50,7 @@ class PanelHandler(BaseHandler):
|
||||
servers.add(server["server_id"])
|
||||
return servers
|
||||
|
||||
def get_perms_quantity(self) -> Tuple[str, dict]:
|
||||
def get_perms_quantity(self) -> t.Tuple[str, dict]:
|
||||
permissions_mask: str = "000"
|
||||
server_quantity: dict = {}
|
||||
for (
|
||||
@ -258,7 +258,7 @@ class PanelHandler(BaseHandler):
|
||||
user_order.remove(server_id)
|
||||
defined_servers = page_servers
|
||||
|
||||
page_data: Dict[str, Any] = {
|
||||
page_data: t.Dict[str, t.Any] = {
|
||||
# todo: make this actually pull and compare version data
|
||||
"update_available": False,
|
||||
"serverTZ": get_localzone(),
|
||||
|
@ -1,6 +1,38 @@
|
||||
import typing as t
|
||||
from jsonschema import ValidationError, validate
|
||||
import orjson
|
||||
from playhouse.shortcuts import model_to_dict
|
||||
from app.classes.web.base_api_handler import BaseApiHandler
|
||||
|
||||
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"],
|
||||
},
|
||||
},
|
||||
},
|
||||
"required": ["name"],
|
||||
"additionalProperties": False,
|
||||
}
|
||||
|
||||
|
||||
class ApiRolesIndexHandler(BaseApiHandler):
|
||||
def get(self):
|
||||
@ -21,7 +53,6 @@ class ApiRolesIndexHandler(BaseApiHandler):
|
||||
if not superuser:
|
||||
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
|
||||
|
||||
# TODO: permissions
|
||||
self.finish_json(
|
||||
200,
|
||||
{
|
||||
@ -31,3 +62,73 @@ class ApiRolesIndexHandler(BaseApiHandler):
|
||||
else [model_to_dict(r) for r in self.controller.roles.get_all_roles()],
|
||||
},
|
||||
)
|
||||
|
||||
def post(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) # pylint: disable=no-member
|
||||
except orjson.decoder.JSONDecodeError as e: # pylint: disable=no-member
|
||||
return self.finish_json(
|
||||
400, {"status": "error", "error": "INVALID_JSON", "error_data": str(e)}
|
||||
)
|
||||
|
||||
try:
|
||||
validate(data, create_role_schema)
|
||||
except ValidationError as e:
|
||||
return self.finish_json(
|
||||
400,
|
||||
{
|
||||
"status": "error",
|
||||
"error": "INVALID_JSON_SCHEMA",
|
||||
"error_data": str(e),
|
||||
},
|
||||
)
|
||||
|
||||
role_name = data["name"]
|
||||
|
||||
# Get the servers
|
||||
servers_dict = {server["server_id"]: server for server in data["servers"]}
|
||||
server_ids = (
|
||||
{
|
||||
s
|
||||
for s in (
|
||||
{server["server_id"] for server in data["servers"]}
|
||||
& set(self.controller.get_all_server_ids())
|
||||
) # Only allow existing servers
|
||||
}
|
||||
if "servers" in data
|
||||
else set()
|
||||
)
|
||||
servers: t.List[dict] = [servers_dict[server_id] for server_id in server_ids]
|
||||
|
||||
if self.controller.roles.get_roleid_by_name(role_name) is not None:
|
||||
return self.finish_json(
|
||||
400, {"status": "error", "error": "ROLE_NAME_ALREADY_EXISTS"}
|
||||
)
|
||||
|
||||
role_id = self.controller.roles.add_role_advanced(role_name, servers)
|
||||
|
||||
self.controller.management.add_to_audit_log(
|
||||
user["user_id"],
|
||||
f"created role {role_name} (RID:{role_id})",
|
||||
server_id=0,
|
||||
source_ip=self.get_remote_ip(),
|
||||
)
|
||||
|
||||
self.finish_json(
|
||||
200,
|
||||
{"status": "ok", "data": {"role_id": role_id}},
|
||||
)
|
||||
|
@ -1,5 +1,39 @@
|
||||
from jsonschema import ValidationError, validate
|
||||
import orjson
|
||||
from app.classes.web.base_api_handler import BaseApiHandler
|
||||
|
||||
modify_role_schema = {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
},
|
||||
"servers": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"server_id": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
},
|
||||
"permissions": {
|
||||
"type": "string",
|
||||
"pattern": "^[01]{8}$", # 8 bits, see EnumPermissionsServer
|
||||
},
|
||||
},
|
||||
"required": ["server_id", "permissions"],
|
||||
},
|
||||
},
|
||||
},
|
||||
"anyOf": [
|
||||
{"required": ["name"]},
|
||||
{"required": ["servers"]},
|
||||
],
|
||||
"additionalProperties": False,
|
||||
}
|
||||
|
||||
|
||||
class ApiRolesRoleIndexHandler(BaseApiHandler):
|
||||
def get(self, role_id: str):
|
||||
@ -17,7 +51,71 @@ class ApiRolesRoleIndexHandler(BaseApiHandler):
|
||||
if not superuser:
|
||||
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
|
||||
|
||||
# TODO: permissions
|
||||
self.finish_json(
|
||||
200,
|
||||
{"status": "ok", "data": self.controller.roles.get_role(role_id)},
|
||||
)
|
||||
|
||||
def delete(self, role_id: str):
|
||||
auth_data = self.authenticate_user()
|
||||
if not auth_data:
|
||||
return
|
||||
(
|
||||
_,
|
||||
_,
|
||||
_,
|
||||
superuser,
|
||||
_,
|
||||
) = auth_data
|
||||
|
||||
if not superuser:
|
||||
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
|
||||
|
||||
self.controller.roles.remove_role(role_id)
|
||||
|
||||
self.finish_json(
|
||||
200,
|
||||
{"status": "ok", "data": role_id},
|
||||
)
|
||||
|
||||
def patch(self, role_id: str):
|
||||
auth_data = self.authenticate_user()
|
||||
if not auth_data:
|
||||
return
|
||||
(
|
||||
_,
|
||||
_,
|
||||
_,
|
||||
superuser,
|
||||
_,
|
||||
) = auth_data
|
||||
|
||||
if not superuser:
|
||||
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
|
||||
|
||||
try:
|
||||
data = orjson.loads(self.request.body) # pylint: disable=no-member
|
||||
except orjson.decoder.JSONDecodeError as e: # pylint: disable=no-member
|
||||
return self.finish_json(
|
||||
400, {"status": "error", "error": "INVALID_JSON", "error_data": str(e)}
|
||||
)
|
||||
|
||||
try:
|
||||
validate(data, modify_role_schema)
|
||||
except ValidationError as e:
|
||||
return self.finish_json(
|
||||
400,
|
||||
{
|
||||
"status": "error",
|
||||
"error": "INVALID_JSON_SCHEMA",
|
||||
"error_data": str(e),
|
||||
},
|
||||
)
|
||||
|
||||
self.controller.roles.update_role_advanced(
|
||||
role_id, data.get("role_name", None), data.get("servers", None)
|
||||
)
|
||||
|
||||
self.finish_json(
|
||||
200,
|
||||
{"status": "ok", "data": self.controller.roles.get_role(role_id)},
|
||||
|
@ -15,6 +15,9 @@ class ApiRolesRoleServersHandler(BaseApiHandler):
|
||||
_,
|
||||
) = auth_data
|
||||
|
||||
# GET /api/v2/roles/role/servers?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"})
|
||||
|
||||
@ -22,6 +25,8 @@ class ApiRolesRoleServersHandler(BaseApiHandler):
|
||||
200,
|
||||
{
|
||||
"status": "ok",
|
||||
"data": PermissionsServers.get_server_ids_from_role(role_id),
|
||||
"data": PermissionsServers.get_server_ids_from_role(role_id)
|
||||
if get_only_ids
|
||||
else self.controller.roles.get_server_ids_and_perms_from_role(role_id),
|
||||
},
|
||||
)
|
||||
|
@ -40,6 +40,7 @@ new_server_schema = {
|
||||
"title": "Name",
|
||||
"type": "string",
|
||||
"examples": ["My Server"],
|
||||
"minLength": 2,
|
||||
},
|
||||
"stop_command": {
|
||||
"title": "Stop command",
|
||||
@ -91,6 +92,7 @@ new_server_schema = {
|
||||
"type": "string",
|
||||
"default": "127.0.0.1",
|
||||
"examples": ["127.0.0.1"],
|
||||
"minLength": 1,
|
||||
},
|
||||
"port": {
|
||||
"title": "Port",
|
||||
@ -111,6 +113,7 @@ new_server_schema = {
|
||||
"type": "string",
|
||||
"default": "127.0.0.1",
|
||||
"examples": ["127.0.0.1"],
|
||||
"minLength": 1,
|
||||
},
|
||||
"port": {
|
||||
"title": "Port",
|
||||
@ -155,11 +158,13 @@ new_server_schema = {
|
||||
"title": "Server JAR Type",
|
||||
"type": "string",
|
||||
"examples": ["Paper"],
|
||||
"minLength": 1,
|
||||
},
|
||||
"version": {
|
||||
"title": "Server JAR Version",
|
||||
"type": "string",
|
||||
"examples": ["1.18.2"],
|
||||
"minLength": 1,
|
||||
},
|
||||
"mem_min": {
|
||||
"title": "Minimum JVM memory (in GiBs)",
|
||||
@ -206,12 +211,14 @@ new_server_schema = {
|
||||
"description": "Absolute path to the old server",
|
||||
"type": "string",
|
||||
"examples": ["/var/opt/server"],
|
||||
"minLength": 1,
|
||||
},
|
||||
"jarfile": {
|
||||
"title": "JAR file",
|
||||
"description": "The JAR file relative to the previous path",
|
||||
"type": "string",
|
||||
"examples": ["paper.jar", "jars/vanilla-1.12.jar"],
|
||||
"minLength": 1,
|
||||
},
|
||||
"mem_min": {
|
||||
"title": "Minimum JVM memory (in GiBs)",
|
||||
@ -259,18 +266,21 @@ new_server_schema = {
|
||||
"description": "Absolute path to the ZIP archive",
|
||||
"type": "string",
|
||||
"examples": ["/var/opt/server.zip"],
|
||||
"minLength": 1,
|
||||
},
|
||||
"zip_root": {
|
||||
"title": "Server root directory",
|
||||
"description": "The server root in the ZIP archive",
|
||||
"type": "string",
|
||||
"examples": ["/", "/paper-server/", "server-1"],
|
||||
"minLength": 1,
|
||||
},
|
||||
"jarfile": {
|
||||
"title": "JAR file",
|
||||
"description": "The JAR relative to the configured root",
|
||||
"type": "string",
|
||||
"examples": ["paper.jar", "jars/vanilla-1.12.jar"],
|
||||
"minLength": 1,
|
||||
},
|
||||
"mem_min": {
|
||||
"title": "Minimum JVM memory (in GiBs)",
|
||||
@ -356,12 +366,14 @@ new_server_schema = {
|
||||
"description": "Absolute path to the old server",
|
||||
"type": "string",
|
||||
"examples": ["/var/opt/server"],
|
||||
"minLength": 1,
|
||||
},
|
||||
"command": {
|
||||
"title": "Command",
|
||||
"type": "string",
|
||||
"default": "echo foo bar baz",
|
||||
"examples": ["LD_LIBRARY_PATH=. ./bedrock_server"],
|
||||
"minLength": 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -375,18 +387,21 @@ new_server_schema = {
|
||||
"description": "Absolute path to the ZIP archive",
|
||||
"type": "string",
|
||||
"examples": ["/var/opt/server.zip"],
|
||||
"minLength": 1,
|
||||
},
|
||||
"zip_root": {
|
||||
"title": "Server root directory",
|
||||
"description": "The server root in the ZIP archive",
|
||||
"type": "string",
|
||||
"examples": ["/", "/paper-server/", "server-1"],
|
||||
"minLength": 1,
|
||||
},
|
||||
"command": {
|
||||
"title": "Command",
|
||||
"type": "string",
|
||||
"default": "echo foo bar baz",
|
||||
"examples": ["LD_LIBRARY_PATH=. ./bedrock_server"],
|
||||
"minLength": 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -474,6 +489,7 @@ new_server_schema = {
|
||||
"type": "string",
|
||||
"default": "echo foo bar baz",
|
||||
"examples": ["caddy start"],
|
||||
"minLength": 1,
|
||||
}
|
||||
},
|
||||
},
|
||||
@ -487,12 +503,14 @@ new_server_schema = {
|
||||
"description": "Absolute path to the old server",
|
||||
"type": "string",
|
||||
"examples": ["/var/opt/server"],
|
||||
"minLength": 1,
|
||||
},
|
||||
"command": {
|
||||
"title": "Command",
|
||||
"type": "string",
|
||||
"default": "echo foo bar baz",
|
||||
"examples": ["caddy start"],
|
||||
"minLength": 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -506,18 +524,21 @@ new_server_schema = {
|
||||
"description": "Absolute path to the ZIP archive",
|
||||
"type": "string",
|
||||
"examples": ["/var/opt/server.zip"],
|
||||
"minLength": 1,
|
||||
},
|
||||
"zip_root": {
|
||||
"title": "Server root directory",
|
||||
"description": "The server root in the ZIP archive",
|
||||
"type": "string",
|
||||
"examples": ["/", "/paper-server/", "server-1"],
|
||||
"minLength": 1,
|
||||
},
|
||||
"command": {
|
||||
"title": "Command",
|
||||
"type": "string",
|
||||
"default": "echo foo bar baz",
|
||||
"examples": ["caddy start"],
|
||||
"minLength": 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -11,21 +11,21 @@ logger = logging.getLogger(__name__)
|
||||
server_patch_schema = {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"server_name": {"type": "string"},
|
||||
"path": {"type": "string"},
|
||||
"server_name": {"type": "string", "minLength": 1},
|
||||
"path": {"type": "string", "minLength": 1},
|
||||
"backup_path": {"type": "string"},
|
||||
"executable": {"type": "string"},
|
||||
"log_path": {"type": "string"},
|
||||
"execution_command": {"type": "string"},
|
||||
"log_path": {"type": "string", "minLength": 1},
|
||||
"execution_command": {"type": "string", "minLength": 1},
|
||||
"auto_start": {"type": "boolean"},
|
||||
"auto_start_delay": {"type": "integer"},
|
||||
"crash_detection": {"type": "boolean"},
|
||||
"stop_command": {"type": "string"},
|
||||
"executable_update_url": {"type": "string"},
|
||||
"server_ip": {"type": "string"},
|
||||
"executable_update_url": {"type": "string", "minLength": 1},
|
||||
"server_ip": {"type": "string", "minLength": 1},
|
||||
"server_port": {"type": "integer"},
|
||||
"logs_delete_after": {"type": "integer"},
|
||||
"type": {"type": "string"},
|
||||
"type": {"type": "string", "minLength": 1},
|
||||
},
|
||||
"anyOf": [
|
||||
# Require at least one property
|
||||
|
Loading…
Reference in New Issue
Block a user