Add user auth, personal cabinet, admin panel and first admin bootstrap

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-06 22:20:09 +03:00
parent c6a7ecfc4c
commit 61e7290ce8
26 changed files with 1351 additions and 108 deletions
+52 -4
View File
@@ -3,6 +3,10 @@
Современный фото-хостинг на **Python (Flask)**, **PostgreSQL** и **Docker Compose**.
- Красивая главная страница с drag-and-drop загрузкой
- **Регистрация и авторизация** пользователей
- **Личный кабинет** — загрузка и управление своими фото
- **Админ-панель** — пользователи, фото, статистика
- **Автоматическое создание первого администратора** через `.env`
- Галерея загруженных фото
- Копирование прямых ссылок на изображения
- Хранение метаданных в PostgreSQL, файлов — в Docker volume
@@ -14,8 +18,13 @@
```
fotohost/
├── app/
│ ├── __init__.py # Flask-приложение и модель Photo
│ ├── routes.py # Маршруты (загрузка, галерея, API)
│ ├── __init__.py # Flask-приложение, Flask-Login
│ ├── models.py # User, Photo
│ ├── auth.py # Регистрация, вход, выход
│ ├── routes.py # Главная, загрузка, личный кабинет
│ ├── admin.py # Админ-панель
│ ├── bootstrap.py # Миграция схемы, первый admin
│ ├── auth_utils.py # Декораторы доступа
│ ├── templates/ # HTML-шаблоны
│ └── static/ # CSS и JavaScript
├── uploads/ # Локальная папка (в Docker — volume)
@@ -132,6 +141,11 @@ DATABASE_URL=postgresql://photohost:YOUR_STRONG_DB_PASSWORD@db:5432/photohost
SECRET_KEY=random_string_min_32_chars
MAX_UPLOAD_MB=10
APP_PORT=8080
# Первый администратор (создаётся автоматически при первом запуске)
ADMIN_USERNAME=admin
ADMIN_EMAIL=admin@example.com
ADMIN_PASSWORD=YOUR_STRONG_ADMIN_PASSWORD
```
Сгенерировать случайный `SECRET_KEY`:
@@ -140,6 +154,14 @@ APP_PORT=8080
python3 -c "import secrets; print(secrets.token_hex(32))"
```
> **Первый администратор:** при первом запуске, если в базе нет ни одного admin, создаётся пользователь из `ADMIN_USERNAME` / `ADMIN_EMAIL` / `ADMIN_PASSWORD`. Обязательно смените пароль в `.env` до деплоя.
Альтернатива — создать admin вручную через CLI:
```bash
docker compose exec web flask create-admin
```
### 8. Запуск приложения
```bash
@@ -175,6 +197,8 @@ http://YOUR_SERVER_IP:8080
Загрузите тестовое изображение — оно должно появиться в галерее.
Войдите как admin (`/auth/login`) → откройте **Админку** (`/admin`).
### 10. Открытие порта в файрволе (UFW)
Если включён UFW:
@@ -197,6 +221,26 @@ sudo systemctl start docker
---
## Регистрация, авторизация и роли
| URL | Описание |
|-----|----------|
| `/auth/register` | Регистрация нового пользователя |
| `/auth/login` | Вход (логин или email) |
| `/auth/logout` | Выход |
| `/cabinet/` | Личный кабинет — мои фото |
| `/cabinet/profile` | Настройки профиля, смена пароля |
| `/admin/` | Панель администратора (только admin) |
| `/admin/users` | Управление пользователями |
| `/admin/photos` | Все фото на сервере |
**Права доступа:**
- Загрузка фото — только авторизованным пользователям
- Удаление фото — владелец или администратор
- Админка — только пользователи с `is_admin=True`
---
## Полезные команды
| Действие | Команда |
@@ -321,7 +365,11 @@ python wsgi.py
| Метод | URL | Описание |
|-------|---------------|-----------------------------|
| GET | `/` | Главная страница |
| POST | `/upload` | Загрузка фото (form-data) |
| POST | `/auth/register` | Регистрация |
| POST | `/auth/login` | Вход |
| GET | `/cabinet/` | Личный кабинет |
| GET | `/admin/` | Админ-панель |
| POST | `/upload` | Загрузка фото (auth) |
| GET | `/uploads/<filename>` | Прямая ссылка на файл |
| GET | `/api/photos` | JSON-список всех фото |
| POST | `/delete/<id>` | Удаление фото |
@@ -377,7 +425,7 @@ docker compose down && docker compose up -d
## Технологии
- Python 3.12, Flask 3, Gunicorn
- Python 3.12, Flask 3, Flask-Login, Gunicorn
- PostgreSQL 16
- SQLAlchemy, Pillow
- Docker & Docker Compose