diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..8613392 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,13 @@ +.git +.venv +__pycache__/ +*.pyc +*.pyo +*.pyd +*.db +*.sqlite +dist/ +build/ +node_modules/ +*.log + diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..ef41e08 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,17 @@ +FROM python:3.11-slim + +WORKDIR /app + +# System deps (optional): none needed for sqlite + +COPY requirements.txt ./ +RUN pip install --no-cache-dir -r requirements.txt gunicorn + +COPY . . + +ENV FLASK_ENV=production +ENV PORT=5000 +EXPOSE 5000 + +CMD ["gunicorn", "-b", "0.0.0.0:5000", "app:app", "--workers", "2", "--threads", "4", "--timeout", "60"] + diff --git a/app.py b/app.py index 90e08e1..fade6ce 100644 --- a/app.py +++ b/app.py @@ -148,6 +148,26 @@ def create_app(): base_url = request.host_url.rstrip("/") return render_template("admin.html", pages=pages, base_url=base_url) + @app.route("/admin/edit/", methods=["GET", "POST"]) + def admin_edit(pid: int): + login_required() + db = get_db() + if request.method == "POST": + title = request.form.get("title", "").strip() + html = request.form.get("html", "").strip() + if not html: + flash("HTML не может быть пустым.", "error") + else: + db.execute("UPDATE pages SET title = ?, html = ? WHERE id = ?", (title, html, pid)) + db.commit() + flash("Страница обновлена.", "success") + return redirect(url_for("admin")) + + row = db.execute("SELECT id, uuid, title, html, created_at FROM pages WHERE id = ?", (pid,)).fetchone() + if row is None: + abort(404) + return render_template("edit.html", page=row) + @app.route("/admin/delete/", methods=["POST"]) def admin_delete(pid: int): login_required() @@ -201,6 +221,22 @@ def create_app(): html = html[:idx] + toolbar + html[idx:] else: html = html + toolbar + # Ensure watermark exists on published pages (top-left) + wm = ( + '' + '' + '' + '
' + 'Made by Ruslan'
' + ) + lower_all = html.lower() + if "" in lower_all: + i2 = lower_all.rfind("") + html = html[:i2] + wm + html[i2:] + else: + html = html + wm return Response(html, mimetype="text/html; charset=utf-8") # Optional: simple 404 page to keep things minimal diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..754de30 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,19 @@ +version: "3.9" + +services: + web: + build: . + container_name: forme-web + ports: + - "5000:5000" + environment: + - SECRET_KEY=${SECRET_KEY:-prod-secret} + - ADMIN_USERNAME=${ADMIN_USERNAME:-ruslan} + - ADMIN_PASSWORD=${ADMIN_PASSWORD:-utOgbZ09ruslan} + volumes: + - appdb:/app/app.db + restart: unless-stopped + +volumes: + appdb: {} + diff --git a/requirements.txt b/requirements.txt index 01a5fbb..e3c27dc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,2 @@ Flask>=2.3,<3.0 +gunicorn>=21.2 diff --git a/templates/admin.html b/templates/admin.html index 6017210..e6850bf 100644 --- a/templates/admin.html +++ b/templates/admin.html @@ -1,6 +1,6 @@ {% extends 'base.html' %} {% block content %} -

Публикация HTML-страниц

+

Публикация HTML-страницы

@@ -11,8 +11,10 @@
- - После публикации создаётся ссылка с UUID. +
+ + После публикации создаётся ссылка с UUID. +
@@ -42,7 +44,8 @@ {{ base_url }}/p/{{ p.uuid }} {{ p.created_at }} -
+ Редактировать +
@@ -51,8 +54,9 @@ {% else %} -

Страниц пока нет.

+

Пока нет опубликованных страниц.

{% endif %} + +{% endblock %}