update, and allow non-mount data
This commit is contained in:
@@ -1,36 +1,23 @@
|
||||
FROM ubuntu:24.04
|
||||
FROM debian:stable
|
||||
|
||||
COPY ./requirements.txt /requirements.txt
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
ENV TMPDIR=/tmp
|
||||
RUN apt-get update -yqq \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
curl \
|
||||
sqlite3 \
|
||||
tzdata \
|
||||
git \
|
||||
make \
|
||||
python3-venv \
|
||||
python3-pip \
|
||||
curl \
|
||||
tzdata \
|
||||
sqlite3 \
|
||||
python3-venv \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& mkdir -p /data \
|
||||
&& python3 -m venv /opt/venv \
|
||||
&& . /opt/venv/bin/activate \
|
||||
&& pip3 install --no-cache -r /requirements.txt \
|
||||
&& rm -rf /root/.cache
|
||||
|
||||
ARG UUID
|
||||
ARG UGID
|
||||
ARG TZ
|
||||
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||||
RUN id ubuntu && userdel ubuntu
|
||||
RUN groupadd -g $UGID user && \
|
||||
useradd -u $UUID -g $UGID -ms /bin/bash user && \
|
||||
mkdir -p /opt/venv && chown $UUID:$UGID /opt/venv
|
||||
COPY ./requirements.txt /requirements.txt
|
||||
COPY docker-builder.sh /
|
||||
USER user
|
||||
|
||||
RUN bash /docker-builder.sh
|
||||
COPY ./ /app
|
||||
USER root
|
||||
RUN chown -R $UUID:$UGID /app
|
||||
USER user
|
||||
|
||||
WORKDIR /app
|
||||
RUN chmod 777 /app /data
|
||||
CMD bash /app/entrypoint.sh
|
||||
|
||||
37
code/app.py
37
code/app.py
@@ -20,6 +20,7 @@ from utils.files import (
|
||||
db_add_download,
|
||||
db_delete_file,
|
||||
db_get_file,
|
||||
db_get_last_maintenance,
|
||||
db_get_name,
|
||||
db_maintenance,
|
||||
db_store_file,
|
||||
@@ -28,6 +29,7 @@ from utils.files import (
|
||||
file_full_url,
|
||||
file_list,
|
||||
file_list_simple,
|
||||
get_db,
|
||||
invalidate_upload_token,
|
||||
new_upload_token,
|
||||
validate_upload_token,
|
||||
@@ -43,16 +45,17 @@ from werkzeug.utils import secure_filename
|
||||
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format=f"[%(asctime)s] [%(levelname)s] %(message)s",
|
||||
format="[%(asctime)s] [%(levelname)s] %(message)s",
|
||||
)
|
||||
|
||||
__VERSION__ = "20250328.0"
|
||||
__VERSION__ = "20251017.0"
|
||||
app = Flask(__name__)
|
||||
app.config.from_object(__name__)
|
||||
app.config.from_prefixed_env()
|
||||
app.debug = True
|
||||
app.secret_key = app.config["APP_SECRET_KEY"]
|
||||
app.wsgi_app = ReverseProxied(app.wsgi_app)
|
||||
app.config["KEY_LENGTH"] = int(app.config["KEY_LENGTH"])
|
||||
|
||||
|
||||
@app.before_request
|
||||
@@ -70,14 +73,24 @@ def log_the_status_code(response):
|
||||
@app.route("/")
|
||||
def index():
|
||||
"""Returns Index"""
|
||||
return render_template(
|
||||
"index.html"
|
||||
)
|
||||
return render_template("index.html")
|
||||
|
||||
|
||||
@app.route('/health.html', methods=["GET",]) # fmt: skip
|
||||
@app.route('/health', methods=["GET",]) # fmt: skip
|
||||
def health():
|
||||
return f"OK {request.url}", 200
|
||||
try:
|
||||
get_db()
|
||||
except Exception:
|
||||
return "DB Error", 500
|
||||
|
||||
try:
|
||||
last_maintenance = db_get_last_maintenance()
|
||||
if time.time() > last_maintenance + 86400: # Daily
|
||||
return f"OK, {db_maintenance()}, {request.url}", 200
|
||||
except Exception:
|
||||
return "DB Maintenance error", 500
|
||||
|
||||
return f"OK, {request.url}", 200
|
||||
|
||||
|
||||
@app.route("/upload", methods=["PUT", "POST"])
|
||||
@@ -144,7 +157,7 @@ def upload():
|
||||
return "IP list contains unknown characters"
|
||||
|
||||
while True:
|
||||
token = random_token()
|
||||
token = random_token(app.config["KEY_LENGTH"])
|
||||
folder = os.path.join(app.config["DATAFOLDER"], token)
|
||||
if not os.path.exists(folder):
|
||||
break
|
||||
@@ -196,6 +209,7 @@ def upload_token():
|
||||
token = new_upload_token(expires)
|
||||
return token, 200
|
||||
|
||||
|
||||
@app.route("/details/<token>", methods=["GET"])
|
||||
@app.route("/details/<token>/<name>", methods=["GET"])
|
||||
def details(token, name=None):
|
||||
@@ -211,7 +225,10 @@ def details(token, name=None):
|
||||
if secret != app.config["ACCESS_TOKEN"]:
|
||||
return "Error", 401
|
||||
if name is None:
|
||||
name = db_get_name(token)[0]
|
||||
try:
|
||||
name = db_get_name(token)[0]
|
||||
except TypeError:
|
||||
return "No such file", 404
|
||||
details = file_details(token, name)
|
||||
if details["allowed_ip"] is not None:
|
||||
if not is_ip_allowed(
|
||||
@@ -223,7 +240,7 @@ def details(token, name=None):
|
||||
|
||||
@app.route("/delete/<token>", methods=["GET"])
|
||||
@app.route("/delete/<token>/<name>", methods=["GET"])
|
||||
def delete_file(token,name=None):
|
||||
def delete_file(token, name=None):
|
||||
"""
|
||||
Delete a file from the system
|
||||
"""
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
PYTHON=python3
|
||||
SQLITE=sqlite3
|
||||
|
||||
set -eu
|
||||
|
||||
export FLASK_DATAFOLDER="/data"
|
||||
export FLASK_DB="/data/flees.db"
|
||||
@@ -9,21 +9,21 @@ export SERVER=gunicorn
|
||||
export PID="flees.pid"
|
||||
export WORKERS
|
||||
export TIMEOUT
|
||||
export TZ
|
||||
|
||||
if [[ $( stat -c %u /data ) -ne $( id -u ) ]]; then
|
||||
echo User id and /data folder owner do not match
|
||||
printf 'UID: %s\nFolder: %s\n' $( id -u ) $( stat -c %u /data )
|
||||
exit 1
|
||||
if [[ ! -w "$FLASK_DATAFOLDER" ]]; then
|
||||
echo Cannot write to $FLASK_DATAFOLDER
|
||||
exit 1
|
||||
fi
|
||||
|
||||
set -eu
|
||||
. /opt/venv/bin/activate
|
||||
sh ./init_db.sh "$FLASK_DB"
|
||||
|
||||
echo "Dowload script: curl -H 'Secret: [FLASK_ACCESS_TOKEN]' http://${FLASK_PUBLIC_URL}/script/mfl"
|
||||
exec "$SERVER" \
|
||||
-w $WORKERS \
|
||||
--timeout $TIMEOUT \
|
||||
-w "$WORKERS" \
|
||||
--worker-tmp-dir "$TMPDIR" \
|
||||
--timeout "$TIMEOUT" \
|
||||
--pid="$PID" \
|
||||
-b 0.0.0.0:$INTERNAL_PORT \
|
||||
-b 0.0.0.0:"$INTERNAL_PORT" \
|
||||
'app:app' \
|
||||
2>&1 | tee -a /data/flees.log
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
|
||||
cat <<'EOF' | sqlite3 "$1"
|
||||
|
||||
CREATE TABLE IF NOT EXISTS files (
|
||||
token text PRIMARY KEY,
|
||||
name text NOT NULL,
|
||||
@@ -13,12 +14,18 @@ CREATE TABLE IF NOT EXISTS files (
|
||||
allowed_ip text,
|
||||
hidden boolean
|
||||
);
|
||||
EOF
|
||||
|
||||
cat <<'EOF' | sqlite3 "$1"
|
||||
CREATE TABLE IF NOT EXISTS upload_tokens (
|
||||
token text PRIMARY KEY,
|
||||
added integer NOT NULL,
|
||||
expires integer NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS tasks (
|
||||
key text PRIMARY KEY,
|
||||
value integer NOT NULL
|
||||
);
|
||||
|
||||
INSERT OR IGNORE INTO tasks(key,value) VALUES('maintenance',0);
|
||||
|
||||
EOF
|
||||
|
||||
@@ -51,7 +51,6 @@ def db_get_name(token):
|
||||
).fetchone()
|
||||
|
||||
|
||||
|
||||
def db_get_files():
|
||||
db, c = get_db()
|
||||
return db.execute(
|
||||
@@ -92,6 +91,16 @@ def db_add_download(token, name):
|
||||
return
|
||||
|
||||
|
||||
def db_get_last_maintenance():
|
||||
db, c = get_db()
|
||||
return db.execute(
|
||||
"""
|
||||
SELECT value
|
||||
FROM tasks WHERE key = 'maintenance'
|
||||
"""
|
||||
).fetchone()[0]
|
||||
|
||||
|
||||
def db_maintenance():
|
||||
messages = []
|
||||
# === Delete DB entries where expiry or max DL is used up ===
|
||||
@@ -174,6 +183,9 @@ def db_maintenance():
|
||||
if c.rowcount > 0:
|
||||
db.commit()
|
||||
|
||||
db, c = get_db()
|
||||
c.execute("UPDATE tasks SET value=? WHERE key='maintenance'", (int(time.time()),))
|
||||
db.commit()
|
||||
messages.append("Maintenance done.")
|
||||
return "\n".join(messages)
|
||||
|
||||
|
||||
@@ -3,15 +3,18 @@ services:
|
||||
miniflees:
|
||||
build:
|
||||
context: code
|
||||
args:
|
||||
UUID: ${UUID}
|
||||
UGID: ${UGID}
|
||||
TZ: ${TZ}
|
||||
ports:
|
||||
- "${EXPOSE}:5000"
|
||||
volumes:
|
||||
- ./data/:/data/
|
||||
- $HOME/tmp/data/:/data/
|
||||
restart: unless-stopped
|
||||
user: "${UUID}:${UGID}"
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:5000/health"]
|
||||
interval: 3600s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
environment:
|
||||
WORKERS:
|
||||
TIMEOUT:
|
||||
@@ -20,6 +23,7 @@ services:
|
||||
FLASK_PUBLIC_URL:
|
||||
FLASK_DEFAULT_EXPIRE:
|
||||
FLASK_DEFAULT_MAX_DL:
|
||||
FLASK_KEY_LENGTH:
|
||||
TZ:
|
||||
|
||||
|
||||
|
||||
@@ -9,3 +9,4 @@ FLASK_ACCESS_TOKEN=dff789f0bbe8183d3254258b33a147d580c1131f39a698c56d3f640ac8415
|
||||
FLASK_PUBLIC_URL=http://localhost:8136
|
||||
FLASK_DEFAULT_EXPIRE=2592000
|
||||
FLASK_DEFAULT_MAX_DL=9999
|
||||
FLASK_KEY_LENGTH=8
|
||||
|
||||
Reference in New Issue
Block a user