mirror of
https://gitlab.com/crafty-controller/crafty-4.git
synced 2024-08-30 18:23:09 +00:00
Backups are editable!
This commit is contained in:
parent
b061ebf5e5
commit
3cf4ebf073
@ -357,7 +357,7 @@ class HelpersManagement:
|
|||||||
data[str(backup.backup_id)] = {
|
data[str(backup.backup_id)] = {
|
||||||
"backup_id": backup.backup_id,
|
"backup_id": backup.backup_id,
|
||||||
"backup_name": backup.backup_name,
|
"backup_name": backup.backup_name,
|
||||||
"backup_path": backup.backup_location,
|
"backup_location": backup.backup_location,
|
||||||
"excluded_dirs": backup.excluded_dirs,
|
"excluded_dirs": backup.excluded_dirs,
|
||||||
"max_backups": backup.max_backups,
|
"max_backups": backup.max_backups,
|
||||||
"server_id": backup.server_id_id,
|
"server_id": backup.server_id_id,
|
||||||
|
@ -235,6 +235,7 @@ class FileHelpers:
|
|||||||
path_to_zip,
|
path_to_zip,
|
||||||
excluded_dirs,
|
excluded_dirs,
|
||||||
server_id,
|
server_id,
|
||||||
|
backup_id,
|
||||||
comment="",
|
comment="",
|
||||||
compressed=None,
|
compressed=None,
|
||||||
):
|
):
|
||||||
@ -306,6 +307,7 @@ class FileHelpers:
|
|||||||
results = {
|
results = {
|
||||||
"percent": percent,
|
"percent": percent,
|
||||||
"total_files": self.helper.human_readable_file_size(dir_bytes),
|
"total_files": self.helper.human_readable_file_size(dir_bytes),
|
||||||
|
"backup_id": backup_id,
|
||||||
}
|
}
|
||||||
# send status results to page.
|
# send status results to page.
|
||||||
WebSocketManager().broadcast_page_params(
|
WebSocketManager().broadcast_page_params(
|
||||||
|
@ -1197,6 +1197,7 @@ class ServerInstance:
|
|||||||
server_dir,
|
server_dir,
|
||||||
excluded_dirs,
|
excluded_dirs,
|
||||||
self.server_id,
|
self.server_id,
|
||||||
|
backup_id,
|
||||||
conf["backup_name"],
|
conf["backup_name"],
|
||||||
conf["compress"],
|
conf["compress"],
|
||||||
)
|
)
|
||||||
@ -1205,7 +1206,7 @@ class ServerInstance:
|
|||||||
len(self.list_backups(backup_location)) > conf["max_backups"]
|
len(self.list_backups(backup_location)) > conf["max_backups"]
|
||||||
and conf["max_backups"] > 0
|
and conf["max_backups"] > 0
|
||||||
):
|
):
|
||||||
backup_list = self.list_backups()
|
backup_list = self.list_backups(conf["backup_location"])
|
||||||
oldfile = backup_list[0]
|
oldfile = backup_list[0]
|
||||||
oldfile_path = f"{backup_location}/{oldfile['path']}"
|
oldfile_path = f"{backup_location}/{oldfile['path']}"
|
||||||
logger.info(f"Removing old backup '{oldfile['path']}'")
|
logger.info(f"Removing old backup '{oldfile['path']}'")
|
||||||
@ -1213,7 +1214,12 @@ class ServerInstance:
|
|||||||
|
|
||||||
self.is_backingup = False
|
self.is_backingup = False
|
||||||
logger.info(f"Backup of server: {self.name} completed")
|
logger.info(f"Backup of server: {self.name} completed")
|
||||||
results = {"percent": 100, "total_files": 0, "current_file": 0}
|
results = {
|
||||||
|
"percent": 100,
|
||||||
|
"total_files": 0,
|
||||||
|
"current_file": 0,
|
||||||
|
"backup_id": backup_id,
|
||||||
|
}
|
||||||
if len(WebSocketManager().clients) > 0:
|
if len(WebSocketManager().clients) > 0:
|
||||||
WebSocketManager().broadcast_page_params(
|
WebSocketManager().broadcast_page_params(
|
||||||
"/panel/server_detail",
|
"/panel/server_detail",
|
||||||
@ -1251,7 +1257,12 @@ class ServerInstance:
|
|||||||
logger.exception(
|
logger.exception(
|
||||||
f"Failed to create backup of server {self.name} (ID {self.server_id})"
|
f"Failed to create backup of server {self.name} (ID {self.server_id})"
|
||||||
)
|
)
|
||||||
results = {"percent": 100, "total_files": 0, "current_file": 0}
|
results = {
|
||||||
|
"percent": 100,
|
||||||
|
"total_files": 0,
|
||||||
|
"current_file": 0,
|
||||||
|
"backup_id": backup_id,
|
||||||
|
}
|
||||||
if len(WebSocketManager().clients) > 0:
|
if len(WebSocketManager().clients) > 0:
|
||||||
WebSocketManager().broadcast_page_params(
|
WebSocketManager().broadcast_page_params(
|
||||||
"/panel/server_detail",
|
"/panel/server_detail",
|
||||||
@ -1267,17 +1278,6 @@ class ServerInstance:
|
|||||||
self.run_threaded_server(HelperUsers.get_user_id_by_name("system"))
|
self.run_threaded_server(HelperUsers.get_user_id_by_name("system"))
|
||||||
self.last_backup_failed = True
|
self.last_backup_failed = True
|
||||||
|
|
||||||
def backup_status(self, source_path, dest_path):
|
|
||||||
results = Helpers.calc_percent(source_path, dest_path)
|
|
||||||
self.backup_stats = results
|
|
||||||
if len(WebSocketManager().clients) > 0:
|
|
||||||
WebSocketManager().broadcast_page_params(
|
|
||||||
"/panel/server_detail",
|
|
||||||
{"id": str(self.server_id)},
|
|
||||||
"backup_status",
|
|
||||||
results,
|
|
||||||
)
|
|
||||||
|
|
||||||
def last_backup_status(self):
|
def last_backup_status(self):
|
||||||
return self.last_backup_failed
|
return self.last_backup_failed
|
||||||
|
|
||||||
|
@ -1286,7 +1286,9 @@ class PanelHandler(BaseHandler):
|
|||||||
)
|
)
|
||||||
self.controller.servers.refresh_server_settings(server_id)
|
self.controller.servers.refresh_server_settings(server_id)
|
||||||
try:
|
try:
|
||||||
page_data["backup_list"] = server.list_backups()
|
page_data["backup_list"] = server.list_backups(
|
||||||
|
page_data["backup_config"]["backup_location"]
|
||||||
|
)
|
||||||
except:
|
except:
|
||||||
page_data["backup_list"] = []
|
page_data["backup_list"] = []
|
||||||
page_data["backup_path"] = Helpers.wtol_path(
|
page_data["backup_path"] = Helpers.wtol_path(
|
||||||
|
@ -218,7 +218,7 @@ def api_handlers(handler_args):
|
|||||||
handler_args,
|
handler_args,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
r"/api/v2/servers/([a-z0-9-]+)/backups/backup/?",
|
r"/api/v2/servers/([a-z0-9-]+)/backups/backup/([a-z0-9-]+)/?",
|
||||||
ApiServersServerBackupsBackupIndexHandler,
|
ApiServersServerBackupsBackupIndexHandler,
|
||||||
handler_args,
|
handler_args,
|
||||||
),
|
),
|
||||||
|
@ -11,7 +11,7 @@ from app.classes.shared.helpers import Helpers
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
backup_schema = {
|
BACKUP_SCHEMA = {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"filename": {"type": "string", "minLength": 5},
|
"filename": {"type": "string", "minLength": 5},
|
||||||
@ -19,11 +19,40 @@ backup_schema = {
|
|||||||
"additionalProperties": False,
|
"additionalProperties": False,
|
||||||
"minProperties": 1,
|
"minProperties": 1,
|
||||||
}
|
}
|
||||||
|
BACKUP_PATCH_SCHEMA = {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"backup_location": {"type": "string", "minLength": 1},
|
||||||
|
"max_backups": {"type": "integer"},
|
||||||
|
"compress": {"type": "boolean"},
|
||||||
|
"shutdown": {"type": "boolean"},
|
||||||
|
"before": {"type": "string"},
|
||||||
|
"after": {"type": "string"},
|
||||||
|
"exclusions": {"type": "array"},
|
||||||
|
},
|
||||||
|
"additionalProperties": False,
|
||||||
|
"minProperties": 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
BASIC_BACKUP_PATCH_SCHEMA = {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"max_backups": {"type": "integer"},
|
||||||
|
"compress": {"type": "boolean"},
|
||||||
|
"shutdown": {"type": "boolean"},
|
||||||
|
"before": {"type": "string"},
|
||||||
|
"after": {"type": "string"},
|
||||||
|
"exclusions": {"type": "array"},
|
||||||
|
},
|
||||||
|
"additionalProperties": False,
|
||||||
|
"minProperties": 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class ApiServersServerBackupsBackupIndexHandler(BaseApiHandler):
|
class ApiServersServerBackupsBackupIndexHandler(BaseApiHandler):
|
||||||
def get(self, server_id: str):
|
def get(self, server_id: str, backup_id: str):
|
||||||
auth_data = self.authenticate_user()
|
auth_data = self.authenticate_user()
|
||||||
|
backup_conf = self.controller.management.get_backup_config(backup_id)
|
||||||
if not auth_data:
|
if not auth_data:
|
||||||
return
|
return
|
||||||
mask = self.controller.server_perms.get_lowest_api_perm_mask(
|
mask = self.controller.server_perms.get_lowest_api_perm_mask(
|
||||||
@ -32,15 +61,40 @@ class ApiServersServerBackupsBackupIndexHandler(BaseApiHandler):
|
|||||||
),
|
),
|
||||||
auth_data[5],
|
auth_data[5],
|
||||||
)
|
)
|
||||||
|
if backup_conf["server_id"]["server_id"] != server_id:
|
||||||
|
return self.finish_json(
|
||||||
|
400,
|
||||||
|
{
|
||||||
|
"status": "error",
|
||||||
|
"error": "ID_MISMATCH",
|
||||||
|
"error_data": "Server ID backup server ID different",
|
||||||
|
},
|
||||||
|
)
|
||||||
server_permissions = self.controller.server_perms.get_permissions(mask)
|
server_permissions = self.controller.server_perms.get_permissions(mask)
|
||||||
if EnumPermissionsServer.BACKUP not in server_permissions:
|
if EnumPermissionsServer.BACKUP not in server_permissions:
|
||||||
# if the user doesn't have Schedule permission, return an error
|
# if the user doesn't have Schedule permission, return an error
|
||||||
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
|
return self.finish_json(
|
||||||
self.finish_json(200, self.controller.management.get_backup_config(server_id))
|
400,
|
||||||
|
{
|
||||||
|
"status": "error",
|
||||||
|
"error": "NOT_AUTHORIZED",
|
||||||
|
"error_data": "Authorization Error",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
self.finish_json(200, backup_conf)
|
||||||
|
|
||||||
def delete(self, server_id: str):
|
def delete(self, server_id: str, backup_id: str):
|
||||||
auth_data = self.authenticate_user()
|
auth_data = self.authenticate_user()
|
||||||
backup_conf = self.controller.management.get_backup_config(server_id)
|
backup_conf = self.controller.management.get_backup_config(backup_id)
|
||||||
|
if backup_conf["server_id"]["server_id"] != server_id:
|
||||||
|
return self.finish_json(
|
||||||
|
400,
|
||||||
|
{
|
||||||
|
"status": "error",
|
||||||
|
"error": "ID_MISMATCH",
|
||||||
|
"error_data": "Server ID backup server ID different",
|
||||||
|
},
|
||||||
|
)
|
||||||
if not auth_data:
|
if not auth_data:
|
||||||
return
|
return
|
||||||
mask = self.controller.server_perms.get_lowest_api_perm_mask(
|
mask = self.controller.server_perms.get_lowest_api_perm_mask(
|
||||||
@ -52,7 +106,14 @@ class ApiServersServerBackupsBackupIndexHandler(BaseApiHandler):
|
|||||||
server_permissions = self.controller.server_perms.get_permissions(mask)
|
server_permissions = self.controller.server_perms.get_permissions(mask)
|
||||||
if EnumPermissionsServer.BACKUP not in server_permissions:
|
if EnumPermissionsServer.BACKUP not in server_permissions:
|
||||||
# if the user doesn't have Schedule permission, return an error
|
# if the user doesn't have Schedule permission, return an error
|
||||||
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
|
return self.finish_json(
|
||||||
|
400,
|
||||||
|
{
|
||||||
|
"status": "error",
|
||||||
|
"error": "NOT_AUTHORIZED",
|
||||||
|
"error_data": "Authorization Error",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
data = json.loads(self.request.body)
|
data = json.loads(self.request.body)
|
||||||
@ -61,7 +122,7 @@ class ApiServersServerBackupsBackupIndexHandler(BaseApiHandler):
|
|||||||
400, {"status": "error", "error": "INVALID_JSON", "error_data": str(e)}
|
400, {"status": "error", "error": "INVALID_JSON", "error_data": str(e)}
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
validate(data, backup_schema)
|
validate(data, BACKUP_SCHEMA)
|
||||||
except ValidationError as e:
|
except ValidationError as e:
|
||||||
return self.finish_json(
|
return self.finish_json(
|
||||||
400,
|
400,
|
||||||
@ -74,7 +135,7 @@ class ApiServersServerBackupsBackupIndexHandler(BaseApiHandler):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
FileHelpers.del_file(
|
FileHelpers.del_file(
|
||||||
os.path.join(backup_conf["backup_path"], data["filename"])
|
os.path.join(backup_conf["backup_location"], data["filename"])
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return self.finish_json(
|
return self.finish_json(
|
||||||
@ -89,7 +150,7 @@ class ApiServersServerBackupsBackupIndexHandler(BaseApiHandler):
|
|||||||
|
|
||||||
return self.finish_json(200, {"status": "ok"})
|
return self.finish_json(200, {"status": "ok"})
|
||||||
|
|
||||||
def post(self, server_id: str):
|
def post(self, server_id: str, backup_id: str):
|
||||||
auth_data = self.authenticate_user()
|
auth_data = self.authenticate_user()
|
||||||
if not auth_data:
|
if not auth_data:
|
||||||
return
|
return
|
||||||
@ -102,7 +163,24 @@ class ApiServersServerBackupsBackupIndexHandler(BaseApiHandler):
|
|||||||
server_permissions = self.controller.server_perms.get_permissions(mask)
|
server_permissions = self.controller.server_perms.get_permissions(mask)
|
||||||
if EnumPermissionsServer.BACKUP not in server_permissions:
|
if EnumPermissionsServer.BACKUP not in server_permissions:
|
||||||
# if the user doesn't have Schedule permission, return an error
|
# if the user doesn't have Schedule permission, return an error
|
||||||
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
|
return self.finish_json(
|
||||||
|
400,
|
||||||
|
{
|
||||||
|
"status": "error",
|
||||||
|
"error": "NOT_AUTHORIZED",
|
||||||
|
"error_data": "Authorization Error",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
backup_config = self.controller.management.get_backup_config(backup_id)
|
||||||
|
if backup_config["server_id"] != server_id:
|
||||||
|
return self.finish_json(
|
||||||
|
400,
|
||||||
|
{
|
||||||
|
"status": "error",
|
||||||
|
"error": "ID_MISMATCH",
|
||||||
|
"error_data": "Server ID backup server ID different",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
data = json.loads(self.request.body)
|
data = json.loads(self.request.body)
|
||||||
@ -111,7 +189,7 @@ class ApiServersServerBackupsBackupIndexHandler(BaseApiHandler):
|
|||||||
400, {"status": "error", "error": "INVALID_JSON", "error_data": str(e)}
|
400, {"status": "error", "error": "INVALID_JSON", "error_data": str(e)}
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
validate(data, backup_schema)
|
validate(data, BACKUP_SCHEMA)
|
||||||
except ValidationError as e:
|
except ValidationError as e:
|
||||||
return self.finish_json(
|
return self.finish_json(
|
||||||
400,
|
400,
|
||||||
@ -184,7 +262,6 @@ class ApiServersServerBackupsBackupIndexHandler(BaseApiHandler):
|
|||||||
self.controller.servers.update_server(new_server_obj)
|
self.controller.servers.update_server(new_server_obj)
|
||||||
|
|
||||||
# preserve backup config
|
# preserve backup config
|
||||||
backup_config = self.controller.management.get_backup_config(server_id)
|
|
||||||
excluded_dirs = []
|
excluded_dirs = []
|
||||||
server_obj = self.controller.servers.get_server_obj(server_id)
|
server_obj = self.controller.servers.get_server_obj(server_id)
|
||||||
loop_backup_path = self.helper.wtol_path(server_obj.path)
|
loop_backup_path = self.helper.wtol_path(server_obj.path)
|
||||||
@ -221,3 +298,70 @@ class ApiServersServerBackupsBackupIndexHandler(BaseApiHandler):
|
|||||||
)
|
)
|
||||||
|
|
||||||
return self.finish_json(200, {"status": "ok"})
|
return self.finish_json(200, {"status": "ok"})
|
||||||
|
|
||||||
|
def patch(self, server_id: str, backup_id: str):
|
||||||
|
auth_data = self.authenticate_user()
|
||||||
|
if not auth_data:
|
||||||
|
return
|
||||||
|
|
||||||
|
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:
|
||||||
|
if auth_data[4]["superuser"]:
|
||||||
|
validate(data, BACKUP_PATCH_SCHEMA)
|
||||||
|
else:
|
||||||
|
validate(data, BASIC_BACKUP_PATCH_SCHEMA)
|
||||||
|
except ValidationError as e:
|
||||||
|
return self.finish_json(
|
||||||
|
400,
|
||||||
|
{
|
||||||
|
"status": "error",
|
||||||
|
"error": "INVALID_JSON_SCHEMA",
|
||||||
|
"error_data": str(e),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
backup_conf = self.controller.management.get_backup_config(backup_id)
|
||||||
|
if server_id not in [str(x["server_id"]) for x in auth_data[0]]:
|
||||||
|
# if the user doesn't have access to the server, return an error
|
||||||
|
return self.finish_json(
|
||||||
|
400,
|
||||||
|
{
|
||||||
|
"status": "error",
|
||||||
|
"error": "NOT_AUTHORIZED",
|
||||||
|
"error_data": "Authorization Error",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if backup_conf["server_id"]["server_id"] != server_id:
|
||||||
|
return self.finish_json(
|
||||||
|
400,
|
||||||
|
{
|
||||||
|
"status": "error",
|
||||||
|
"error": "ID_MISMATCH",
|
||||||
|
"error_data": "Server ID backup server ID different",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
mask = self.controller.server_perms.get_lowest_api_perm_mask(
|
||||||
|
self.controller.server_perms.get_user_permissions_mask(
|
||||||
|
auth_data[4]["user_id"], server_id
|
||||||
|
),
|
||||||
|
auth_data[5],
|
||||||
|
)
|
||||||
|
server_permissions = self.controller.server_perms.get_permissions(mask)
|
||||||
|
if EnumPermissionsServer.BACKUP not in server_permissions:
|
||||||
|
# if the user doesn't have Schedule permission, return an error
|
||||||
|
return self.finish_json(
|
||||||
|
400,
|
||||||
|
{
|
||||||
|
"status": "error",
|
||||||
|
"error": "NOT_AUTHORIZED",
|
||||||
|
"error_data": "Authorization Error",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
self.controller.management.update_backup_config(backup_id, data)
|
||||||
|
return self.finish_json(200, {"status": "ok"})
|
||||||
|
@ -10,12 +10,12 @@ logger = logging.getLogger(__name__)
|
|||||||
backup_patch_schema = {
|
backup_patch_schema = {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"backup_path": {"type": "string", "minLength": 1},
|
"backup_location": {"type": "string", "minLength": 1},
|
||||||
"max_backups": {"type": "integer"},
|
"max_backups": {"type": "integer"},
|
||||||
"compress": {"type": "boolean"},
|
"compress": {"type": "boolean"},
|
||||||
"shutdown": {"type": "boolean"},
|
"shutdown": {"type": "boolean"},
|
||||||
"backup_before": {"type": "string"},
|
"before": {"type": "string"},
|
||||||
"backup_after": {"type": "string"},
|
"after": {"type": "string"},
|
||||||
"exclusions": {"type": "array"},
|
"exclusions": {"type": "array"},
|
||||||
},
|
},
|
||||||
"additionalProperties": False,
|
"additionalProperties": False,
|
||||||
@ -28,8 +28,8 @@ basic_backup_patch_schema = {
|
|||||||
"max_backups": {"type": "integer"},
|
"max_backups": {"type": "integer"},
|
||||||
"compress": {"type": "boolean"},
|
"compress": {"type": "boolean"},
|
||||||
"shutdown": {"type": "boolean"},
|
"shutdown": {"type": "boolean"},
|
||||||
"backup_before": {"type": "string"},
|
"before": {"type": "string"},
|
||||||
"backup_after": {"type": "string"},
|
"after": {"type": "string"},
|
||||||
"exclusions": {"type": "array"},
|
"exclusions": {"type": "array"},
|
||||||
},
|
},
|
||||||
"additionalProperties": False,
|
"additionalProperties": False,
|
||||||
@ -52,9 +52,11 @@ class ApiServersServerBackupsIndexHandler(BaseApiHandler):
|
|||||||
if EnumPermissionsServer.BACKUP not in server_permissions:
|
if EnumPermissionsServer.BACKUP not in server_permissions:
|
||||||
# if the user doesn't have Schedule permission, return an error
|
# if the user doesn't have Schedule permission, return an error
|
||||||
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
|
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
|
||||||
self.finish_json(200, self.controller.management.get_backup_config(server_id))
|
self.finish_json(
|
||||||
|
200, self.controller.management.get_backups_by_server(server_id)
|
||||||
|
)
|
||||||
|
|
||||||
def patch(self, backup_id: str):
|
def post(self, server_id: str):
|
||||||
auth_data = self.authenticate_user()
|
auth_data = self.authenticate_user()
|
||||||
if not auth_data:
|
if not auth_data:
|
||||||
return
|
return
|
||||||
@ -80,8 +82,6 @@ class ApiServersServerBackupsIndexHandler(BaseApiHandler):
|
|||||||
"error_data": str(e),
|
"error_data": str(e),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
backup_conf = self.controller.management.get_backup_config(backup_id)
|
|
||||||
server_id = backup_conf["server_id"]
|
|
||||||
if server_id not in [str(x["server_id"]) for x in auth_data[0]]:
|
if server_id not in [str(x["server_id"]) for x in auth_data[0]]:
|
||||||
# if the user doesn't have access to the server, return an error
|
# if the user doesn't have access to the server, return an error
|
||||||
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
|
return self.finish_json(400, {"status": "error", "error": "NOT_AUTHORIZED"})
|
||||||
|
@ -67,7 +67,7 @@
|
|||||||
<label for="server_name">{{ translate('serverBackups', 'storageLocation', data['lang']) }} <small
|
<label for="server_name">{{ translate('serverBackups', 'storageLocation', data['lang']) }} <small
|
||||||
class="text-muted ml-1"> - {{ translate('serverBackups', 'storageLocationDesc', data['lang'])
|
class="text-muted ml-1"> - {{ translate('serverBackups', 'storageLocationDesc', data['lang'])
|
||||||
}}</small> </label>
|
}}</small> </label>
|
||||||
<input type="text" class="form-control" name="backup_path" id="backup_path"
|
<input type="text" class="form-control" name="backup_location" id="backup_location"
|
||||||
value="{{ data['backup_config']['backup_location'] }}"
|
value="{{ data['backup_config']['backup_location'] }}"
|
||||||
placeholder="{{ translate('serverBackups', 'storageLocation', data['lang']) }}">
|
placeholder="{{ translate('serverBackups', 'storageLocation', data['lang']) }}">
|
||||||
{% end %}
|
{% end %}
|
||||||
@ -107,14 +107,14 @@
|
|||||||
<input type="checkbox" class="form-check-input" id="before-check" name="before-check" checked>{{
|
<input type="checkbox" class="form-check-input" id="before-check" name="before-check" checked>{{
|
||||||
translate('serverBackups', 'before', data['lang']) }}
|
translate('serverBackups', 'before', data['lang']) }}
|
||||||
<br>
|
<br>
|
||||||
<input type="text" class="form-control" name="backup_before" id="backup_before"
|
<input type="text" class="form-control" name="before" id="backup_before"
|
||||||
value="{{ data['backup_config']['before'] }}" placeholder="We enter the / for you"
|
value="{{ data['backup_config']['before'] }}" placeholder="We enter the / for you"
|
||||||
style="display: inline-block;">
|
style="display: inline-block;">
|
||||||
{% else %}
|
{% else %}
|
||||||
<input type="checkbox" class="form-check-input" id="before-check" name="before-check">{{
|
<input type="checkbox" class="form-check-input" id="before-check" name="before-check">{{
|
||||||
translate('serverBackups', 'before', data['lang']) }}
|
translate('serverBackups', 'before', data['lang']) }}
|
||||||
<br>
|
<br>
|
||||||
<input type="text" class="form-control" name="backup_before" id="backup_before" value=""
|
<input type="text" class="form-control" name="before" id="backup_before" value=""
|
||||||
placeholder="We enter the / for you." style="display: none;">
|
placeholder="We enter the / for you." style="display: none;">
|
||||||
{% end %}
|
{% end %}
|
||||||
</div>
|
</div>
|
||||||
@ -124,14 +124,14 @@
|
|||||||
<input type="checkbox" class="form-check-input" id="after-check" name="after-check" checked>{{
|
<input type="checkbox" class="form-check-input" id="after-check" name="after-check" checked>{{
|
||||||
translate('serverBackups', 'after', data['lang']) }}
|
translate('serverBackups', 'after', data['lang']) }}
|
||||||
<br>
|
<br>
|
||||||
<input type="text" class="form-control" name="backup_after" id="backup_after"
|
<input type="text" class="form-control" name="after" id="backup_after"
|
||||||
value="{{ data['backup_config']['after'] }}" placeholder="We enter the / for you"
|
value="{{ data['backup_config']['after'] }}" placeholder="We enter the / for you"
|
||||||
style="display: inline-block;">
|
style="display: inline-block;">
|
||||||
{% else %}
|
{% else %}
|
||||||
<input type="checkbox" class="form-check-input" id="after-check" name="after-check">{{
|
<input type="checkbox" class="form-check-input" id="after-check" name="after-check">{{
|
||||||
translate('serverBackups', 'after', data['lang']) }}
|
translate('serverBackups', 'after', data['lang']) }}
|
||||||
<br>
|
<br>
|
||||||
<input type="text" class="form-control" name="backup_after" id="backup_after" value=""
|
<input type="text" class="form-control" name="after" id="backup_after" value=""
|
||||||
placeholder="We enter the / for you." style="display: none;">
|
placeholder="We enter the / for you." style="display: none;">
|
||||||
{% end %}
|
{% end %}
|
||||||
</div>
|
</div>
|
||||||
@ -206,7 +206,8 @@
|
|||||||
</a>
|
</a>
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
<button data-file="{{ backup['path'] }}" data-backup_path="{{ data['backup_location'] }}"
|
<button data-file="{{ backup['path'] }}"
|
||||||
|
data-backup_location="{{ data['backup_config']['backup_location'] }}"
|
||||||
class="btn btn-danger del_button">
|
class="btn btn-danger del_button">
|
||||||
<i class="fas fa-trash" aria-hidden="true"></i>
|
<i class="fas fa-trash" aria-hidden="true"></i>
|
||||||
{{ translate('serverBackups', 'delete', data['lang']) }}
|
{{ translate('serverBackups', 'delete', data['lang']) }}
|
||||||
@ -300,6 +301,7 @@
|
|||||||
<script>
|
<script>
|
||||||
|
|
||||||
const server_id = new URLSearchParams(document.location.search).get('id')
|
const server_id = new URLSearchParams(document.location.search).get('id')
|
||||||
|
const backup_id = new URLSearchParams(document.location.search).get('backup_id')
|
||||||
|
|
||||||
|
|
||||||
//used to get cookies from browser - this is part of tornados xsrf protection - it's for extra security
|
//used to get cookies from browser - this is part of tornados xsrf protection - it's for extra security
|
||||||
@ -310,7 +312,7 @@
|
|||||||
|
|
||||||
async function backup_started() {
|
async function backup_started() {
|
||||||
const token = getCookie("_xsrf")
|
const token = getCookie("_xsrf")
|
||||||
let res = await fetch(`/api/v2/servers/${server_id}/action/backup_server`, {
|
let res = await fetch(`/api/v2/servers/${server_id}/action/backup_server/${backup_id}`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'X-XSRFToken': token
|
'X-XSRFToken': token
|
||||||
@ -339,7 +341,7 @@
|
|||||||
async function del_backup(filename, id) {
|
async function del_backup(filename, id) {
|
||||||
const token = getCookie("_xsrf")
|
const token = getCookie("_xsrf")
|
||||||
let contents = JSON.stringify({ "filename": filename })
|
let contents = JSON.stringify({ "filename": filename })
|
||||||
let res = await fetch(`/api/v2/servers/${id}/backups/backup/`, {
|
let res = await fetch(`/api/v2/servers/${id}/backups/backup/${backup_id}/`, {
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
headers: {
|
headers: {
|
||||||
'token': token,
|
'token': token,
|
||||||
@ -364,7 +366,7 @@
|
|||||||
message: "<i class='fa fa-spin fa-spinner'></i> {{ translate('serverBackups', 'restoring', data['lang']) }}",
|
message: "<i class='fa fa-spin fa-spinner'></i> {{ translate('serverBackups', 'restoring', data['lang']) }}",
|
||||||
closeButton: false
|
closeButton: false
|
||||||
});
|
});
|
||||||
let res = await fetch(`/api/v2/servers/${id}/backups/backup/`, {
|
let res = await fetch(`/api/v2/servers/${id}/backups/backup/${backup_id}/`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'token': token,
|
'token': token,
|
||||||
@ -400,7 +402,14 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
function replacer(key, value) {
|
function replacer(key, value) {
|
||||||
if (key != "backup_before" && key != "backup_after") {
|
if (key === "exclusions") {
|
||||||
|
if (value == 0) {
|
||||||
|
return []
|
||||||
|
} else {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (key != "before" && key != "after") {
|
||||||
if (typeof value == "boolean" || key === "executable_update_url") {
|
if (typeof value == "boolean" || key === "executable_update_url") {
|
||||||
return value
|
return value
|
||||||
} else {
|
} else {
|
||||||
@ -426,22 +435,20 @@
|
|||||||
//We need to make sure these are sent regardless of whether or not they're checked
|
//We need to make sure these are sent regardless of whether or not they're checked
|
||||||
formDataObject.compress = $("#compress").prop('checked');
|
formDataObject.compress = $("#compress").prop('checked');
|
||||||
formDataObject.shutdown = $("#shutdown").prop('checked');
|
formDataObject.shutdown = $("#shutdown").prop('checked');
|
||||||
let excluded = [];
|
|
||||||
$('input.excluded:checkbox:checked').each(function () {
|
|
||||||
excluded.push($(this).val());
|
|
||||||
});
|
|
||||||
if ($("#root_files_button").hasClass("clicked")) {
|
if ($("#root_files_button").hasClass("clicked")) {
|
||||||
|
$('input.excluded:checkbox:checked').each(function () {
|
||||||
|
excluded.push($(this).val());
|
||||||
|
});
|
||||||
formDataObject.exclusions = excluded;
|
formDataObject.exclusions = excluded;
|
||||||
}
|
}
|
||||||
delete formDataObject.root_path
|
delete formDataObject.root_path
|
||||||
console.log(excluded);
|
|
||||||
console.log(formDataObject);
|
console.log(formDataObject);
|
||||||
// Format the plain form data as JSON
|
// Format the plain form data as JSON
|
||||||
let formDataJsonString = JSON.stringify(formDataObject, replacer);
|
let formDataJsonString = JSON.stringify(formDataObject, replacer);
|
||||||
|
|
||||||
console.log(formDataJsonString);
|
console.log(formDataJsonString);
|
||||||
|
|
||||||
let res = await fetch(`/api/v2/servers/${server_id}/backups/`, {
|
let res = await fetch(`/api/v2/servers/${server_id}/backups/backup/${backup_id}`, {
|
||||||
method: 'PATCH',
|
method: 'PATCH',
|
||||||
headers: {
|
headers: {
|
||||||
'X-XSRFToken': token
|
'X-XSRFToken': token
|
||||||
@ -461,7 +468,7 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if ($('#backup_path').val() == '') {
|
if ($('#backup_location').val() == '') {
|
||||||
console.log('true')
|
console.log('true')
|
||||||
try {
|
try {
|
||||||
document.getElementById('backup_now_button').disabled = true;
|
document.getElementById('backup_now_button').disabled = true;
|
||||||
@ -502,7 +509,7 @@
|
|||||||
|
|
||||||
$(".del_button").click(function () {
|
$(".del_button").click(function () {
|
||||||
var file_to_del = $(this).data("file");
|
var file_to_del = $(this).data("file");
|
||||||
var backup_path = $(this).data('backup_path');
|
var backup_location = $(this).data('backup_location');
|
||||||
|
|
||||||
console.log("file to delete is" + file_to_del);
|
console.log("file to delete is" + file_to_del);
|
||||||
|
|
||||||
@ -520,7 +527,7 @@
|
|||||||
callback: function (result) {
|
callback: function (result) {
|
||||||
console.log(result);
|
console.log(result);
|
||||||
if (result == true) {
|
if (result == true) {
|
||||||
var full_path = backup_path + '/' + file_to_del;
|
var full_path = backup_location + '/' + file_to_del;
|
||||||
del_backup(file_to_del, server_id);
|
del_backup(file_to_del, server_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user