Files
2025-04-01 19:17:33 -04:00

118 lines
3.7 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"))
# Check for reserved subdomains
if subdomain in Config.RESERVED_SUBDOMAINS:
flash(f"The subdomain '{subdomain}' is reserved", "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"))