initial commit
Build and Push Docker Images / build-and-push (push) Failing after 3m33s

This commit is contained in:
admin committed 2026-11-07 16:39:43 +03:00
commit 46af290db3
100 files changed
+16663

No files matched your search

+196
View File
@@ -0,0 +1,196 @@
import json
import shutil
from datetime import datetime
from pathlib import Path
from config.settings import settings
from models.bible import StoryBible
from models.project import Project
from models.user import User
from services.auth_service import auth_service
class ProjectService:
def __init__(self):
self.data_dir = Path(settings.DATA_DIR)
self.projects_dir = self.data_dir / "projects"
self.projects_dir.mkdir(parents=True, exist_ok=True)
self.projects_file = self.data_dir / "projects.json"
self.projects = self._load_projects()
# Миграция: перенос старых проектов в структуру с пользователями
self._migrate_old_data()
def _load_projects(self) -> list[Project]:
"""Загрузить список проектов"""
if self.projects_file.exists():
with open(self.projects_file, "r", encoding="utf-8") as f:
data = json.load(f)
return [Project(**p) for p in data]
return []
def _save_projects(self):
"""Сохранить список проектов"""
with open(self.projects_file, "w", encoding="utf-8") as f:
json.dump(
[p.model_dump() for p in self.projects],
f,
ensure_ascii=False,
indent=2,
)
def _migrate_old_data(self):
"""Миграция старых проектов в структуру data/users/{user_id}/projects/"""
old_projects_dir = self.data_dir / "projects"
users_dir = self.data_dir / "users"
users_file = self.data_dir / "users.json"
default_user_id = "default-user-0000-0000-0000-000000000000"
# Если есть старые проекты, но нет пользователей — создаём дефолтного и перемещаем
if old_projects_dir.exists() and not users_dir.exists():
print("Migrating old projects to a default user...")
default_user = User(
id=default_user_id,
username="admin",
email="admin@local",
hashed_password=auth_service.get_password_hash("admin"),
)
auth_service.users.append(default_user)
auth_service._save_users()
# Перемещаем папку проектов
new_user_dir = users_dir / default_user.id
new_user_dir.mkdir(parents=True, exist_ok=True)
old_projects_dir.rename(new_user_dir / "projects")
# Обновляем user_id у существующих проектов
for i, project in enumerate(self.projects):
self.projects[i].user_id = default_user.id
self._save_projects()
print("Migration complete. Default user: admin / admin")
# Если проекты уже перемещены, но users.json отсутствует — восстанавливаем
if users_dir.exists() and not users_file.exists():
has_projects_without_user = any(
p.user_id == "" or p.user_id == default_user_id for p in self.projects
)
if has_projects_without_user or any(users_dir.iterdir()):
print("Restoring default user (users.json was missing)...")
default_user = User(
id=default_user_id,
username="admin",
email="admin@local",
hashed_password=auth_service.get_password_hash("admin"),
)
auth_service.users.append(default_user)
auth_service._save_users()
# Обновляем user_id у проектов без привязки
for i, project in enumerate(self.projects):
if not project.user_id:
self.projects[i].user_id = default_user.id
self._save_projects()
print("Default user restored: admin / admin")
# Если папка projects уже переехала, обновляем ссылку
if users_dir.exists():
new_projects_dir = self.data_dir / "users"
# Проверяем что old_projects_dir больше не существует (уже перемещён)
if not old_projects_dir.exists():
self.projects_dir = new_projects_dir
def get_project_dir(self, project_id: str, user_id: str) -> Path:
"""Получить директорию проекта с учётом пользователя"""
# Определяем базу: если есть users/{user_id}, используем новую структуру
user_projects_base = self.data_dir / "users" / user_id / "projects"
if user_projects_base.exists():
project_dir = user_projects_base / project_id
else:
# Fallback для обратной совместимости
project_dir = self.data_dir / "projects" / project_id
if not project_dir.exists():
raise ValueError(f"Project directory not found: {project_id}")
return project_dir
def get_all_projects(self, user_id: str | None = None) -> list[Project]:
"""Получить все проекты (опционально фильтруя по пользователю)"""
if user_id:
return [p for p in self.projects if p.user_id == user_id]
return self.projects
def get_project(self, project_id: str) -> Project | None:
"""Получить проект по ID"""
for project in self.projects:
if project.id == project_id:
return project
return None
def create_project(
self, title: str, user_id: str, description: str = ""
) -> Project:
"""Создать новый проект"""
project = Project(title=title, user_id=user_id, description=description)
self.projects.append(project)
self._save_projects()
# Создаем директорию проекта в папке пользователя
project_dir = self.data_dir / "users" / user_id / "projects" / project.id
project_dir.mkdir(parents=True, exist_ok=True)
# Инициализируем пустые файлы
(project_dir / "documents.json").write_text("[]", encoding="utf-8")
# Создаем пустую Story Bible
empty_bible = StoryBible()
(project_dir / "story_bible.json").write_text(
json.dumps(empty_bible.model_dump(), ensure_ascii=False, indent=2),
encoding="utf-8",
)
return project
def update_project(
self,
project_id: str,
title: str | None = None,
description: str | None = None,
) -> Project | None:
"""Обновить проект"""
for i, project in enumerate(self.projects):
if project.id == project_id:
if title is not None:
self.projects[i].title = title
if description is not None:
self.projects[i].description = description
self.projects[i].updated_at = datetime.now().isoformat()
self._save_projects()
return self.projects[i]
return None
def delete_project(self, project_id: str, user_id: str) -> bool:
"""Удалить проект и все его данные"""
for i, project in enumerate(self.projects):
if project.id == project_id:
# Проверяем принадлежность
if project.user_id != user_id:
raise ValueError("Project does not belong to this user")
self.projects.pop(i)
self._save_projects()
# Удаляем директорию проекта
project_dir = (
self.data_dir / "users" / user_id / "projects" / project_id
)
if project_dir.exists():
shutil.rmtree(project_dir)
return True
return False
# Singleton instance
project_service = ProjectService()