mirror of
https://github.com/partitioncloud/partitioncloud-server.git
synced 2025-02-03 18:53:42 +01:00
Compare commits
No commits in common. "2ff7a515d58e504e9bb56da22e9e4629509b48f3" and "5a7c3ed09d3fb30a12243e18362850ff62fc37ed" have entirely different histories.
2ff7a515d5
...
5a7c3ed09d
@ -24,6 +24,3 @@ MAX_AGE=31
|
|||||||
# Keep in mind that this config option can only be loaded from default_config.py,
|
# Keep in mind that this config option can only be loaded from default_config.py,
|
||||||
# as the custom config is stored in $INSTANCE_PATH/
|
# as the custom config is stored in $INSTANCE_PATH/
|
||||||
INSTANCE_PATH="instance"
|
INSTANCE_PATH="instance"
|
||||||
|
|
||||||
# Events to log
|
|
||||||
ENABLED_LOGS=["NEW_GROUPE", "NEW_ALBUM", "NEW_PARTITION", "NEW_USER", "SERVER_RESTART", "FAILED_LOGIN"]
|
|
@ -12,7 +12,7 @@ from flask import Flask, g, redirect, render_template, request, send_file, flash
|
|||||||
from werkzeug.security import generate_password_hash
|
from werkzeug.security import generate_password_hash
|
||||||
|
|
||||||
from .modules.utils import User, Album, get_all_albums
|
from .modules.utils import User, Album, get_all_albums
|
||||||
from .modules import albums, auth, partition, admin, groupe, thumbnails, logging
|
from .modules import albums, auth, partition, admin, groupe, thumbnails
|
||||||
from .modules.auth import admin_required, login_required
|
from .modules.auth import admin_required, login_required
|
||||||
from .modules.db import get_db
|
from .modules.db import get_db
|
||||||
|
|
||||||
@ -33,11 +33,6 @@ def load_config():
|
|||||||
".",
|
".",
|
||||||
os.path.join(app.instance_path, "config.py")
|
os.path.join(app.instance_path, "config.py")
|
||||||
)
|
)
|
||||||
|
|
||||||
if spec is None:
|
|
||||||
print("[ERROR] Failed to load $INSTANCE_PATH/config.py")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
user_config = importlib.util.module_from_spec(spec)
|
user_config = importlib.util.module_from_spec(spec)
|
||||||
spec.loader.exec_module(user_config)
|
spec.loader.exec_module(user_config)
|
||||||
|
|
||||||
@ -56,18 +51,6 @@ def load_config():
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def setup_logging():
|
|
||||||
logging.log_file = os.path.join(app.instance_path, "logs.txt")
|
|
||||||
enabled = []
|
|
||||||
for event in app.config["ENABLED_LOGS"]:
|
|
||||||
try:
|
|
||||||
enabled.append(logging.LogEntry.from_string(event))
|
|
||||||
except KeyError:
|
|
||||||
print(f"[ERROR] There is an error in your config: Unknown event {event}")
|
|
||||||
|
|
||||||
logging.enabled = enabled
|
|
||||||
|
|
||||||
|
|
||||||
def get_version():
|
def get_version():
|
||||||
try:
|
try:
|
||||||
result = subprocess.run(["git", "describe", "--tags"], stdout=subprocess.PIPE, check=True)
|
result = subprocess.run(["git", "describe", "--tags"], stdout=subprocess.PIPE, check=True)
|
||||||
@ -78,7 +61,6 @@ def get_version():
|
|||||||
|
|
||||||
|
|
||||||
load_config()
|
load_config()
|
||||||
setup_logging()
|
|
||||||
|
|
||||||
app.register_blueprint(auth.bp)
|
app.register_blueprint(auth.bp)
|
||||||
app.register_blueprint(admin.bp)
|
app.register_blueprint(admin.bp)
|
||||||
@ -89,8 +71,6 @@ app.register_blueprint(thumbnails.bp)
|
|||||||
|
|
||||||
__version__ = get_version()
|
__version__ = get_version()
|
||||||
|
|
||||||
logging.log([], logging.LogEntry.SERVER_RESTART)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route("/")
|
@app.route("/")
|
||||||
def home():
|
def home():
|
||||||
@ -116,12 +96,6 @@ def add_user():
|
|||||||
if error is None:
|
if error is None:
|
||||||
# Success, go to the login page.
|
# Success, go to the login page.
|
||||||
user = User(name=username)
|
user = User(name=username)
|
||||||
|
|
||||||
logging.log(
|
|
||||||
[user.username, user.id, True, current_user.username],
|
|
||||||
logging.LogEntry.NEW_USER
|
|
||||||
)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if album_uuid != "":
|
if album_uuid != "":
|
||||||
user.join_album(album_uuid)
|
user.join_album(album_uuid)
|
||||||
|
@ -2,8 +2,7 @@
|
|||||||
"""
|
"""
|
||||||
Admin Panel
|
Admin Panel
|
||||||
"""
|
"""
|
||||||
import os
|
from flask import Blueprint, render_template, session
|
||||||
from flask import Blueprint, render_template, session, current_app, send_file
|
|
||||||
|
|
||||||
from .db import get_db
|
from .db import get_db
|
||||||
from .auth import admin_required
|
from .auth import admin_required
|
||||||
@ -36,28 +35,3 @@ def index():
|
|||||||
users=users,
|
users=users,
|
||||||
user=current_user
|
user=current_user
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/logs")
|
|
||||||
@admin_required
|
|
||||||
def logs():
|
|
||||||
"""
|
|
||||||
Admin panel logs page
|
|
||||||
"""
|
|
||||||
user = User(user_id=session.get("user_id"))
|
|
||||||
|
|
||||||
return render_template(
|
|
||||||
"admin/logs.html",
|
|
||||||
user=user
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/logs.txt")
|
|
||||||
@admin_required
|
|
||||||
def logs_txt():
|
|
||||||
"""
|
|
||||||
Admin panel logs page
|
|
||||||
"""
|
|
||||||
return send_file(
|
|
||||||
os.path.join(current_app.instance_path, "logs.txt")
|
|
||||||
)
|
|
||||||
|
@ -13,7 +13,7 @@ from flask import (Blueprint, abort, flash, redirect, render_template,
|
|||||||
from .auth import login_required
|
from .auth import login_required
|
||||||
from .db import get_db
|
from .db import get_db
|
||||||
from .utils import User, Album
|
from .utils import User, Album
|
||||||
from . import search, utils, logging
|
from . import search, utils
|
||||||
|
|
||||||
|
|
||||||
bp = Blueprint("albums", __name__, url_prefix="/albums")
|
bp = Blueprint("albums", __name__, url_prefix="/albums")
|
||||||
@ -116,8 +116,6 @@ def create_album_req():
|
|||||||
db = get_db()
|
db = get_db()
|
||||||
error = None
|
error = None
|
||||||
|
|
||||||
user = User(user_id=session["user_id"])
|
|
||||||
|
|
||||||
if not name or name.strip() == "":
|
if not name or name.strip() == "":
|
||||||
error = "Un nom est requis. L'album n'a pas été créé"
|
error = "Un nom est requis. L'album n'a pas été créé"
|
||||||
|
|
||||||
@ -133,8 +131,6 @@ def create_album_req():
|
|||||||
)
|
)
|
||||||
db.commit()
|
db.commit()
|
||||||
|
|
||||||
logging.log([album.name, album.uuid, user.username], logging.LogEntry.NEW_ALBUM)
|
|
||||||
|
|
||||||
if "response" in request.args and request.args["response"] == "json":
|
if "response" in request.args and request.args["response"] == "json":
|
||||||
return {
|
return {
|
||||||
"status": "ok",
|
"status": "ok",
|
||||||
@ -221,7 +217,7 @@ def delete_album(uuid):
|
|||||||
@login_required
|
@login_required
|
||||||
def add_partition(album_uuid):
|
def add_partition(album_uuid):
|
||||||
"""
|
"""
|
||||||
Ajouter une partition à un album (nouveau fichier)
|
Ajouter une partition à un album (par upload)
|
||||||
"""
|
"""
|
||||||
T = TypeVar("T")
|
T = TypeVar("T")
|
||||||
def get_opt_string(dictionary: dict[T, str], key: T):
|
def get_opt_string(dictionary: dict[T, str], key: T):
|
||||||
@ -269,7 +265,6 @@ def add_partition(album_uuid):
|
|||||||
author = get_opt_string(request.form, "author")
|
author = get_opt_string(request.form, "author")
|
||||||
body = get_opt_string(request.form, "body")
|
body = get_opt_string(request.form, "body")
|
||||||
|
|
||||||
partition_uuid: str
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
partition_uuid = str(uuid4())
|
partition_uuid = str(uuid4())
|
||||||
@ -312,11 +307,6 @@ def add_partition(album_uuid):
|
|||||||
except db.IntegrityError:
|
except db.IntegrityError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
logging.log(
|
|
||||||
[request.form["name"], partition_uuid, user.username],
|
|
||||||
logging.LogEntry.NEW_PARTITION
|
|
||||||
)
|
|
||||||
|
|
||||||
if "response" in request.args and request.args["response"] == "json":
|
if "response" in request.args and request.args["response"] == "json":
|
||||||
return {
|
return {
|
||||||
"status": "ok",
|
"status": "ok",
|
||||||
@ -330,7 +320,7 @@ def add_partition(album_uuid):
|
|||||||
@login_required
|
@login_required
|
||||||
def add_partition_from_search():
|
def add_partition_from_search():
|
||||||
"""
|
"""
|
||||||
Ajout d'une partition (depuis la recherche locale)
|
Ajout d'une partition (depuis la recherche)
|
||||||
"""
|
"""
|
||||||
user = User(user_id=session.get("user_id"))
|
user = User(user_id=session.get("user_id"))
|
||||||
error = None
|
error = None
|
||||||
|
@ -12,7 +12,6 @@ from werkzeug.security import check_password_hash, generate_password_hash
|
|||||||
|
|
||||||
from .db import get_db
|
from .db import get_db
|
||||||
from .utils import User
|
from .utils import User
|
||||||
from . import logging
|
|
||||||
|
|
||||||
bp = Blueprint("auth", __name__, url_prefix="/auth")
|
bp = Blueprint("auth", __name__, url_prefix="/auth")
|
||||||
|
|
||||||
@ -121,15 +120,8 @@ def register():
|
|||||||
if error is not None:
|
if error is not None:
|
||||||
flash(error)
|
flash(error)
|
||||||
else:
|
else:
|
||||||
user = User(name=username)
|
|
||||||
|
|
||||||
flash("Utilisateur créé avec succès. Vous pouvez vous connecter.")
|
flash("Utilisateur créé avec succès. Vous pouvez vous connecter.")
|
||||||
|
|
||||||
logging.log(
|
|
||||||
[user.username, user.id, False],
|
|
||||||
logging.LogEntry.NEW_USER
|
|
||||||
)
|
|
||||||
|
|
||||||
return render_template("auth/register.html")
|
return render_template("auth/register.html")
|
||||||
|
|
||||||
|
|
||||||
@ -147,16 +139,12 @@ def login():
|
|||||||
).fetchone()
|
).fetchone()
|
||||||
|
|
||||||
if (user is None) or not check_password_hash(user["password"], password):
|
if (user is None) or not check_password_hash(user["password"], password):
|
||||||
logging.log([username], logging.LogEntry.FAILED_LOGIN)
|
|
||||||
error = "Nom d'utilisateur ou mot de passe incorrect."
|
error = "Nom d'utilisateur ou mot de passe incorrect."
|
||||||
|
|
||||||
if error is None:
|
if error is None:
|
||||||
# store the user id in a new session and return to the index
|
# store the user id in a new session and return to the index
|
||||||
session.clear()
|
session.clear()
|
||||||
session["user_id"] = user["id"]
|
session["user_id"] = user["id"]
|
||||||
|
|
||||||
logging.log([username], logging.LogEntry.LOGIN)
|
|
||||||
|
|
||||||
return redirect(url_for("albums.index"))
|
return redirect(url_for("albums.index"))
|
||||||
|
|
||||||
flash(error)
|
flash(error)
|
||||||
|
@ -9,7 +9,6 @@ from .auth import login_required
|
|||||||
from .db import get_db
|
from .db import get_db
|
||||||
from .utils import User, Album, Groupe
|
from .utils import User, Album, Groupe
|
||||||
from . import utils
|
from . import utils
|
||||||
from . import logging
|
|
||||||
|
|
||||||
bp = Blueprint("groupe", __name__, url_prefix="/groupe")
|
bp = Blueprint("groupe", __name__, url_prefix="/groupe")
|
||||||
|
|
||||||
@ -64,8 +63,6 @@ def create_groupe():
|
|||||||
db = get_db()
|
db = get_db()
|
||||||
error = None
|
error = None
|
||||||
|
|
||||||
user = User(user_id=session["user_id"])
|
|
||||||
|
|
||||||
if not name or name.strip() == "":
|
if not name or name.strip() == "":
|
||||||
error = "Un nom est requis. Le groupe n'a pas été créé"
|
error = "Un nom est requis. Le groupe n'a pas été créé"
|
||||||
|
|
||||||
@ -96,8 +93,6 @@ def create_groupe():
|
|||||||
except db.IntegrityError:
|
except db.IntegrityError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
logging.log([name, uuid, user.username], logging.LogEntry.NEW_GROUPE)
|
|
||||||
|
|
||||||
if "response" in request.args and request.args["response"] == "json":
|
if "response" in request.args and request.args["response"] == "json":
|
||||||
return {
|
return {
|
||||||
"status": "ok",
|
"status": "ok",
|
||||||
@ -199,8 +194,6 @@ def create_album_req(groupe_uuid):
|
|||||||
)
|
)
|
||||||
db.commit()
|
db.commit()
|
||||||
|
|
||||||
logging.log([album.name, album.uuid, user.username], logging.LogEntry.NEW_ALBUM)
|
|
||||||
|
|
||||||
if "response" in request.args and request.args["response"] == "json":
|
if "response" in request.args and request.args["response"] == "json":
|
||||||
return {
|
return {
|
||||||
"status": "ok",
|
"status": "ok",
|
||||||
|
@ -1,74 +0,0 @@
|
|||||||
from datetime import datetime
|
|
||||||
from typing import Union
|
|
||||||
from enum import Enum
|
|
||||||
|
|
||||||
global log_file
|
|
||||||
global enabled
|
|
||||||
|
|
||||||
|
|
||||||
class LogEntry(Enum):
|
|
||||||
LOGIN = 1
|
|
||||||
NEW_GROUPE = 2
|
|
||||||
NEW_ALBUM = 3
|
|
||||||
NEW_PARTITION = 4
|
|
||||||
NEW_USER = 5
|
|
||||||
SERVER_RESTART = 6
|
|
||||||
FAILED_LOGIN = 7
|
|
||||||
|
|
||||||
def from_string(entry: str):
|
|
||||||
mapping = {
|
|
||||||
"LOGIN": LogEntry.LOGIN,
|
|
||||||
"NEW_GROUPE": LogEntry.NEW_GROUPE,
|
|
||||||
"NEW_ALBUM": LogEntry.NEW_ALBUM,
|
|
||||||
"NEW_PARTITION": LogEntry.NEW_PARTITION,
|
|
||||||
"NEW_USER": LogEntry.NEW_USER,
|
|
||||||
"SERVER_RESTART": LogEntry.SERVER_RESTART,
|
|
||||||
"FAILED_LOGIN": LogEntry.FAILED_LOGIN
|
|
||||||
}
|
|
||||||
# Will return KeyError if not available
|
|
||||||
return mapping[entry]
|
|
||||||
|
|
||||||
|
|
||||||
def add_entry(entry: str) -> None:
|
|
||||||
date = datetime.now().strftime("%y-%b-%Y %H:%M:%S")
|
|
||||||
|
|
||||||
with open(log_file, 'a', encoding="utf8") as f:
|
|
||||||
f.write(f"[{date}] {entry}\n")
|
|
||||||
|
|
||||||
|
|
||||||
def log(content: list[Union[str, bool, int]], log_type: LogEntry) -> None:
|
|
||||||
description: str = ""
|
|
||||||
|
|
||||||
if log_type not in enabled:
|
|
||||||
return
|
|
||||||
|
|
||||||
match log_type:
|
|
||||||
case LogEntry.LOGIN: # content = (user.name)
|
|
||||||
description = f"Successful login for {content[0]}"
|
|
||||||
|
|
||||||
case LogEntry.NEW_GROUPE: # content = (groupe.name, groupe.id, user.name)
|
|
||||||
description = f"{content[2]} added groupe '{content[0]}' ({content[1]})"
|
|
||||||
|
|
||||||
case LogEntry.NEW_ALBUM: # content = (album.name, album.id, user.name)
|
|
||||||
description = f"{content[2]} added album '{content[0]}' ({content[1]})"
|
|
||||||
|
|
||||||
case LogEntry.NEW_PARTITION: # content = (partition.name, partition.uuid, user.name)
|
|
||||||
description = f"{content[2]} added partition '{content[0]}' ({content[1]})"
|
|
||||||
|
|
||||||
case LogEntry.NEW_USER: # content = (user.name, user.id, from_register_page, admin.name if relevant)
|
|
||||||
if not content[2]:
|
|
||||||
description = f"New user {content[0]}[{content[1]}]"
|
|
||||||
else:
|
|
||||||
description = f"New user {content[0]}[{content[1]}] added by {content[3]}"
|
|
||||||
|
|
||||||
case LogEntry.SERVER_RESTART: # content = ()
|
|
||||||
description = "Server just restarted"
|
|
||||||
|
|
||||||
case LogEntry.FAILED_LOGIN: # content = (user.name)
|
|
||||||
description = f"Failed login for {content[0]}"
|
|
||||||
|
|
||||||
add_entry(description)
|
|
||||||
|
|
||||||
|
|
||||||
log_file = "logs.txt"
|
|
||||||
enabled = [i for i in LogEntry]
|
|
@ -1,20 +0,0 @@
|
|||||||
let logsEmbed = document.getElementById("logs-embed");
|
|
||||||
|
|
||||||
logsEmbed.addEventListener("load", () => {
|
|
||||||
var cssLink = document.createElement("link");
|
|
||||||
|
|
||||||
cssLink.href = "/static/style/logs.css";
|
|
||||||
cssLink.rel = "stylesheet";
|
|
||||||
cssLink.type = "text/css";
|
|
||||||
|
|
||||||
// add css
|
|
||||||
logsEmbed.contentDocument.head.appendChild(cssLink);
|
|
||||||
|
|
||||||
// Scroll to bottom
|
|
||||||
logsEmbed.contentWindow.scrollTo(0, logsEmbed.contentDocument.body.scrollHeight);
|
|
||||||
});
|
|
||||||
|
|
||||||
// check if the iframe is already loaded (happened with FF Android)
|
|
||||||
if (logsEmbed.contentDocument.readyState == "complete") {
|
|
||||||
logsEmbed.dispatchEvent(new Event("load"));
|
|
||||||
}
|
|
@ -1,7 +1,75 @@
|
|||||||
@import url('/static/style/colors.css');
|
|
||||||
/** @import url('https://www.augustin64.fr/static/font/iosevka.css'); */
|
/** @import url('https://www.augustin64.fr/static/font/iosevka.css'); */
|
||||||
|
|
||||||
|
|
||||||
|
/** Color Schemes */
|
||||||
|
/* Themes used: Catppuccin Latte & Moccha
|
||||||
|
* https://github.com/catppuccin/catppuccin */
|
||||||
|
|
||||||
|
/* Dark theme: Catpuccin Mocha */
|
||||||
|
:root {
|
||||||
|
--color-rosewater: #f5e0dc;
|
||||||
|
--color-flamingo: #f2cdcd;
|
||||||
|
--color-pink: #f5c2e7;
|
||||||
|
--color-mauve: #cba6f7;
|
||||||
|
--color-red: #f38ba8;
|
||||||
|
--color-maroon: #eba0ac;
|
||||||
|
--color-peach: #fab387;
|
||||||
|
--color-yellow: #f9e2af;
|
||||||
|
--color-green: #a6e3a1;
|
||||||
|
--color-teal: #94e2d5;
|
||||||
|
--color-sky: #89dceb;
|
||||||
|
--color-sapphire: #74c7ec;
|
||||||
|
--color-blue: #89b4fa;
|
||||||
|
--color-lavender: #b4befe;
|
||||||
|
--color-text: #cdd6f4;
|
||||||
|
--color-subtext1: #bac2de;
|
||||||
|
--color-subtext0: #a6adc8;
|
||||||
|
--color-overlay2: #9399b2;
|
||||||
|
--color-overlay1: #7f849c;
|
||||||
|
--color-overlay0: #6c7086;
|
||||||
|
--color-surface2: #585b70;
|
||||||
|
--color-surface1: #45475a;
|
||||||
|
--color-surface0: #313244;
|
||||||
|
--color-base: #1e1e2e;
|
||||||
|
--color-mantle: #181825;
|
||||||
|
--color-crust: #11111b;
|
||||||
|
|
||||||
|
/* --font-family: Iosevka Web; /* Specify the font here */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Light theme: Catppuccin Latte */
|
||||||
|
@media (prefers-color-scheme: light) {
|
||||||
|
:root {
|
||||||
|
--color-rosewater: #dc8a78;
|
||||||
|
--color-flamingo: #dd7878;
|
||||||
|
--color-pink: #ea76cb;
|
||||||
|
--color-mauve: #8839ef;
|
||||||
|
--color-red: #d20f39;
|
||||||
|
--color-maroon: #e64553;
|
||||||
|
--color-peach: #fe640b;
|
||||||
|
--color-yellow: #df8e1d;
|
||||||
|
--color-green: #40a02b;
|
||||||
|
--color-teal: #179299;
|
||||||
|
--color-sky: #04a5e5;
|
||||||
|
--color-sapphire: #209fb5;
|
||||||
|
--color-blue: #1e66f5;
|
||||||
|
--color-lavender: #7287fd;
|
||||||
|
--color-text: #4c4f69;
|
||||||
|
--color-subtext1: #5c5f77;
|
||||||
|
--color-subtext0: #6c6f85;
|
||||||
|
--color-overlay2: #7c7f93;
|
||||||
|
--color-overlay1: #8c8fa1;
|
||||||
|
--color-overlay0: #9ca0b0;
|
||||||
|
--color-surface2: #acb0be;
|
||||||
|
--color-surface1: #bcc0cc;
|
||||||
|
--color-surface0: #ccd0da;
|
||||||
|
--color-base: #eff1f5;
|
||||||
|
--color-mantle: #e6e9ef;
|
||||||
|
--color-crust: #dce0e8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Various settings (variables) */
|
/** Various settings (variables) */
|
||||||
:root {
|
:root {
|
||||||
--sidebar-size: max(10vw, 160px);
|
--sidebar-size: max(10vw, 160px);
|
||||||
@ -705,12 +773,3 @@ midi-player {
|
|||||||
margin-bottom: 100px;
|
margin-bottom: 100px;
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#logs-embed {
|
|
||||||
margin: auto;
|
|
||||||
height: 80vh;
|
|
||||||
width: 95%;
|
|
||||||
padding: 5px;
|
|
||||||
border-radius: 5px;
|
|
||||||
background-color: var(--color-crust);
|
|
||||||
}
|
|
@ -1,65 +0,0 @@
|
|||||||
/** Color Schemes */
|
|
||||||
/* Themes used: Catppuccin Latte & Moccha
|
|
||||||
* https://github.com/catppuccin/catppuccin */
|
|
||||||
|
|
||||||
/* Dark theme: Catpuccin Mocha */
|
|
||||||
:root {
|
|
||||||
--color-rosewater: #f5e0dc;
|
|
||||||
--color-flamingo: #f2cdcd;
|
|
||||||
--color-pink: #f5c2e7;
|
|
||||||
--color-mauve: #cba6f7;
|
|
||||||
--color-red: #f38ba8;
|
|
||||||
--color-maroon: #eba0ac;
|
|
||||||
--color-peach: #fab387;
|
|
||||||
--color-yellow: #f9e2af;
|
|
||||||
--color-green: #a6e3a1;
|
|
||||||
--color-teal: #94e2d5;
|
|
||||||
--color-sky: #89dceb;
|
|
||||||
--color-sapphire: #74c7ec;
|
|
||||||
--color-blue: #89b4fa;
|
|
||||||
--color-lavender: #b4befe;
|
|
||||||
--color-text: #cdd6f4;
|
|
||||||
--color-subtext1: #bac2de;
|
|
||||||
--color-subtext0: #a6adc8;
|
|
||||||
--color-overlay2: #9399b2;
|
|
||||||
--color-overlay1: #7f849c;
|
|
||||||
--color-overlay0: #6c7086;
|
|
||||||
--color-surface2: #585b70;
|
|
||||||
--color-surface1: #45475a;
|
|
||||||
--color-surface0: #313244;
|
|
||||||
--color-base: #1e1e2e;
|
|
||||||
--color-mantle: #181825;
|
|
||||||
--color-crust: #11111b;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Light theme: Catppuccin Latte */
|
|
||||||
@media (prefers-color-scheme: light) {
|
|
||||||
:root {
|
|
||||||
--color-rosewater: #dc8a78;
|
|
||||||
--color-flamingo: #dd7878;
|
|
||||||
--color-pink: #ea76cb;
|
|
||||||
--color-mauve: #8839ef;
|
|
||||||
--color-red: #d20f39;
|
|
||||||
--color-maroon: #e64553;
|
|
||||||
--color-peach: #fe640b;
|
|
||||||
--color-yellow: #df8e1d;
|
|
||||||
--color-green: #40a02b;
|
|
||||||
--color-teal: #179299;
|
|
||||||
--color-sky: #04a5e5;
|
|
||||||
--color-sapphire: #209fb5;
|
|
||||||
--color-blue: #1e66f5;
|
|
||||||
--color-lavender: #7287fd;
|
|
||||||
--color-text: #4c4f69;
|
|
||||||
--color-subtext1: #5c5f77;
|
|
||||||
--color-subtext0: #6c6f85;
|
|
||||||
--color-overlay2: #7c7f93;
|
|
||||||
--color-overlay1: #8c8fa1;
|
|
||||||
--color-overlay0: #9ca0b0;
|
|
||||||
--color-surface2: #acb0be;
|
|
||||||
--color-surface1: #bcc0cc;
|
|
||||||
--color-surface0: #ccd0da;
|
|
||||||
--color-base: #eff1f5;
|
|
||||||
--color-mantle: #e6e9ef;
|
|
||||||
--color-crust: #dce0e8;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
@import url('/static/style/colors.css');
|
|
||||||
|
|
||||||
body {
|
|
||||||
background-color: var(--color-crust);
|
|
||||||
color: var(--color-text);
|
|
||||||
}
|
|
||||||
|
|
||||||
pre {
|
|
||||||
white-space: pre;
|
|
||||||
}
|
|
@ -6,13 +6,10 @@
|
|||||||
|
|
||||||
<div id="actions-rapides">
|
<div id="actions-rapides">
|
||||||
<a href="/add-user">
|
<a href="/add-user">
|
||||||
<div class="button">Nouvel utilisateur</div>
|
<div class="button">Ajouter un utilisateur</div>
|
||||||
</a>
|
</a>
|
||||||
<a href="/partition">
|
<a href="/partition">
|
||||||
<div class="button">Voir les partitions</div>
|
<div class="button">Voir toutes les partitions</div>
|
||||||
</a>
|
|
||||||
<a href="/admin/logs">
|
|
||||||
<div class="button">Voir les logs</div>
|
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="x-scrollable">
|
<div class="x-scrollable">
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
{% set scripts=["scripts/logs.js"] %}
|
|
||||||
{% extends 'base.html' %}
|
|
||||||
|
|
||||||
{% block header %}
|
|
||||||
<h1>{% block title %}Logs{% endblock %}</h1>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<iframe type="text/plain" id="logs-embed" src="/admin/logs.txt" frameborder="0" width="100%" height="100%"></iframe>
|
|
||||||
{% endblock %}
|
|
@ -5,8 +5,8 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
|
||||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||||
<title>{% block title %}{% endblock %} - PartitionCloud</title>
|
<title>{% block title %}{% endblock %} - PartitionCloud</title>
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='style/style.css') }}">
|
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='style/mobile.css') }}">
|
<link rel="stylesheet" href="{{ url_for('static', filename='mobile.css') }}">
|
||||||
<link rel="icon" type="image/png" href="{{ url_for('static', filename='icons/512.png') }}" />
|
<link rel="icon" type="image/png" href="{{ url_for('static', filename='icons/512.png') }}" />
|
||||||
<link rel="apple-touch-icon" href="{{ url_for('static', filename='icons/512.png') }}">
|
<link rel="apple-touch-icon" href="{{ url_for('static', filename='icons/512.png') }}">
|
||||||
<link rel="manifest" href="{{ url_for('static', filename='manifest.webmanifest') }}" />
|
<link rel="manifest" href="{{ url_for('static', filename='manifest.webmanifest') }}" />
|
||||||
@ -185,8 +185,5 @@
|
|||||||
<div id="footer"><a href="https://github.com/partitioncloud/partitioncloud-server">PartitionCloud</a> {{ version }}</div>
|
<div id="footer"><a href="https://github.com/partitioncloud/partitioncloud-server">PartitionCloud</a> {{ version }}</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
<script src="{{ url_for('static', filename='scripts/main.js') }}"></script>
|
<script src="{{ url_for('static', filename='main.js') }}"></script>
|
||||||
{% for script in scripts %}
|
|
||||||
<script src="{{ url_for('static', filename=script) }}"></script>
|
|
||||||
{% endfor %}
|
|
||||||
</html>
|
</html>
|
Loading…
x
Reference in New Issue
Block a user