- JavaScript 47.9%
- Python 36.8%
- CSS 14.6%
- HTML 0.4%
- Dockerfile 0.3%
|
|
||
|---|---|---|
| backend | ||
| frontend | ||
| .gitignore | ||
| docker-compose.yml | ||
| example.env | ||
| README.md | ||
Disk
Docker-приложение для облачного хранилища с интерфейсом в стиле Яндекс.Диска.
Что внутри:
FastAPI + SQLitebackend.React + Vitefrontend.- Личная директория каждого пользователя в
data/<user_id>/. - Содержимое файлов в
data/<user_id>/шифруется, recovery-доступ вынесен в отдельную утилиту. - Доступ к файлам и папкам для других пользователей.
- Публичные ссылки для неавторизованных людей.
- Права
viewer,editor,manager. - Корзина с хранением удалённых файлов и папок 30 дней.
- Скачивание папок одним архивом
zip.
Запуск
docker compose up --build
После старта:
- frontend:
http://localhost:3000 - backend:
http://localhost:8000
Для домена и HTTPS frontend ходит в backend через относительный путь /api, который проксируется nginx внутри web контейнера. Это убирает проблемы с CORS и запросами на localhost.
Для backend теперь обязательно задать:
JWT_SECRET_KEYSERVER_FILE_KEY_ENCRYPTION_KEY: base64-строка, которая декодируется ровно в 32 байтаADMIN_RECOVERY_PUBLIC_KEYADMIN_RECOVERY_PRIVATE_KEY
ADMIN_RECOVERY_* можно передавать либо PEM-текстом прямо в env, либо путём к PEM-файлу внутри контейнера.
Минимальная генерация ключей для .env:
# 32-байтный base64-ключ для шифрования пользовательских file keys
python3 -c "import os,base64; print(base64.b64encode(os.urandom(32)).decode())"
# recovery RSA key pair
mkdir -p secrets
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 -out secrets/disk_recovery_private.pem
openssl rsa -pubout -in secrets/disk_recovery_private.pem -out secrets/disk_recovery_public.pem
Пример значений в .env:
JWT_SECRET_KEY=change-me
SERVER_FILE_KEY_ENCRYPTION_KEY=<base64-ключ-из-команды-выше>
ADMIN_RECOVERY_PUBLIC_KEY=/app/secrets/disk_recovery_public.pem
ADMIN_RECOVERY_PRIVATE_KEY=/app/secrets/disk_recovery_private.pem
ADMIN_RECOVERY_PRIVATE_KEY_PASSWORD=
Если приватный recovery-ключ создаёте с паролем, укажите его в ADMIN_RECOVERY_PRIVATE_KEY_PASSWORD. Если без пароля, оставьте переменную пустой.
Публичные ссылки и ссылки-приглашения по умолчанию строятся от адреса, на котором открыт frontend. Чтобы всегда выдавать ссылки с вашим доменом, задайте PUBLIC_BASE_URL перед сборкой Docker:
PUBLIC_BASE_URL=https://disk.example.com docker compose up --build
Для локальной frontend-разработки можно задать:
VITE_PUBLIC_BASE_URL=https://disk.example.com
Локальная разработка
Frontend:
cd frontend
npm install
npm run dev
Backend:
cd backend
pip install -r requirements.txt
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
По умолчанию Vite ходит в backend через VITE_API_URL. В docker-сборке используется /api, локально можно работать и с прямым backend на http://localhost:8000.
Сценарий
- Зарегистрируйте двух пользователей.
- Под первым пользователем создайте папку или загрузите файл.
- Нажмите
Доступи выдайте:- доступ другому пользователю по его
username; - или публичную ссылку для неавторизованного просмотра/редактирования.
- доступ другому пользователю по его
- У второго пользователя общий ресурс появится в блоке
Доступно мне.
Корзина
- Удаление из раздела
Файлыперемещает объект вКорзину. - Объект хранится 30 дней с момента удаления.
- Из корзины можно восстановить объект или удалить навсегда.
Права
viewer: просмотр списка и скачивание файлов.editor: просмотр, загрузка файлов, создание папок, удаление и переименование.manager: всё выше плюс возможность управлять доступом владельца ресурса.
Хранение
Файлы лежат в локальном томе:
data/
<user_id>/
SQLite база хранится рядом в data/storage.db.
Сами файлы больше не лежат в открытом виде: на диске хранится шифротекст. Структура каталогов и имена файлов пока сохраняются в открытом виде, чтобы не ломать текущий API и механику шаринга.
Шифрование и Recovery
- У каждого пользователя есть собственный ключ шифрования файлов.
- Этот ключ хранится в трёх обёртках: по паролю пользователя, сервисным ключом backend и recovery-ключом администратора.
- Обычная работа приложения идёт через сервисную обёртку.
- Смена пароля переупаковывает пользовательскую обёртку, не трогая сами файлы.
- Админский recovery-доступ вынесен в отдельную явную утилиту, а не в прямое чтение из
data/.
Миграция существующих файлов
- Сначала задайте новые переменные окружения и убедитесь, что backend может стартовать с ними.
- Сделайте backup каталога
data/. - Выполните миграцию:
cd backend
python scripts/migrate_to_encrypted_storage.py
Что делает миграция:
- создаёт сервисную и recovery-обёртки ключей для старых пользователей;
- шифрует все незашифрованные файлы в
data/<user_id>/и.trash; - уже зашифрованные файлы пропускает;
- если у старого пользователя ещё нет парольной обёртки ключа, она будет автоматически создана при его следующем успешном логине.
Recovery-доступ администратора
Чтобы явно расшифровать конкретный файл по recovery-ключу:
cd backend
python scripts/recover_file.py --user-id 12 --path "docs/report.pdf" --output /tmp/report.pdf
Структура проекта
docker-compose.yml
example.env
backend/
Dockerfile
requirements.txt
app/
__init__.py
auth.py
crypto.py
database.py
main.py
models.py
schemas.py
storage.py
scripts/
migrate_to_encrypted_storage.py
recover_file.py
frontend/
Dockerfile
index.html
nginx.conf
package.json
vite.config.js
public/
favicon.png
src/
components/
constants/
hooks/
pages/
utils/
App.jsx
api.js
config.js
main.jsx
styles.css
secrets/
disk_recovery_private.pem
disk_recovery_public.pem
Frontend Architecture
Frontend больше не собран в одном файле. Основные части разделены так:
pages/: экраны приложения:DiskPage,PublicSharePage,AdminPage,AuthScreen,InviteRegistrationPage.components/: переиспользуемые UI-блоки, модалки, карточки, header/sidebar-части.hooks/: клиентское состояние и сценарии, напримерuseSession,useExplorer,useShareModal,useUploadQueue.utils/: низкоуровневые утилиты и action-layer, включаяexplorerActions.js, превью, скачивание и форматирование.
Ключевая идея:
App.jsxотвечает только за маршрутизацию.- страницы собираются из переиспользуемых компонентов и хуков.
- операции над файлами и шарингом вынесены из страниц в общий action-layer.
Backend Notes
main.pyсодержит HTTP API и маршруты FastAPI.storage.pyотвечает за работу с файловой системой, корзиной и правами доступа.auth.pyреализует аутентификацию и JWT.database.pyподнимает SQLite и выполняет простую инициализацию схемы.