mirror of
https://gitlab.com/crafty-controller/crafty-4.git
synced 2024-08-30 18:23:09 +00:00
Merge branch 'dev' into feature/backup-echo
This commit is contained in:
commit
b5d259bce7
@ -3,9 +3,12 @@
|
||||
### New features
|
||||
TBD
|
||||
### Bug fixes
|
||||
TBD
|
||||
- Fix local java server imports. ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/529))
|
||||
- Fix Schedule Restore | Add Backup Config Preservation. ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/533))
|
||||
### Tweaks
|
||||
TBD
|
||||
- Added further login screen customisation settings. ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/531))
|
||||
- Set backup filename to use same time as schedule. ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/534))
|
||||
- Move Schedules to from DB to Queue Datatype. ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/535))
|
||||
### Lang
|
||||
TBD
|
||||
<br><br>
|
||||
|
@ -1,4 +1,5 @@
|
||||
import logging
|
||||
import queue
|
||||
|
||||
from app.classes.models.management import HelpersManagement
|
||||
from app.classes.models.servers import HelperServers
|
||||
@ -9,6 +10,26 @@ logger = logging.getLogger(__name__)
|
||||
class ManagementController:
|
||||
def __init__(self, management_helper):
|
||||
self.management_helper = management_helper
|
||||
self.command_queue = queue.Queue()
|
||||
|
||||
# **********************************************************************************
|
||||
# Config Methods
|
||||
# **********************************************************************************
|
||||
@staticmethod
|
||||
def set_login_image(path):
|
||||
HelpersManagement.set_login_image(path)
|
||||
|
||||
@staticmethod
|
||||
def get_login_image():
|
||||
return HelpersManagement.get_login_image()
|
||||
|
||||
@staticmethod
|
||||
def set_login_opacity(opacity):
|
||||
return HelpersManagement.set_login_opacity(opacity)
|
||||
|
||||
@staticmethod
|
||||
def get_login_opacity():
|
||||
return HelpersManagement.get_login_opacity()
|
||||
|
||||
# **********************************************************************************
|
||||
# Host_Stats Methods
|
||||
@ -28,9 +49,6 @@ class ManagementController:
|
||||
# **********************************************************************************
|
||||
# Commands Methods
|
||||
# **********************************************************************************
|
||||
@staticmethod
|
||||
def get_unactioned_commands():
|
||||
return HelpersManagement.get_unactioned_commands()
|
||||
|
||||
def send_command(self, user_id, server_id, remote_ip, command):
|
||||
server_name = HelperServers.get_server_friendly_name(server_id)
|
||||
@ -42,11 +60,12 @@ class ManagementController:
|
||||
server_id,
|
||||
remote_ip,
|
||||
)
|
||||
HelpersManagement.add_command(server_id, user_id, remote_ip, command)
|
||||
self.queue_command(
|
||||
{"server_id": server_id, "user_id": user_id, "command": command}
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def mark_command_complete(command_id=None):
|
||||
return HelpersManagement.mark_command_complete(command_id)
|
||||
def queue_command(self, command_data):
|
||||
self.command_queue.put(command_data)
|
||||
|
||||
# **********************************************************************************
|
||||
# Audit_Log Methods
|
||||
@ -78,6 +97,10 @@ class ManagementController:
|
||||
command,
|
||||
name,
|
||||
enabled=True,
|
||||
one_time=False,
|
||||
cron_string="* * * * *",
|
||||
parent=None,
|
||||
delay=0,
|
||||
):
|
||||
return HelpersManagement.create_scheduled_task(
|
||||
server_id,
|
||||
@ -88,20 +111,16 @@ class ManagementController:
|
||||
command,
|
||||
name,
|
||||
enabled,
|
||||
one_time,
|
||||
cron_string,
|
||||
parent,
|
||||
delay,
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def delete_scheduled_task(schedule_id):
|
||||
return HelpersManagement.delete_scheduled_task(schedule_id)
|
||||
|
||||
@staticmethod
|
||||
def set_login_image(path):
|
||||
HelpersManagement.set_login_image(path)
|
||||
|
||||
@staticmethod
|
||||
def get_login_image():
|
||||
return HelpersManagement.get_login_image()
|
||||
|
||||
@staticmethod
|
||||
def update_scheduled_task(schedule_id, updates):
|
||||
return HelpersManagement.update_scheduled_task(schedule_id, updates)
|
||||
|
@ -13,7 +13,7 @@ from peewee import (
|
||||
from playhouse.shortcuts import model_to_dict
|
||||
|
||||
from app.classes.models.base_model import BaseModel
|
||||
from app.classes.models.users import Users, HelperUsers
|
||||
from app.classes.models.users import HelperUsers
|
||||
from app.classes.models.servers import Servers
|
||||
from app.classes.models.server_permissions import PermissionsServers
|
||||
from app.classes.shared.main_models import DatabaseShortcuts
|
||||
@ -44,6 +44,7 @@ class AuditLog(BaseModel):
|
||||
class CraftySettings(BaseModel):
|
||||
secret_api_key = CharField(default="")
|
||||
login_photo = CharField(default="login_1.jpg")
|
||||
login_opacity = IntegerField(default=100)
|
||||
|
||||
class Meta:
|
||||
table_name = "crafty_settings"
|
||||
@ -68,22 +69,6 @@ class HostStats(BaseModel):
|
||||
table_name = "host_stats"
|
||||
|
||||
|
||||
# **********************************************************************************
|
||||
# Commands Class
|
||||
# **********************************************************************************
|
||||
class Commands(BaseModel):
|
||||
command_id = AutoField()
|
||||
created = DateTimeField(default=datetime.datetime.now)
|
||||
server_id = ForeignKeyField(Servers, backref="server", index=True)
|
||||
user = ForeignKeyField(Users, backref="user", index=True)
|
||||
source_ip = CharField(default="127.0.0.1")
|
||||
command = CharField(default="")
|
||||
executed = BooleanField(default=False)
|
||||
|
||||
class Meta:
|
||||
table_name = "commands"
|
||||
|
||||
|
||||
# **********************************************************************************
|
||||
# Webhooks Class
|
||||
# **********************************************************************************
|
||||
@ -152,33 +137,6 @@ class HelpersManagement:
|
||||
query = HostStats.select().order_by(HostStats.id.desc()).get()
|
||||
return model_to_dict(query)
|
||||
|
||||
# **********************************************************************************
|
||||
# Commands Methods
|
||||
# **********************************************************************************
|
||||
@staticmethod
|
||||
def add_command(server_id, user_id, remote_ip, command):
|
||||
Commands.insert(
|
||||
{
|
||||
Commands.server_id: server_id,
|
||||
Commands.user: user_id,
|
||||
Commands.source_ip: remote_ip,
|
||||
Commands.command: command,
|
||||
}
|
||||
).execute()
|
||||
|
||||
@staticmethod
|
||||
def get_unactioned_commands():
|
||||
query = Commands.select().where(Commands.executed == 0)
|
||||
return query
|
||||
|
||||
@staticmethod
|
||||
def mark_command_complete(command_id=None):
|
||||
if command_id is not None:
|
||||
logger.debug(f"Marking Command {command_id} completed")
|
||||
Commands.update({Commands.executed: True}).where(
|
||||
Commands.command_id == command_id
|
||||
).execute()
|
||||
|
||||
# **********************************************************************************
|
||||
# Audit_Log Methods
|
||||
# **********************************************************************************
|
||||
@ -257,6 +215,9 @@ class HelpersManagement:
|
||||
)
|
||||
return settings[0].secret_api_key
|
||||
|
||||
# **********************************************************************************
|
||||
# Config Methods
|
||||
# **********************************************************************************
|
||||
@staticmethod
|
||||
def get_login_image():
|
||||
settings = CraftySettings.select(CraftySettings.login_photo).where(
|
||||
@ -270,6 +231,19 @@ class HelpersManagement:
|
||||
CraftySettings.id == 1
|
||||
).execute()
|
||||
|
||||
@staticmethod
|
||||
def get_login_opacity():
|
||||
settings = CraftySettings.select(CraftySettings.login_opacity).where(
|
||||
CraftySettings.id == 1
|
||||
)
|
||||
return settings[0].login_opacity
|
||||
|
||||
@staticmethod
|
||||
def set_login_opacity(opacity):
|
||||
CraftySettings.update({CraftySettings.login_opacity: opacity}).where(
|
||||
CraftySettings.id == 1
|
||||
).execute()
|
||||
|
||||
# **********************************************************************************
|
||||
# Schedules Methods
|
||||
# **********************************************************************************
|
||||
@ -485,9 +459,3 @@ class HelpersManagement:
|
||||
f"Not removing {dir_to_del} from excluded directories - "
|
||||
f"not in the excluded directory list for server ID {server_id}"
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def clear_unexecuted_commands():
|
||||
Commands.update({Commands.executed: True}).where(
|
||||
Commands.executed == False # pylint: disable=singleton-comparison
|
||||
).execute()
|
||||
|
@ -965,10 +965,6 @@ class Controller:
|
||||
# remove the server from the DB
|
||||
self.servers.remove_server(server_id)
|
||||
|
||||
@staticmethod
|
||||
def clear_unexecuted_commands():
|
||||
HelpersManagement.clear_unexecuted_commands()
|
||||
|
||||
@staticmethod
|
||||
def clear_support_status():
|
||||
HelperUsers.clear_support_status()
|
||||
|
@ -131,13 +131,13 @@ class ServerInstance:
|
||||
self.stats_helper = HelperServerStats(self.server_id)
|
||||
self.last_backup_failed = False
|
||||
try:
|
||||
tz = get_localzone()
|
||||
self.tz = get_localzone()
|
||||
except ZoneInfoNotFoundError:
|
||||
logger.error(
|
||||
"Could not capture time zone from system. Falling back to Europe/London"
|
||||
)
|
||||
tz = "Europe/London"
|
||||
self.server_scheduler = BackgroundScheduler(timezone=str(tz))
|
||||
self.tz = "Europe/London"
|
||||
self.server_scheduler = BackgroundScheduler(timezone=str(self.tz))
|
||||
self.server_scheduler.start()
|
||||
self.backup_thread = threading.Thread(
|
||||
target=self.a_backup_server, daemon=True, name=f"backup_{self.name}"
|
||||
@ -1047,7 +1047,7 @@ class ServerInstance:
|
||||
try:
|
||||
backup_filename = (
|
||||
f"{self.settings['backup_path']}/"
|
||||
f"{datetime.datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}"
|
||||
f"{datetime.datetime.now().astimezone(self.tz).strftime('%Y-%m-%d_%H-%M-%S')}" # pylint: disable=line-too-long
|
||||
)
|
||||
logger.info(
|
||||
f"Creating backup of server '{self.settings['server_name']}'"
|
||||
|
@ -91,22 +91,21 @@ class TasksManager:
|
||||
def command_watcher(self):
|
||||
while True:
|
||||
# select any commands waiting to be processed
|
||||
commands = HelpersManagement.get_unactioned_commands()
|
||||
for cmd in commands:
|
||||
if not self.controller.management.command_queue.empty():
|
||||
cmd = self.controller.management.command_queue.get()
|
||||
try:
|
||||
svr = self.controller.servers.get_server_instance_by_id(
|
||||
cmd.server_id.server_id
|
||||
cmd["server_id"]
|
||||
)
|
||||
except:
|
||||
logger.error(
|
||||
"Server value requested does not exist! "
|
||||
"Purging item from waiting commands."
|
||||
)
|
||||
HelpersManagement.mark_command_complete(cmd.command_id)
|
||||
continue
|
||||
|
||||
user_id = cmd.user_id
|
||||
command = cmd.command
|
||||
user_id = cmd["user_id"]
|
||||
command = cmd["command"]
|
||||
|
||||
if command == "start_server":
|
||||
svr.run_threaded_server(user_id)
|
||||
@ -136,8 +135,6 @@ class TasksManager:
|
||||
else:
|
||||
svr.send_command(command)
|
||||
|
||||
HelpersManagement.mark_command_complete(cmd.command_id)
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
def _main_graceful_exit(self):
|
||||
@ -212,16 +209,19 @@ class TasksManager:
|
||||
if schedule.cron_string != "":
|
||||
try:
|
||||
new_job = self.scheduler.add_job(
|
||||
HelpersManagement.add_command,
|
||||
self.controller.management.queue_command,
|
||||
CronTrigger.from_crontab(
|
||||
schedule.cron_string, timezone=str(self.tz)
|
||||
),
|
||||
id=str(schedule.schedule_id),
|
||||
args=[
|
||||
schedule.server_id,
|
||||
self.users_controller.get_id_by_name("system"),
|
||||
"127.0.0.1",
|
||||
schedule.command,
|
||||
{
|
||||
"server_id": schedule.server_id.server_id,
|
||||
"user_id": self.users_controller.get_id_by_name(
|
||||
"system"
|
||||
),
|
||||
"command": schedule.command,
|
||||
}
|
||||
],
|
||||
)
|
||||
except Exception as e:
|
||||
@ -237,45 +237,54 @@ class TasksManager:
|
||||
else:
|
||||
if schedule.interval_type == "hours":
|
||||
new_job = self.scheduler.add_job(
|
||||
HelpersManagement.add_command,
|
||||
self.controller.management.queue_command,
|
||||
"cron",
|
||||
minute=0,
|
||||
hour="*/" + str(schedule.interval),
|
||||
id=str(schedule.schedule_id),
|
||||
args=[
|
||||
schedule.server_id,
|
||||
self.users_controller.get_id_by_name("system"),
|
||||
"127.0.0.1",
|
||||
schedule.command,
|
||||
{
|
||||
"server_id": schedule.server_id.server_id,
|
||||
"user_id": self.users_controller.get_id_by_name(
|
||||
"system"
|
||||
),
|
||||
"command": schedule.command,
|
||||
}
|
||||
],
|
||||
)
|
||||
elif schedule.interval_type == "minutes":
|
||||
new_job = self.scheduler.add_job(
|
||||
HelpersManagement.add_command,
|
||||
self.controller.management.queue_command,
|
||||
"cron",
|
||||
minute="*/" + str(schedule.interval),
|
||||
id=str(schedule.schedule_id),
|
||||
args=[
|
||||
schedule.server_id,
|
||||
self.users_controller.get_id_by_name("system"),
|
||||
"127.0.0.1",
|
||||
schedule.command,
|
||||
{
|
||||
"server_id": schedule.server_id.server_id,
|
||||
"user_id": self.users_controller.get_id_by_name(
|
||||
"system"
|
||||
),
|
||||
"command": schedule.command,
|
||||
}
|
||||
],
|
||||
)
|
||||
elif schedule.interval_type == "days":
|
||||
curr_time = schedule.start_time.split(":")
|
||||
new_job = self.scheduler.add_job(
|
||||
HelpersManagement.add_command,
|
||||
self.controller.management.queue_command,
|
||||
"cron",
|
||||
day="*/" + str(schedule.interval),
|
||||
hour=curr_time[0],
|
||||
minute=curr_time[1],
|
||||
id=str(schedule.schedule_id),
|
||||
args=[
|
||||
schedule.server_id,
|
||||
self.users_controller.get_id_by_name("system"),
|
||||
"127.0.0.1",
|
||||
schedule.command,
|
||||
{
|
||||
"server_id": schedule.server_id.server_id,
|
||||
"user_id": self.users_controller.get_id_by_name(
|
||||
"system"
|
||||
),
|
||||
"command": schedule.command,
|
||||
}
|
||||
],
|
||||
)
|
||||
if new_job != "error":
|
||||
@ -322,16 +331,19 @@ class TasksManager:
|
||||
if job_data["cron_string"] != "":
|
||||
try:
|
||||
new_job = self.scheduler.add_job(
|
||||
HelpersManagement.add_command,
|
||||
self.controller.management.queue_command,
|
||||
CronTrigger.from_crontab(
|
||||
job_data["cron_string"], timezone=str(self.tz)
|
||||
),
|
||||
id=str(sch_id),
|
||||
args=[
|
||||
job_data["server_id"],
|
||||
self.users_controller.get_id_by_name("system"),
|
||||
"127.0.0.1",
|
||||
job_data["command"],
|
||||
{
|
||||
"server_id": job_data["server_id"],
|
||||
"user_id": self.users_controller.get_id_by_name(
|
||||
"system"
|
||||
),
|
||||
"command": job_data["command"],
|
||||
}
|
||||
],
|
||||
)
|
||||
except Exception as e:
|
||||
@ -345,45 +357,54 @@ class TasksManager:
|
||||
else:
|
||||
if job_data["interval_type"] == "hours":
|
||||
new_job = self.scheduler.add_job(
|
||||
HelpersManagement.add_command,
|
||||
self.controller.management.queue_command,
|
||||
"cron",
|
||||
minute=0,
|
||||
hour="*/" + str(job_data["interval"]),
|
||||
id=str(sch_id),
|
||||
args=[
|
||||
job_data["server_id"],
|
||||
self.users_controller.get_id_by_name("system"),
|
||||
"127.0.0.1",
|
||||
job_data["command"],
|
||||
{
|
||||
"server_id": job_data["server_id"],
|
||||
"user_id": self.users_controller.get_id_by_name(
|
||||
"system"
|
||||
),
|
||||
"command": job_data["command"],
|
||||
}
|
||||
],
|
||||
)
|
||||
elif job_data["interval_type"] == "minutes":
|
||||
new_job = self.scheduler.add_job(
|
||||
HelpersManagement.add_command,
|
||||
self.controller.management.queue_command,
|
||||
"cron",
|
||||
minute="*/" + str(job_data["interval"]),
|
||||
id=str(sch_id),
|
||||
args=[
|
||||
job_data["server_id"],
|
||||
self.users_controller.get_id_by_name("system"),
|
||||
"127.0.0.1",
|
||||
job_data["command"],
|
||||
{
|
||||
"server_id": job_data["server_id"],
|
||||
"user_id": self.users_controller.get_id_by_name(
|
||||
"system"
|
||||
),
|
||||
"command": job_data["command"],
|
||||
}
|
||||
],
|
||||
)
|
||||
elif job_data["interval_type"] == "days":
|
||||
curr_time = job_data["start_time"].split(":")
|
||||
new_job = self.scheduler.add_job(
|
||||
HelpersManagement.add_command,
|
||||
self.controller.management.queue_command,
|
||||
"cron",
|
||||
day="*/" + str(job_data["interval"]),
|
||||
hour=curr_time[0],
|
||||
minute=curr_time[1],
|
||||
id=str(sch_id),
|
||||
args=[
|
||||
job_data["server_id"],
|
||||
self.users_controller.get_id_by_name("system"),
|
||||
"127.0.0.1",
|
||||
job_data["command"],
|
||||
{
|
||||
"server_id": job_data["server_id"],
|
||||
"user_id": self.users_controller.get_id_by_name(
|
||||
"system"
|
||||
),
|
||||
"command": job_data["command"],
|
||||
}
|
||||
],
|
||||
)
|
||||
logger.info("Added job. Current enabled schedules: ")
|
||||
@ -460,16 +481,19 @@ class TasksManager:
|
||||
if job_data["cron_string"] != "":
|
||||
try:
|
||||
new_job = self.scheduler.add_job(
|
||||
HelpersManagement.add_command,
|
||||
self.controller.management.queue_command,
|
||||
CronTrigger.from_crontab(
|
||||
job_data["cron_string"], timezone=str(self.tz)
|
||||
),
|
||||
id=str(sch_id),
|
||||
args=[
|
||||
job_data["server_id"],
|
||||
self.users_controller.get_id_by_name("system"),
|
||||
"127.0.0.1",
|
||||
job_data["command"],
|
||||
{
|
||||
"server_id": job_data["server_id"],
|
||||
"user_id": self.users_controller.get_id_by_name(
|
||||
"system"
|
||||
),
|
||||
"command": job_data["command"],
|
||||
}
|
||||
],
|
||||
)
|
||||
except Exception as e:
|
||||
@ -480,45 +504,54 @@ class TasksManager:
|
||||
else:
|
||||
if job_data["interval_type"] == "hours":
|
||||
new_job = self.scheduler.add_job(
|
||||
HelpersManagement.add_command,
|
||||
self.controller.management.queue_command,
|
||||
"cron",
|
||||
minute=0,
|
||||
hour="*/" + str(job_data["interval"]),
|
||||
id=str(sch_id),
|
||||
args=[
|
||||
job_data["server_id"],
|
||||
self.users_controller.get_id_by_name("system"),
|
||||
"127.0.0.1",
|
||||
job_data["command"],
|
||||
{
|
||||
"server_id": job_data["server_id"],
|
||||
"user_id": self.users_controller.get_id_by_name(
|
||||
"system"
|
||||
),
|
||||
"command": job_data["command"],
|
||||
}
|
||||
],
|
||||
)
|
||||
elif job_data["interval_type"] == "minutes":
|
||||
new_job = self.scheduler.add_job(
|
||||
HelpersManagement.add_command,
|
||||
self.controller.management.queue_command,
|
||||
"cron",
|
||||
minute="*/" + str(job_data["interval"]),
|
||||
id=str(sch_id),
|
||||
args=[
|
||||
job_data["server_id"],
|
||||
self.users_controller.get_id_by_name("system"),
|
||||
"127.0.0.1",
|
||||
job_data["command"],
|
||||
{
|
||||
"server_id": job_data["server_id"],
|
||||
"user_id": self.users_controller.get_id_by_name(
|
||||
"system"
|
||||
),
|
||||
"command": job_data["command"],
|
||||
}
|
||||
],
|
||||
)
|
||||
elif job_data["interval_type"] == "days":
|
||||
curr_time = job_data["start_time"].split(":")
|
||||
new_job = self.scheduler.add_job(
|
||||
HelpersManagement.add_command,
|
||||
self.controller.management.queue_command,
|
||||
"cron",
|
||||
day="*/" + str(job_data["interval"]),
|
||||
hour=curr_time[0],
|
||||
minute=curr_time[1],
|
||||
id=str(sch_id),
|
||||
args=[
|
||||
job_data["server_id"],
|
||||
self.users_controller.get_id_by_name("system"),
|
||||
"127.0.0.1",
|
||||
job_data["command"],
|
||||
{
|
||||
"server_id": job_data["server_id"],
|
||||
"user_id": self.users_controller.get_id_by_name(
|
||||
"system"
|
||||
),
|
||||
"command": job_data["command"],
|
||||
}
|
||||
],
|
||||
)
|
||||
if new_job != "error":
|
||||
@ -579,15 +612,18 @@ class TasksManager:
|
||||
seconds=schedule.delay
|
||||
)
|
||||
self.scheduler.add_job(
|
||||
HelpersManagement.add_command,
|
||||
self.controller.management.queue_command,
|
||||
"date",
|
||||
run_date=delaytime,
|
||||
id=str(schedule.schedule_id),
|
||||
args=[
|
||||
schedule.server_id,
|
||||
self.users_controller.get_id_by_name("system"),
|
||||
"127.0.0.1",
|
||||
schedule.command,
|
||||
{
|
||||
"server_id": schedule.server_id.server_id,
|
||||
"user_id": self.users_controller.get_id_by_name(
|
||||
"system"
|
||||
),
|
||||
"command": schedule.command,
|
||||
}
|
||||
],
|
||||
)
|
||||
else:
|
||||
|
@ -348,14 +348,11 @@ class AjaxHandler(BaseHandler):
|
||||
|
||||
server.backup_server()
|
||||
|
||||
elif page == "clear_comms":
|
||||
if exec_user["superuser"]:
|
||||
self.controller.clear_unexecuted_commands()
|
||||
return
|
||||
|
||||
elif page == "select_photo":
|
||||
if exec_user["superuser"]:
|
||||
photo = self.get_argument("photo", None)
|
||||
photo = urllib.parse.unquote(self.get_argument("photo", ""))
|
||||
opacity = self.get_argument("opacity", 100)
|
||||
self.controller.management.set_login_opacity(int(opacity))
|
||||
if photo == "login_1.jpg":
|
||||
self.controller.management.set_login_image("login_1.jpg")
|
||||
self.controller.cached_login = f"{photo}"
|
||||
@ -366,7 +363,7 @@ class AjaxHandler(BaseHandler):
|
||||
|
||||
elif page == "delete_photo":
|
||||
if exec_user["superuser"]:
|
||||
photo = self.get_argument("photo", None)
|
||||
photo = urllib.parse.unquote(self.get_argument("photo", None))
|
||||
if photo and photo != "login_1.jpg":
|
||||
os.remove(
|
||||
os.path.join(
|
||||
@ -440,15 +437,8 @@ class AjaxHandler(BaseHandler):
|
||||
for schedule in self.controller.management.get_schedules_by_server(
|
||||
server_id
|
||||
):
|
||||
self.controller.management.create_scheduled_task(
|
||||
new_server_id,
|
||||
schedule.action,
|
||||
schedule.interval,
|
||||
schedule.interval_type,
|
||||
schedule.start_time,
|
||||
schedule.command,
|
||||
schedule.name,
|
||||
schedule.enabled,
|
||||
self.tasks_manager.update_job(
|
||||
schedule.schedule_id, {"server_id": new_server_id}
|
||||
)
|
||||
# preserve execution command
|
||||
new_server_obj = self.controller.servers.get_server_obj(
|
||||
@ -456,6 +446,29 @@ class AjaxHandler(BaseHandler):
|
||||
)
|
||||
new_server_obj.execution_command = server_data["execution_command"]
|
||||
self.controller.servers.update_server(new_server_obj)
|
||||
|
||||
# preserve backup config
|
||||
backup_config = self.controller.management.get_backup_config(
|
||||
server_id
|
||||
)
|
||||
excluded_dirs = []
|
||||
server_obj = self.controller.servers.get_server_obj(server_id)
|
||||
loop_backup_path = self.helper.wtol_path(server_obj.path)
|
||||
for item in self.controller.management.get_excluded_backup_dirs(
|
||||
server_id
|
||||
):
|
||||
item_path = self.helper.wtol_path(item)
|
||||
bu_path = os.path.relpath(item_path, loop_backup_path)
|
||||
bu_path = os.path.join(new_server_obj.path, bu_path)
|
||||
excluded_dirs.append(bu_path)
|
||||
self.controller.management.set_backup_config(
|
||||
new_server_id,
|
||||
new_server_obj.backup_path,
|
||||
backup_config["max_backups"],
|
||||
excluded_dirs,
|
||||
backup_config["compress"],
|
||||
backup_config["shutdown"],
|
||||
)
|
||||
# remove old server's tasks
|
||||
try:
|
||||
self.tasks_manager.remove_all_server_tasks(server_id)
|
||||
@ -484,15 +497,8 @@ class AjaxHandler(BaseHandler):
|
||||
for schedule in self.controller.management.get_schedules_by_server(
|
||||
server_id
|
||||
):
|
||||
self.controller.management.create_scheduled_task(
|
||||
new_server_id,
|
||||
schedule.action,
|
||||
schedule.interval,
|
||||
schedule.interval_type,
|
||||
schedule.start_time,
|
||||
schedule.command,
|
||||
schedule.name,
|
||||
schedule.enabled,
|
||||
self.tasks_manager.update_job(
|
||||
schedule.schedule_id, {"server_id": new_server_id}
|
||||
)
|
||||
# preserve execution command
|
||||
new_server_obj = self.controller.servers.get_server_obj(
|
||||
@ -500,6 +506,29 @@ class AjaxHandler(BaseHandler):
|
||||
)
|
||||
new_server_obj.execution_command = server_data["execution_command"]
|
||||
self.controller.servers.update_server(new_server_obj)
|
||||
|
||||
# preserve backup config
|
||||
backup_config = self.controller.management.get_backup_config(
|
||||
server_id
|
||||
)
|
||||
excluded_dirs = []
|
||||
server_obj = self.controller.servers.get_server_obj(server_id)
|
||||
loop_backup_path = self.helper.wtol_path(server_obj.path)
|
||||
for item in self.controller.management.get_excluded_backup_dirs(
|
||||
server_id
|
||||
):
|
||||
item_path = self.helper.wtol_path(item)
|
||||
bu_path = os.path.relpath(item_path, loop_backup_path)
|
||||
bu_path = os.path.join(new_server_obj.path, bu_path)
|
||||
excluded_dirs.append(bu_path)
|
||||
self.controller.management.set_backup_config(
|
||||
new_server_id,
|
||||
new_server_obj.backup_path,
|
||||
backup_config["max_backups"],
|
||||
excluded_dirs,
|
||||
backup_config["compress"],
|
||||
backup_config["shutdown"],
|
||||
)
|
||||
try:
|
||||
self.tasks_manager.remove_all_server_tasks(server_id)
|
||||
except:
|
||||
|
@ -291,6 +291,7 @@ class PanelHandler(BaseHandler):
|
||||
# todo: make this actually pull and compare version data
|
||||
"update_available": self.helper.update_available,
|
||||
"background": self.controller.cached_login,
|
||||
"login_opacity": self.controller.management.get_login_opacity(),
|
||||
"serverTZ": tz,
|
||||
"version_data": self.helper.get_version_string(),
|
||||
"failed_servers": self.controller.servers.failed_servers,
|
||||
@ -883,6 +884,9 @@ class PanelHandler(BaseHandler):
|
||||
if item not in page_data["backgrounds"]:
|
||||
page_data["backgrounds"].append(item)
|
||||
page_data["background"] = self.controller.cached_login
|
||||
page_data[
|
||||
"login_opacity"
|
||||
] = self.controller.management.get_login_opacity()
|
||||
else:
|
||||
page_data["managed_users"] = self.controller.users.get_managed_users(
|
||||
exec_user["user_id"]
|
||||
|
@ -40,6 +40,7 @@ class PublicHandler(BaseHandler):
|
||||
"lang_page": self.helper.get_lang_page(self.helper.get_setting("language")),
|
||||
"query": "",
|
||||
"background": self.controller.cached_login,
|
||||
"login_opacity": self.controller.management.get_login_opacity(),
|
||||
}
|
||||
|
||||
if self.request.query:
|
||||
|
@ -331,7 +331,7 @@ class ServerHandler(BaseHandler):
|
||||
return
|
||||
|
||||
if import_type == "import_jar":
|
||||
if not self.helper.is_subdir(
|
||||
if self.helper.is_subdir(
|
||||
import_server_path, self.controller.project_root
|
||||
):
|
||||
self.redirect(
|
||||
|
@ -1,69 +1,82 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!-- Required meta tags -->
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<title>Crafty Controller</title>
|
||||
<!-- plugins:css -->
|
||||
<link rel="stylesheet" href="/static/assets/vendors/mdi/css/materialdesignicons.min.css">
|
||||
<link rel="stylesheet" href="/static/assets/vendors/flag-icon-css/css/flag-icon.min.css">
|
||||
<link rel="stylesheet" href="/static/assets/vendors/ti-icons/css/themify-icons.css">
|
||||
<link rel="stylesheet" href="/static/assets/vendors/typicons/typicons.css">
|
||||
<link rel="stylesheet" href="/static/assets/vendors/css/vendor.bundle.base.css">
|
||||
<!-- endinject -->
|
||||
<!-- Plugin css for this page -->
|
||||
<!-- End Plugin css for this page -->
|
||||
<!-- Layout styles -->
|
||||
<link rel="stylesheet" href="/static/assets/css/dark/style.css">
|
||||
<!-- End Layout styles -->
|
||||
<link rel="shortcut icon" type="image/svg+xml" href="/static/assets/images/logo_small.svg">
|
||||
<link rel="alternate icon" href="/static/assets/images/favicon.png" />
|
||||
</head>
|
||||
<body class="dark-theme">
|
||||
<div class="container-scroller">
|
||||
<div class="container-fluid page-body-wrapper full-page-wrapper">
|
||||
<div class="content-wrapper d-flex align-items-center auth auth-bg-1 theme-one">
|
||||
<div class="row w-100">
|
||||
<div class="col-lg-4 mx-auto">
|
||||
|
||||
<div class="auto-form-wrapper">
|
||||
<div class="text-center">
|
||||
<head>
|
||||
<!-- Required meta tags -->
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<title>Crafty Controller</title>
|
||||
<!-- plugins:css -->
|
||||
<link rel="stylesheet" href="/static/assets/vendors/mdi/css/materialdesignicons.min.css">
|
||||
<link rel="stylesheet" href="/static/assets/vendors/flag-icon-css/css/flag-icon.min.css">
|
||||
<link rel="stylesheet" href="/static/assets/vendors/ti-icons/css/themify-icons.css">
|
||||
<link rel="stylesheet" href="/static/assets/vendors/typicons/typicons.css">
|
||||
<link rel="stylesheet" href="/static/assets/vendors/css/vendor.bundle.base.css">
|
||||
<!-- endinject -->
|
||||
<!-- Plugin css for this page -->
|
||||
<!-- End Plugin css for this page -->
|
||||
<!-- Layout styles -->
|
||||
<link rel="stylesheet" href="/static/assets/css/dark/style.css">
|
||||
<!-- End Layout styles -->
|
||||
<link rel="shortcut icon" type="image/svg+xml" href="/static/assets/images/logo_small.svg">
|
||||
<link rel="alternate icon" href="/static/assets/images/favicon.png" />
|
||||
</head>
|
||||
<style>
|
||||
.auth.auth-bg-1 {
|
||||
background: url("../../static/assets/images/auth/{% raw data['background'] %}"),
|
||||
url("../../static/assets/images/auth/login-1.jpg");
|
||||
background-size: cover;
|
||||
}
|
||||
</style>
|
||||
|
||||
<body class="dark-theme">
|
||||
<div class="container-scroller">
|
||||
<div class="container-fluid page-body-wrapper full-page-wrapper">
|
||||
<div class="content-wrapper d-flex align-items-center auth auth-bg-1 theme-one">
|
||||
<div class="row w-100">
|
||||
<div class="col-lg-4 mx-auto">
|
||||
|
||||
<div class="auto-form-wrapper">
|
||||
<div class="text-center">
|
||||
<img src="/static/assets/images/logo_long.svg"><br /><br />
|
||||
<div class="col-sm-12 grid-margin stretch-card">
|
||||
<div class="card card-statistics social-card google-card card-colored">
|
||||
<div class="card-body">
|
||||
<h4 class="platform-name mb-3 mt-4 font-weight-semibold user-name">{{ translate('accessDenied', 'accessDenied', data['lang']) }}</h4>
|
||||
<h5 class="headline font-weight-medium">{{ translate('accessDenied', 'noAccess', data['lang']) }}</h5>
|
||||
<p class="mb-2 comment font-weight-light">
|
||||
{{ translate('accessDenied', 'contactAdmin', data['lang']) }}<br /><br />
|
||||
<a class="d-inline font-weight-medium" href="https://discord.gg/9VJPhCE"> {{ translate('accessDenied', 'contact', data['lang']) }}</a>
|
||||
</p>
|
||||
<div class="col-sm-12 grid-margin stretch-card">
|
||||
<div class="card card-statistics social-card google-card card-colored">
|
||||
<div class="card-body">
|
||||
<h4 class="platform-name mb-3 mt-4 font-weight-semibold user-name">{{ translate('accessDenied',
|
||||
'accessDenied', data['lang']) }}</h4>
|
||||
<h5 class="headline font-weight-medium">{{ translate('accessDenied', 'noAccess', data['lang']) }}
|
||||
</h5>
|
||||
<p class="mb-2 comment font-weight-light">
|
||||
{{ translate('accessDenied', 'contactAdmin', data['lang']) }}<br /><br />
|
||||
<a class="d-inline font-weight-medium" href="https://discord.gg/9VJPhCE"> {{
|
||||
translate('accessDenied', 'contact', data['lang']) }}</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!-- content-wrapper ends -->
|
||||
</div>
|
||||
<!-- page-body-wrapper ends -->
|
||||
<!-- content-wrapper ends -->
|
||||
</div>
|
||||
<!-- container-scroller -->
|
||||
<!-- plugins:js -->
|
||||
<script src="/static/assets/vendors/js/vendor.bundle.base.js"></script>
|
||||
<!-- endinject -->
|
||||
<!-- inject:js -->
|
||||
<script src="/static/assets/js/shared/off-canvas.js"></script>
|
||||
<script src="/static/assets/js/shared/hoverable-collapse.js"></script>
|
||||
<script src="/static/assets/js/shared/misc.js"></script>
|
||||
<script src="/static/assets/js/shared/settings.js"></script>
|
||||
<script src="/static/assets/js/shared/todolist.js"></script>
|
||||
<!-- endinject -->
|
||||
</body>
|
||||
<!-- page-body-wrapper ends -->
|
||||
</div>
|
||||
<!-- container-scroller -->
|
||||
<!-- plugins:js -->
|
||||
<script src="/static/assets/vendors/js/vendor.bundle.base.js"></script>
|
||||
<!-- endinject -->
|
||||
<!-- inject:js -->
|
||||
<script src="/static/assets/js/shared/off-canvas.js"></script>
|
||||
<script src="/static/assets/js/shared/hoverable-collapse.js"></script>
|
||||
<script src="/static/assets/js/shared/misc.js"></script>
|
||||
<script src="/static/assets/js/shared/settings.js"></script>
|
||||
<script src="/static/assets/js/shared/todolist.js"></script>
|
||||
<!-- endinject -->
|
||||
</body>
|
||||
|
||||
</html>
|
@ -221,73 +221,184 @@
|
||||
<h4 class="card-title"><i class="fas fa-user-tag"></i> {{ translate('panelConfig', 'adminControls',
|
||||
data['lang']) }}</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<button type="button" class="btn btn-outline-danger clear-comm">{{ translate('panelConfig',
|
||||
'clearComms', data['lang']) }}</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-6 grid-margin stretch-card">
|
||||
<div class="col-md-12 col-lg-12 grid-margin stretch-card">
|
||||
<div class="card">
|
||||
<div class="card-header header-sm d-flex justify-content-between align-items-center">
|
||||
<h4>{{ translate('panelConfig', 'customLoginPage', data['lang']) }}</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
|
||||
<h4>{{ translate('panelConfig', 'loginImage', data['lang']) }}</h4>
|
||||
<br />
|
||||
<p class="card-description">
|
||||
|
||||
<form name="zip" method="post" class="server-wizard" onSubmit="wait_msg(true)">
|
||||
{% raw xsrf_form_html() %}
|
||||
<input type="hidden" value="import_zip" name="create_type">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
|
||||
<div class="col-sm-12">
|
||||
<div class="form-group">
|
||||
<label for="server">{{ translate('panelConfig', 'backgroundUpload', data['lang'])
|
||||
}}</label><br>
|
||||
<span id="upload_input">
|
||||
<input type="file" multiple="false" class="form-control" id="file" name="file" required
|
||||
style="width: 70%;">
|
||||
<button type="button" class="btn btn-info" id="upload-button" onclick="sendFile()"
|
||||
disabled>UPLOAD</button>
|
||||
</span>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-6">
|
||||
<h4>{{ translate('panelConfig', 'loginImage', data['lang']) }}</h4>
|
||||
<hr>
|
||||
<form class="form-row" name="zip" method="post" class="server-wizard" onSubmit="wait_msg(true)">
|
||||
{% raw xsrf_form_html() %}
|
||||
<input type="hidden" value="import_zip" name="create_type">
|
||||
<div class="col form-group">
|
||||
<span id="upload_input"><input type="file" class="form-control-file" id="file" name="file"
|
||||
multiple="false" required></span>
|
||||
</div>
|
||||
<div class="col form-group">
|
||||
<button type="button" class="btn btn-info" id="upload-button" onclick="sendFile()"
|
||||
disabled>UPLOAD</button>
|
||||
</div>
|
||||
</form>
|
||||
<hr>
|
||||
<hr />
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div>
|
||||
<h6>{{ translate('panelConfig', 'preview', data['lang']) }}:</h6>
|
||||
<form id="photo_form">
|
||||
<div class="form-group row">
|
||||
<label for="photo" class="col-sm-6 col-form-label">Selected Background Image</label>
|
||||
<div class="col-sm-6">
|
||||
<select class="form-select form-control form-control-lg select-css form-control-plaintext"
|
||||
id="photo" name="photo" form="photo_form" onchange="updateBackgroundPreview()">
|
||||
{% for image in data["backgrounds"] %}
|
||||
<option value="{{image}}">{{image}}</option>
|
||||
{% end %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div id="photo_loading" class="form-group" hidden>
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar"
|
||||
aria-valuenow="100" aria-valuemin="0" aria-valuemax="100" style="width: 100%"> <i
|
||||
class="fa-solid fa-spinner"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-3" for="formControlRange">{{ translate('panelConfig', 'loginOpacity',
|
||||
data['lang']) }}</label>
|
||||
<label class="col-sm-1" id="opacityValue">{{ data['login_opacity'] }}%</label>
|
||||
<div class="range col-sm-8">
|
||||
<input type="range" class="form-control-range" id="modal_opacity" name="modal_opacity"
|
||||
onchange="previewOpacity()" min="0" max="100" value="{{ data['login_opacity'] }}">
|
||||
</div>
|
||||
</div>
|
||||
<div id="login_preview" style="position: relative;">
|
||||
<img id="bg-preview" src="../../static/assets/images/auth/{{ data['background'] }}"
|
||||
class="img-fluid" alt="Responsive image">
|
||||
<div id="login-form-preview">
|
||||
<div id="login-form-background" class="auto-form-wrapper login-modal">
|
||||
<div class="text-center auto-form-logo">
|
||||
<img src="/static/assets/images/logo_long.svg">
|
||||
</div>
|
||||
<style>
|
||||
#login-form-preview {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%) translateY(-50%);
|
||||
max-width: 90%;
|
||||
max-height: 90%;
|
||||
}
|
||||
|
||||
.auto-form-wrapper {
|
||||
background: rgb(34, 36, 55, 1);
|
||||
padding: 2rem 2rem 0.5rem;
|
||||
border-radius: 4px;
|
||||
-webkit-box-shadow: 0 -25px 37.7px 11.3px rgb(8 143 220 / 7%);
|
||||
box-shadow: 0 -25px 37.7px 11.3px rgb(8 143 220 / 7%);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/*.auto-form-logo {
|
||||
background: #222437;
|
||||
padding: 0rem;
|
||||
margin: 0.5rem 0rem;
|
||||
border-radius: 0.2rem;
|
||||
color: #fff;
|
||||
}*/
|
||||
|
||||
.login-modal {
|
||||
border-radius: 0.4rem !important;
|
||||
box-shadow: 0 8px 12px 0 hsla(0, 0%, 0%, 0.2) !important;
|
||||
}
|
||||
|
||||
.login-text-input {
|
||||
border: none !important;
|
||||
background-color: hsl(234, 30%, 45%);
|
||||
color: var(--white) !important;
|
||||
}
|
||||
|
||||
.login-text-input:hover,
|
||||
.login-text-input:focus {
|
||||
background-color: hsl(234, 30%, 39%) !important;
|
||||
}
|
||||
|
||||
.login-input {
|
||||
border-radius: 0.4rem !important;
|
||||
box-shadow: 0 8px 12px 0 hsla(0, 0%, 0%, 0.2);
|
||||
transition: all 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
.login-input:hover,
|
||||
.login-input:focus {
|
||||
box-shadow: 0 12px 16px 0 hsla(0, 0%, 0%, 0.4);
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="login_form_data">
|
||||
<input type="hidden" name="_xsrf"
|
||||
value="2|1d603267|809fb6bd82f677d440e484dde7c3a310|1671726040" disabled>
|
||||
<div class="form-group">
|
||||
<label class="label">Username</label>
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control login-text-input login-input"
|
||||
placeholder="Username" name="username" id="username" required="true" disabled>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="label">Password</label>
|
||||
<div class="input-group">
|
||||
<input type="password" class="form-control login-text-input login-input"
|
||||
placeholder="Password" name="password" id="password" required="true" disabled>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button class="login-input btn btn-primary submit-btn btn-block" disabled>Log
|
||||
In</button>
|
||||
</div>
|
||||
|
||||
<fieldset style="color: red; text-align: center;">
|
||||
<span></span>
|
||||
</fieldset>
|
||||
|
||||
<div class="form-group d-flex justify-content-between">
|
||||
<div class="form-check form-check-flat mt-0">
|
||||
|
||||
</div>
|
||||
<a href="#" class="text-small forgot-password" disabled>Forgot Password</a>
|
||||
</div>
|
||||
<div class="text-block text-center my-3">
|
||||
<span class="text-small font-weight-semibold"><a
|
||||
href="https://craftycontrol.com/">Crafty Control
|
||||
4.0.20</a> </span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button class="btn btn-outline-success select-photo" type="button">{{
|
||||
translate('panelConfig',
|
||||
'apply', data['lang']) }}</button>
|
||||
<button class="btn btn-outline-danger delete-photo" type="button">{{
|
||||
translate('panelConfig',
|
||||
'delete', data['lang']) }}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 grid-margin stretch-card">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h4>{{ translate('panelConfig', 'loginBackground', data['lang']) }}</h4><br /><br><br />
|
||||
<form id="photo_form">
|
||||
<select class="form-select form-control form-control-lg select-css" id="photo" name="photo"
|
||||
form="photo_form">
|
||||
{% for image in data["backgrounds"] %}
|
||||
<option value="{{image}}">{{image}}</option>
|
||||
{% end %}
|
||||
</select>
|
||||
<div>
|
||||
<br>
|
||||
<h6>{{ translate('panelConfig', 'preview', data['lang']) }}:</h6>
|
||||
<img style="width: 200px; height: 113px;"
|
||||
src="../../static/assets/images/auth/{{ data['background'] }}">
|
||||
</div>
|
||||
<br />
|
||||
<br />
|
||||
<button class="btn btn-outline-success select-photo" type="button">{{ translate('panelConfig',
|
||||
'select', data['lang']) }}</button>
|
||||
<button class="btn btn-outline-danger delete-photo" type="button">{{ translate('panelConfig',
|
||||
'delete', data['lang']) }}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -367,24 +478,13 @@
|
||||
});
|
||||
});
|
||||
|
||||
$('.clear-comm').click(function () {
|
||||
var token = getCookie("_xsrf")
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
headers: { 'X-XSRFToken': token },
|
||||
url: '/ajax/clear_comm',
|
||||
success: function (data) {
|
||||
},
|
||||
});
|
||||
})
|
||||
|
||||
$('.delete-photo').click(function () {
|
||||
var token = getCookie("_xsrf")
|
||||
let photo = $('#photo').find(":selected").val();
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
headers: { 'X-XSRFToken': token },
|
||||
url: '/ajax/delete_photo?photo=' + photo,
|
||||
url: '/ajax/delete_photo?photo=' + encodeURIComponent(photo),
|
||||
success: function (data) {
|
||||
location.reload();
|
||||
},
|
||||
@ -394,20 +494,50 @@
|
||||
$('.select-photo').click(function () {
|
||||
var token = getCookie("_xsrf")
|
||||
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=' + photo,
|
||||
url: '/ajax/select_photo?photo=' + enc_photo + '&opacity=' + opacity,
|
||||
success: function (data) {
|
||||
window.location.reload();
|
||||
},
|
||||
});
|
||||
})
|
||||
|
||||
$(document).ready(function () {
|
||||
let opacity = parseInt($("#modal_opacity").val());
|
||||
document.getElementById('login-form-background').style.background = 'rgb(34, 36, 55, ' + (opacity / 100) + ')';
|
||||
});
|
||||
|
||||
function previewOpacity() {
|
||||
let opacity = parseInt($("#modal_opacity").val())
|
||||
console.debug("Selected Opacity = " + opacity + "%");
|
||||
document.getElementById('opacityValue').innerHTML = (opacity) + "%";
|
||||
document.getElementById('login-form-background').style.background = 'rgb(34, 36, 55, ' + (opacity / 100) + ')';
|
||||
}
|
||||
|
||||
function updateBackgroundSelect() {
|
||||
$("#photo").val($("#try_photo").val()).change();
|
||||
}
|
||||
|
||||
function updateBackgroundPreview() {
|
||||
var img = document.getElementById('bg-preview');
|
||||
if ($("#photo").val() == "login_1.jpg") {
|
||||
var src_path = "../../static/assets/images/auth/".concat($("#photo").val());
|
||||
}
|
||||
else {
|
||||
var src_path = "../../static/assets/images/auth/custom/".concat($("#photo").val());
|
||||
}
|
||||
img.src = src_path;
|
||||
}
|
||||
|
||||
var file;
|
||||
function sendFile() {
|
||||
file = $("#file")[0].files[0]
|
||||
document.getElementById("upload_input").innerHTML = '<div class="progress"><div class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100" style="width: 100%"> <i class="fa-solid fa-spinner"></i></div></div>'
|
||||
document.getElementById("upload_input").innerHTML = '<div class="progress"><div class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100" style="width: 100%"> <i class="fa-solid fa-spinner"></i></div></div>';
|
||||
let xmlHttpRequest = new XMLHttpRequest();
|
||||
let token = getCookie("_xsrf")
|
||||
let fileName = file.name
|
||||
|
@ -23,7 +23,7 @@
|
||||
</head>
|
||||
<style>
|
||||
.auth.auth-bg-1 {
|
||||
background: url("../../static/assets/images/auth/{{data['background']}}"),
|
||||
background: url("../../static/assets/images/auth/{% raw data['background'] %}"),
|
||||
url("../../static/assets/images/auth/login-1.jpg");
|
||||
background-size: cover;
|
||||
}
|
||||
|
@ -23,7 +23,7 @@
|
||||
</head>
|
||||
<style>
|
||||
.auth.auth-bg-1 {
|
||||
background: url("../../static/assets/images/auth/{{data['background']}}"),
|
||||
background: url("../../static/assets/images/auth/{% raw data['background'] %}"),
|
||||
url("../../static/assets/images/auth/login-1.jpg");
|
||||
background-size: cover;
|
||||
}
|
||||
|
@ -23,9 +23,10 @@
|
||||
</head>
|
||||
<style>
|
||||
.auth.auth-bg-1 {
|
||||
background: url("../../static/assets/images/auth/{{data['background']}}"),
|
||||
background: url("../../static/assets/images/auth/{% raw data['background'] %}"),
|
||||
url("../../static/assets/images/auth/login-1.jpg");
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -36,8 +37,9 @@
|
||||
<div class="row w-100">
|
||||
<div class="col-lg-4 mx-auto">
|
||||
|
||||
<div class="auto-form-wrapper login-modal">
|
||||
<div class="text-center">
|
||||
<div id="login-form-background" class="auto-form-wrapper login-modal">
|
||||
<div id="login_opacity" data-value="{{ data['login_opacity'] }}" hidden></div>
|
||||
<div class="text-center auto-form-logo">
|
||||
<img src="/static/assets/images/logo_long.svg">
|
||||
</div>
|
||||
<style>
|
||||
@ -133,6 +135,13 @@
|
||||
<script src="/static/assets/js/shared/settings.js"></script>
|
||||
<script src="/static/assets/js/shared/todolist.js"></script>
|
||||
<!-- endinject -->
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
let login_opacity_div = document.getElementById('login_opacity');
|
||||
let opacity = login_opacity_div.getAttribute('data-value');
|
||||
document.getElementById('login-form-background').style.background = 'rgb(34, 36, 55, ' + (opacity / 100) + ')';
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -9,7 +9,7 @@
|
||||
<!-- View for Large screen -->
|
||||
<style>
|
||||
.auth.auth-bg-1 {
|
||||
background: url("../../static/assets/images/auth/{{data['background']}}"),
|
||||
background: url("../../static/assets/images/auth/{% raw data['background'] %}"),
|
||||
url("../../static/assets/images/auth/login-1.jpg");
|
||||
background-size: cover;
|
||||
}
|
||||
|
18
app/migrations/20230111_adding_login_opacity.py
Normal file
18
app/migrations/20230111_adding_login_opacity.py
Normal file
@ -0,0 +1,18 @@
|
||||
# Generated by database migrator
|
||||
import peewee
|
||||
|
||||
|
||||
def migrate(migrator, database, **kwargs):
|
||||
migrator.add_columns(
|
||||
"crafty_settings", login_opacity=peewee.IntegerField(default=100)
|
||||
)
|
||||
"""
|
||||
Write your migrations here.
|
||||
"""
|
||||
|
||||
|
||||
def rollback(migrator, database, **kwargs):
|
||||
migrator.drop_columns("crafty_settings", ["login_opacity"])
|
||||
"""
|
||||
Write your rollback migrations here.
|
||||
"""
|
35
app/migrations/20230119_command_drop.py
Normal file
35
app/migrations/20230119_command_drop.py
Normal file
@ -0,0 +1,35 @@
|
||||
# Generated by database migrator
|
||||
import datetime
|
||||
from peewee import *
|
||||
from app.classes.models.users import Users
|
||||
from app.classes.models.servers import Servers
|
||||
|
||||
|
||||
def migrate(migrator, database, **kwargs):
|
||||
migrator.drop_table("commands")
|
||||
"""
|
||||
Write your migrations here.
|
||||
"""
|
||||
|
||||
|
||||
def rollback(migrator, database, **kwargs):
|
||||
db = database
|
||||
|
||||
class Commands(Model):
|
||||
command_id = AutoField()
|
||||
created = DateTimeField(default=datetime.datetime.now)
|
||||
server_id = ForeignKeyField(Servers, backref="server", index=True)
|
||||
user = ForeignKeyField(Users, backref="user", index=True)
|
||||
source_ip = CharField(default="127.0.0.1")
|
||||
command = CharField(default="")
|
||||
executed = BooleanField(default=False)
|
||||
|
||||
class Meta:
|
||||
table_name = "commands"
|
||||
database = db
|
||||
|
||||
migrator.create_table(Commands)
|
||||
|
||||
"""
|
||||
Write your rollback migrations here.
|
||||
"""
|
@ -228,10 +228,13 @@
|
||||
"superConfirmTitle": "Enable superuser? Are you sure?",
|
||||
"user": "User",
|
||||
"users": "Users",
|
||||
"customLoginPage": "Customise the Login Page",
|
||||
"loginImage": "Upload a background image for the login screen.",
|
||||
"backgroundUpload": "Background Upload",
|
||||
"loginBackground": "Login Background Image",
|
||||
"loginOpacity": "Select the Login Window Opacity",
|
||||
"select": "Select",
|
||||
"apply": "Apply",
|
||||
"selectImage": "Select an image",
|
||||
"preview": "Preview"
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user