mirror of
https://github.com/ION606/static-site-hosting.git
synced 2026-05-14 22:16:54 +00:00
c1f26094de
* split into files * attempted path fix * perms fix * added missed functions * fixed circular dependancy * I hate splitting * env fix * path fix
113 lines
3.5 KiB
Python
113 lines
3.5 KiB
Python
# upload_handler.py
|
|
from flask import flash, redirect, url_for, current_app
|
|
import os
|
|
import re
|
|
from .config import Config
|
|
from .models import Site
|
|
from . import db
|
|
|
|
# Constants
|
|
MAX_FILE_SIZE = 5 * 1024 * 1024 # 5MB per file
|
|
MAX_TOTAL_STORAGE = 100 * 1024 * 1024 # 100MB per user
|
|
ALLOWED_EXTENSIONS = {
|
|
"html",
|
|
"css",
|
|
"js",
|
|
"png",
|
|
"jpg",
|
|
"jpeg",
|
|
"gif",
|
|
"svg",
|
|
"ico",
|
|
"webp",
|
|
"txt",
|
|
"pdf",
|
|
}
|
|
MAX_FILES_PER_UPLOAD = 50
|
|
|
|
|
|
def get_user_storage(user_id):
|
|
total_size = 0
|
|
user_dir = os.path.join(current_app.config["UPLOAD_FOLDER"], str(user_id))
|
|
if os.path.exists(user_dir):
|
|
for site_dir in os.listdir(user_dir):
|
|
site_path = os.path.join(user_dir, site_dir)
|
|
if os.path.isdir(site_path):
|
|
for root, _, files in os.walk(site_path):
|
|
for f in files:
|
|
fp = os.path.join(root, f)
|
|
total_size += os.path.getsize(fp)
|
|
return total_size
|
|
|
|
|
|
def handle_upload(current_user, site_name, subdomain, files):
|
|
# Validation checks
|
|
if not re.match(r"^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$", subdomain):
|
|
flash("Invalid subdomain format", "error")
|
|
return redirect(url_for("main.dashboard"))
|
|
|
|
if not site_name or not subdomain:
|
|
flash("Name and subdomain required", "error")
|
|
return redirect(url_for("main.dashboard"))
|
|
|
|
if Site.query.filter_by(subdomain=subdomain).first():
|
|
flash("Subdomain taken", "error")
|
|
return redirect(url_for("main.dashboard"))
|
|
|
|
if len(files) > MAX_FILES_PER_UPLOAD:
|
|
flash(f"Max {MAX_FILES_PER_UPLOAD} files per upload", "error")
|
|
return redirect(url_for("main.dashboard"))
|
|
|
|
for file in files:
|
|
if "." not in file.filename:
|
|
flash(f"File {file.filename} has no extension", "error")
|
|
return redirect(url_for("main.dashboard"))
|
|
ext = file.filename.rsplit(".", 1)[1].lower()
|
|
if ext not in ALLOWED_EXTENSIONS:
|
|
flash(f".{ext} files not allowed", "error")
|
|
return redirect(url_for("main.dashboard"))
|
|
|
|
total_new_size = 0
|
|
for file in files:
|
|
file.stream.seek(0, os.SEEK_END)
|
|
size = file.stream.tell()
|
|
file.stream.seek(0)
|
|
if size > MAX_FILE_SIZE:
|
|
flash(f"{file.filename} exceeds {MAX_FILE_SIZE//1024//1024}MB", "error")
|
|
return redirect(url_for("main.dashboard"))
|
|
total_new_size += size
|
|
|
|
current_storage = get_user_storage(current_user.id)
|
|
if current_storage + total_new_size > MAX_TOTAL_STORAGE:
|
|
flash(f"Storage limit ({MAX_TOTAL_STORAGE//1024//1024}MB) exceeded", "error")
|
|
return redirect(url_for("main.dashboard"))
|
|
|
|
if not any(f.filename == "index.html" for f in files):
|
|
flash("Missing index.html", "error")
|
|
return redirect(url_for("main.dashboard"))
|
|
|
|
# Create site
|
|
site = Site(user_id=current_user.id, name=site_name, subdomain=subdomain)
|
|
db.session.add(site)
|
|
db.session.commit()
|
|
|
|
# Save files
|
|
site_dir = os.path.join(
|
|
current_app.config["UPLOAD_FOLDER"], str(current_user.id), str(site.id)
|
|
)
|
|
os.makedirs(site_dir, exist_ok=True)
|
|
|
|
try:
|
|
for file in files:
|
|
if file.filename:
|
|
file.save(os.path.join(site_dir, file.filename))
|
|
except Exception as e:
|
|
db.session.delete(site)
|
|
db.session.commit()
|
|
flash("Upload failed", "error")
|
|
return redirect(url_for("main.dashboard"))
|
|
|
|
flash("Site created!", "success")
|
|
return redirect(url_for("main.dashboard"))
|
|
|