mirror of
https://github.com/partitioncloud/partitioncloud-server.git
synced 2025-01-23 09:16:25 +01:00
Move all instance files to instance directory
Still to move: thumbnails
This commit is contained in:
parent
f43b1e1090
commit
6f5031623c
@ -19,3 +19,8 @@ BASE_URL="http://localhost:5000"
|
||||
|
||||
# Session expiration, in days
|
||||
MAX_AGE=31
|
||||
|
||||
# Instance path ie. where are all the files + the database stored
|
||||
# Keep in mind that this config option can only be loaded from default_config.py,
|
||||
# as the custom config is stored in $INSTANCE_PATH/
|
||||
INSTANCE_PATH="instance"
|
||||
|
28
make.sh
28
make.sh
@ -1,25 +1,27 @@
|
||||
#!/bin/bash
|
||||
|
||||
init () {
|
||||
mkdir -p "instance"
|
||||
mkdir -p "partitioncloud/partitions"
|
||||
mkdir -p "partitioncloud/attachments"
|
||||
mkdir -p "partitioncloud/search-partitions"
|
||||
mkdir -p "partitioncloud/static/thumbnails"
|
||||
mkdir -p "partitioncloud/static/search-thumbnails"
|
||||
INSTANCE_PATH="instance"
|
||||
|
||||
if ! test -f "instance/config.py"; then
|
||||
echo "SECRET_KEY=$(python3 -c 'import secrets; print(secrets.token_hex())')" > instance/config.py
|
||||
init () {
|
||||
mkdir -p "$INSTANCE_PATH"
|
||||
mkdir -p "$INSTANCE_PATH/partitions"
|
||||
mkdir -p "$INSTANCE_PATH/attachments"
|
||||
mkdir -p "$INSTANCE_PATH/search-partitions"
|
||||
mkdir -p "$INSTANCE_PATH/static/thumbnails"
|
||||
mkdir -p "$INSTANCE_PATH/static/search-thumbnails"
|
||||
|
||||
if ! test -f "$INSTANCE_PATH/config.py"; then
|
||||
echo "SECRET_KEY=$(python3 -c 'import secrets; print(secrets.token_hex())')" > "$INSTANCE_PATH/config.py"
|
||||
fi
|
||||
|
||||
if test -f "instance/partitioncloud.sqlite"; then
|
||||
if test -f "$INSTANCE_PATH/partitioncloud.sqlite"; then
|
||||
printf "Souhaitez vous supprimer la base de données existante ? [y/n] "
|
||||
read -r CONFIRMATION
|
||||
[[ $CONFIRMATION == y ]] || exit 1
|
||||
fi
|
||||
sqlite3 "instance/partitioncloud.sqlite" '.read partitioncloud/schema.sql'
|
||||
sqlite3 "$INSTANCE_PATH/partitioncloud.sqlite" '.read partitioncloud/schema.sql'
|
||||
echo "Base de données créé"
|
||||
sqlite3 "instance/partitioncloud.sqlite" '.read partitioncloud/init.sql'
|
||||
sqlite3 "$INSTANCE_PATH/partitioncloud.sqlite" '.read partitioncloud/init.sql'
|
||||
echo "Utilisateur root:root ajouté"
|
||||
}
|
||||
|
||||
@ -43,7 +45,7 @@ usage () {
|
||||
if [[ $1 && $(type "$1") = *"is a"*"function"* || $(type "$1") == *"est une fonction"* ]]; then
|
||||
# Import config
|
||||
source "default_config.py"
|
||||
[[ ! -x instance/config.py ]] && source "instance/config.py"
|
||||
[[ ! -x" $INSTANCE_PATH/config.py" ]] && source "$INSTANCE_PATH/config.py"
|
||||
$1 ${*:2} # Call the function
|
||||
else
|
||||
usage
|
||||
|
@ -3,8 +3,10 @@
|
||||
Main file
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
import datetime
|
||||
import subprocess
|
||||
import importlib.util
|
||||
|
||||
from flask import Flask, g, redirect, render_template, request, send_file, flash, session, abort
|
||||
from werkzeug.security import generate_password_hash
|
||||
@ -16,28 +18,56 @@ from .modules.db import get_db
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
app.config.from_mapping(
|
||||
DATABASE=os.path.join(app.instance_path, f"{__name__}.sqlite"),
|
||||
)
|
||||
app.config.from_object('default_config')
|
||||
if os.path.exists("instance/config.py"):
|
||||
app.config.from_object('instance.config')
|
||||
else:
|
||||
|
||||
def load_config():
|
||||
app.config.from_object('default_config')
|
||||
app.instance_path = os.path.abspath(app.config["INSTANCE_PATH"])
|
||||
|
||||
if not os.path.exists(app.instance_path):
|
||||
print("[ERROR] Instance path does not exist. Make sure to use an existing directory.")
|
||||
sys.exit(1)
|
||||
|
||||
if os.path.exists(f"{app.instance_path}/config.py"):
|
||||
# Load module from instance_path/config.py in user_config object
|
||||
spec = importlib.util.spec_from_file_location(
|
||||
".",
|
||||
os.path.join(app.instance_path, "config.py")
|
||||
)
|
||||
user_config = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(user_config)
|
||||
|
||||
app.config.from_object(user_config)
|
||||
|
||||
if os.path.abspath(app.config["INSTANCE_PATH"]) != app.instance_path:
|
||||
print("[ERROR] Using two different instance path. \
|
||||
\nPlease modify INSTANCE_PATH only in default_config.py and remove it from $INSTANCE_PATH/config.py")
|
||||
sys.exit(1)
|
||||
else:
|
||||
print("[WARNING] Using default config")
|
||||
|
||||
app.config.from_mapping(
|
||||
DATABASE=os.path.join(app.instance_path, f"{__name__}.sqlite"),
|
||||
)
|
||||
|
||||
|
||||
def get_version():
|
||||
try:
|
||||
result = subprocess.run(["git", "describe", "--tags"], stdout=subprocess.PIPE, check=True)
|
||||
return result.stdout.decode('utf8')
|
||||
except (FileNotFoundError, subprocess.CalledProcessError):
|
||||
# In case git not found or any platform specific weird error
|
||||
return "unknown"
|
||||
|
||||
|
||||
load_config()
|
||||
|
||||
app.register_blueprint(auth.bp)
|
||||
app.register_blueprint(admin.bp)
|
||||
app.register_blueprint(groupe.bp)
|
||||
app.register_blueprint(albums.bp)
|
||||
app.register_blueprint(partition.bp)
|
||||
|
||||
|
||||
try:
|
||||
result = subprocess.run(["git", "describe", "--tags"], stdout=subprocess.PIPE, check=True)
|
||||
__version__ = result.stdout.decode('utf8')
|
||||
except (FileNotFoundError, subprocess.CalledProcessError):
|
||||
# In case git not found or any platform specific weird error
|
||||
__version__ = "unknown"
|
||||
__version__ = get_version()
|
||||
|
||||
|
||||
@app.route("/")
|
||||
@ -99,7 +129,7 @@ def search_thumbnail(uuid):
|
||||
f'/usr/bin/convert -thumbnail\
|
||||
"178^>" -background white -alpha \
|
||||
remove -crop 178x178+0+0 \
|
||||
partitioncloud/search-partitions/{uuid}.pdf[0] \
|
||||
{app.instance_path}/search-partitions/{uuid}.pdf[0] \
|
||||
partitioncloud/static/search-thumbnails/{uuid}.jpg'
|
||||
)
|
||||
|
||||
|
@ -42,7 +42,7 @@ def search_page():
|
||||
|
||||
query = request.form["query"]
|
||||
nb_queries = abs(int(request.form["nb-queries"]))
|
||||
search.flush_cache()
|
||||
search.flush_cache(current_app.instance_path)
|
||||
partitions_local = search.local_search(query, utils.get_all_partitions())
|
||||
|
||||
user = User(user_id=session.get("user_id"))
|
||||
@ -52,7 +52,7 @@ def search_page():
|
||||
nb_queries = min(current_app.config["MAX_ONLINE_QUERIES"], nb_queries)
|
||||
else:
|
||||
nb_queries = min(10, nb_queries) # Query limit is 10 for an admin
|
||||
google_results = search.online_search(query, nb_queries)
|
||||
google_results = search.online_search(query, nb_queries, current_app.instance_path)
|
||||
else:
|
||||
google_results = []
|
||||
|
||||
@ -207,7 +207,7 @@ def delete_album(uuid):
|
||||
flash(error)
|
||||
return redirect(request.referrer)
|
||||
|
||||
album.delete()
|
||||
album.delete(current_app.instance_path)
|
||||
|
||||
flash("Album supprimé.")
|
||||
return redirect("/albums")
|
||||
@ -278,20 +278,32 @@ def add_partition(album_uuid):
|
||||
)
|
||||
db.commit()
|
||||
|
||||
partition_path = os.path.join(
|
||||
current_app.instance_path,
|
||||
"partitions",
|
||||
f"{partition_uuid}.pdf"
|
||||
)
|
||||
|
||||
if partition_type == "file":
|
||||
file = request.files["file"]
|
||||
file.save(f"partitioncloud/partitions/{partition_uuid}.pdf")
|
||||
file.save(partition_path)
|
||||
else:
|
||||
search_partition_path = os.path.join(
|
||||
current_app.instance_path,
|
||||
"search-partitions",
|
||||
f"{search_uuid}.pdf"
|
||||
)
|
||||
|
||||
shutil.copyfile(
|
||||
f"partitioncloud/search-partitions/{search_uuid}.pdf",
|
||||
f"partitioncloud/partitions/{partition_uuid}.pdf"
|
||||
search_partition_path,
|
||||
partition_path
|
||||
)
|
||||
|
||||
os.system(
|
||||
f'/usr/bin/convert -thumbnail\
|
||||
"178^>" -background white -alpha \
|
||||
remove -crop 178x178+0+0 \
|
||||
partitioncloud/partitions/{partition_uuid}.pdf[0] \
|
||||
{partition_path}[0] \
|
||||
partitioncloud/static/thumbnails/{partition_uuid}.jpg'
|
||||
)
|
||||
db.commit()
|
||||
|
@ -82,7 +82,7 @@ class Album():
|
||||
).fetchall()
|
||||
|
||||
|
||||
def delete(self):
|
||||
def delete(self, instance_path):
|
||||
"""
|
||||
Supprimer l'album
|
||||
"""
|
||||
@ -130,9 +130,9 @@ class Album():
|
||||
attachments = [Attachment(data=i) for i in data]
|
||||
|
||||
for attachment in attachments:
|
||||
attachment.delete()
|
||||
attachment.delete(instance_path)
|
||||
|
||||
os.remove(f"partitioncloud/partitions/{partition['uuid']}.pdf")
|
||||
os.remove(f"{instance_path}/partitions/{partition['uuid']}.pdf")
|
||||
if os.path.exists(f"partitioncloud/static/thumbnails/{partition['uuid']}.jpg"):
|
||||
os.remove(f"partitioncloud/static/thumbnails/{partition['uuid']}.jpg")
|
||||
|
||||
|
@ -29,7 +29,7 @@ class Attachment():
|
||||
self.filetype = data["filetype"]
|
||||
self.partition_uuid = data["partition_uuid"]
|
||||
|
||||
def delete(self):
|
||||
def delete(self, instance_path):
|
||||
db = get_db()
|
||||
db.execute(
|
||||
"""
|
||||
@ -40,7 +40,7 @@ class Attachment():
|
||||
)
|
||||
db.commit()
|
||||
|
||||
os.remove(f"partitioncloud/attachments/{self.uuid}.{self.filetype}")
|
||||
os.remove(f"{instance_path}/attachments/{self.uuid}.{self.filetype}")
|
||||
|
||||
def __repr__(self):
|
||||
return f"{self.name}.{self.filetype}"
|
||||
|
@ -21,7 +21,7 @@ class Groupe():
|
||||
self.albums = None
|
||||
self.admins = None
|
||||
|
||||
def delete(self):
|
||||
def delete(self, instance_path):
|
||||
"""
|
||||
Supprime le groupe, et les albums laissés orphelins (sans utilisateur)
|
||||
"""
|
||||
@ -63,7 +63,7 @@ class Groupe():
|
||||
|
||||
for i in data:
|
||||
album = Album(id=i["id"])
|
||||
album.delete()
|
||||
album.delete(instance_path)
|
||||
|
||||
|
||||
def get_users(self):
|
||||
|
@ -29,7 +29,7 @@ class Partition():
|
||||
else:
|
||||
raise LookupError
|
||||
|
||||
def delete(self):
|
||||
def delete(self, instance_path):
|
||||
self.load_attachments()
|
||||
|
||||
db = get_db()
|
||||
@ -42,7 +42,7 @@ class Partition():
|
||||
)
|
||||
db.commit()
|
||||
|
||||
os.remove(f"partitioncloud/partitions/{self.uuid}.pdf")
|
||||
os.remove(f"{instance_path}/partitions/{self.uuid}.pdf")
|
||||
if os.path.exists(f"partitioncloud/static/thumbnails/{self.uuid}.jpg"):
|
||||
os.remove(f"partitioncloud/static/thumbnails/{self.uuid}.jpg")
|
||||
|
||||
@ -56,7 +56,7 @@ class Partition():
|
||||
db.commit()
|
||||
|
||||
for attachment in self.attachments:
|
||||
attachment.delete()
|
||||
attachment.delete(instance_path)
|
||||
|
||||
def update(self, name=None, author="", body=""):
|
||||
if name is None:
|
||||
|
@ -3,7 +3,7 @@
|
||||
Groupe module
|
||||
"""
|
||||
from flask import (Blueprint, abort, flash, redirect, render_template,
|
||||
request, session)
|
||||
request, session, current_app)
|
||||
|
||||
from .auth import login_required
|
||||
from .db import get_db
|
||||
@ -155,7 +155,7 @@ def delete_groupe(uuid):
|
||||
flash(error)
|
||||
return redirect(request.referrer)
|
||||
|
||||
groupe.delete()
|
||||
groupe.delete(current_app.instance_path)
|
||||
|
||||
flash("Groupe supprimé.")
|
||||
return redirect("/albums")
|
||||
|
@ -4,7 +4,8 @@ Partition module
|
||||
"""
|
||||
import os
|
||||
from uuid import uuid4
|
||||
from flask import Blueprint, abort, send_file, render_template, request, redirect, flash, session
|
||||
from flask import (Blueprint, abort, send_file, render_template,
|
||||
request, redirect, flash, session, current_app)
|
||||
|
||||
from .db import get_db
|
||||
from .auth import login_required, admin_required
|
||||
@ -21,9 +22,11 @@ def get_partition(uuid):
|
||||
abort(404)
|
||||
|
||||
|
||||
return send_file(
|
||||
os.path.join("partitions", f"{uuid}.pdf"),
|
||||
download_name = f"{partition.name}.pdf"
|
||||
return send_file(os.path.join(
|
||||
current_app.instance_path,
|
||||
"partitions",
|
||||
f"{uuid}.pdf"
|
||||
), download_name = f"{partition.name}.pdf"
|
||||
)
|
||||
|
||||
@bp.route("/<uuid>/attachments")
|
||||
@ -51,7 +54,7 @@ def add_attachment(uuid):
|
||||
user = User(user_id=session.get("user_id"))
|
||||
|
||||
if user.id != partition.user_id and user.access_level != 1:
|
||||
flash("Cette partition ne vous appartient pas")
|
||||
flash("Cette partition ne vous current_appartient pas")
|
||||
return redirect(request.referrer)
|
||||
|
||||
error = None # À mettre au propre
|
||||
@ -90,7 +93,11 @@ def add_attachment(uuid):
|
||||
db.commit()
|
||||
|
||||
file = request.files["file"]
|
||||
file.save(f"partitioncloud/attachments/{attachment_uuid}.{ext}")
|
||||
file.save(os.path.join(
|
||||
current_app.instance_path,
|
||||
"attachments",
|
||||
f"{attachment_uuid}.{ext}"
|
||||
))
|
||||
break
|
||||
|
||||
except db.IntegrityError:
|
||||
@ -114,9 +121,11 @@ def get_attachment(uuid, filetype):
|
||||
|
||||
assert filetype == attachment.filetype
|
||||
|
||||
return send_file(
|
||||
os.path.join("attachments", f"{uuid}.{attachment.filetype}"),
|
||||
download_name = f"{attachment.name}.{attachment.filetype}"
|
||||
return send_file(os.path.join(
|
||||
current_app.instance_path,
|
||||
"attachments",
|
||||
f"{uuid}.{attachment.filetype}"
|
||||
), download_name = f"{attachment.name}.{attachment.filetype}"
|
||||
)
|
||||
|
||||
|
||||
@ -223,7 +232,7 @@ def delete(uuid):
|
||||
if request.method == "GET":
|
||||
return render_template("partition/delete.html", partition=partition, user=user)
|
||||
|
||||
partition.delete()
|
||||
partition.delete(current_app.instance_path)
|
||||
|
||||
flash("Partition supprimée.")
|
||||
return redirect("/albums")
|
||||
@ -245,7 +254,13 @@ def partition_search(uuid):
|
||||
abort(404)
|
||||
if request.args.get("redirect") == "true" and partition["url"] is not None:
|
||||
return redirect(partition["url"])
|
||||
return send_file(os.path.join("search-partitions", f"{uuid}.pdf"))
|
||||
|
||||
return send_file(os.path.join(
|
||||
current_app.instance_path,
|
||||
"search-partitions",
|
||||
f"{uuid}.pdf"
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@bp.route("/")
|
||||
|
@ -49,19 +49,19 @@ def local_search(query, partitions):
|
||||
return selection
|
||||
|
||||
|
||||
def download_search_result(element):
|
||||
def download_search_result(element, instance_path):
|
||||
uuid = element["uuid"]
|
||||
url = element["url"]
|
||||
|
||||
try:
|
||||
urllib.request.urlretrieve(url, f"partitioncloud/search-partitions/{uuid}.pdf")
|
||||
urllib.request.urlretrieve(url, f"{instance_path}/search-partitions/{uuid}.pdf")
|
||||
|
||||
except (urllib.error.HTTPError, urllib.error.URLError):
|
||||
with open(f"partitioncloud/search-partitions/{uuid}.pdf", 'a', encoding="utf8") as _:
|
||||
with open(f"{instance_path}/search-partitions/{uuid}.pdf", 'a', encoding="utf8") as _:
|
||||
pass # Create empty file
|
||||
|
||||
|
||||
def online_search(query, num_queries):
|
||||
def online_search(query, num_queries, instance_path):
|
||||
"""
|
||||
Renvoie les 3 résultats les plus pertinents depuis google
|
||||
"""
|
||||
@ -103,7 +103,12 @@ def online_search(query, num_queries):
|
||||
except urllib.error.URLError: # Unable to access network
|
||||
return []
|
||||
|
||||
threads = [threading.Thread(target=download_search_result, args=(elem,)) for elem in partitions]
|
||||
threads = [
|
||||
threading.Thread(
|
||||
target=download_search_result,
|
||||
args=(elem, instance_path)
|
||||
) for elem in partitions
|
||||
]
|
||||
|
||||
for thread in threads:
|
||||
thread.start()
|
||||
@ -114,7 +119,7 @@ def online_search(query, num_queries):
|
||||
for element in partitions.copy():
|
||||
uuid = element["uuid"]
|
||||
url = element["url"]
|
||||
if os.stat(f"partitioncloud/search-partitions/{uuid}.pdf").st_size == 0:
|
||||
if os.stat(f"{instance_path}/search-partitions/{uuid}.pdf").st_size == 0:
|
||||
print("An error occured", url)
|
||||
db.execute(
|
||||
"""
|
||||
@ -125,14 +130,14 @@ def online_search(query, num_queries):
|
||||
)
|
||||
db.commit()
|
||||
|
||||
os.remove(f"partitioncloud/search-partitions/{uuid}.pdf")
|
||||
os.remove(f"{instance_path}/search-partitions/{uuid}.pdf")
|
||||
|
||||
partitions.remove(element)
|
||||
|
||||
return partitions
|
||||
|
||||
|
||||
def flush_cache():
|
||||
def flush_cache(instance_path):
|
||||
"""
|
||||
Supprimer les résultats de recherche datant de plus de 15 minutes
|
||||
"""
|
||||
@ -146,7 +151,7 @@ def flush_cache():
|
||||
for element in expired_cache:
|
||||
uuid = element["uuid"]
|
||||
try:
|
||||
os.remove(f"partitioncloud/search-partitions/{uuid}.pdf")
|
||||
os.remove(f"{instance_path}/search-partitions/{uuid}.pdf")
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
try:
|
||||
|
@ -1,4 +1,5 @@
|
||||
import os
|
||||
import shutil
|
||||
import sqlite3
|
||||
from hooks import utils
|
||||
from colorama import Fore, Style
|
||||
@ -142,3 +143,21 @@ def base_url_parameter_added():
|
||||
|
||||
def install_qrcode():
|
||||
os.system("pip install qrcode -qq")
|
||||
|
||||
|
||||
"""
|
||||
v1.5.*
|
||||
"""
|
||||
|
||||
|
||||
def move_instance():
|
||||
paths = [
|
||||
"attachments",
|
||||
"partitions",
|
||||
"search-partitions"
|
||||
]
|
||||
for path in paths:
|
||||
shutil.move(
|
||||
os.path.join("partitioncloud", path),
|
||||
os.path.join("instance", path)
|
||||
)
|
@ -33,6 +33,7 @@ hooks = [
|
||||
],
|
||||
),
|
||||
("v1.4.1", [("Install qrcode", v1_hooks.install_qrcode)]),
|
||||
("v1.5.0", [("Move to instance directory", v1_hooks.move_instance)])
|
||||
]
|
||||
|
||||
|
||||
@ -86,10 +87,10 @@ def backup_instance(version, verbose=True):
|
||||
os.path.join(dest, "search-partitions"),
|
||||
),
|
||||
]
|
||||
for src, dst in paths:
|
||||
for src, dst in paths: # Only the first one exists after v1.5.0
|
||||
if os.path.exists(src):
|
||||
print_verbose(f"\tBacking up {src}")
|
||||
shutil.copy_tree(src, dst)
|
||||
shutil.copytree(src, dst)
|
||||
|
||||
|
||||
def print_hooks(hooks_list):
|
||||
@ -108,7 +109,7 @@ def apply_hooks(hooks_list):
|
||||
|
||||
|
||||
def migrate(current, target, skip_backup=False, prog_name="scripts/migration.py"):
|
||||
""""""
|
||||
"""Migrate from one version to another"""
|
||||
print(f"Trying to migrate from {current} to {target}")
|
||||
|
||||
assert is_newer(target, current)
|
||||
@ -168,13 +169,13 @@ def restore(version):
|
||||
os.path.join(dest, "search-partitions"),
|
||||
),
|
||||
]
|
||||
for src, dst in paths:
|
||||
for src, dst in paths: # Only the first one exists after v1.5.0
|
||||
if os.path.exists(src):
|
||||
shutil.rmtree(src)
|
||||
|
||||
if os.path.exists(dst):
|
||||
print(f"\tRestoring {src}")
|
||||
shutil.copy_tree(dst, src)
|
||||
shutil.copytree(dst, src)
|
||||
else:
|
||||
print(
|
||||
f"\t{Fore.RED}No available backup for {src}, \
|
||||
|
Loading…
Reference in New Issue
Block a user