diff --git a/.gitignore b/.gitignore index e5eaa34..e28f2ec 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ logs/ FLAT.xml **/package-lock.json .nx/ +**/*.db diff --git a/apps/backend/fastapi/app/api/routes/versions.py b/apps/backend/fastapi/app/api/routes/versions.py index 9699781..ed53426 100644 --- a/apps/backend/fastapi/app/api/routes/versions.py +++ b/apps/backend/fastapi/app/api/routes/versions.py @@ -7,6 +7,7 @@ from app.api.deps import get_current_user, get_db from app.schemas import BranchCreateRequest, VersionResponse from app.services.versions import create_branch, delete_version from dlib.auth import AuthenticatedUser +from dlib.cv.ats_guard import PatchValidationError router = APIRouter(prefix="/versions", tags=["versions"]) @@ -18,14 +19,17 @@ async def create_version_branch( session: AsyncSession = Depends(get_db), user: AuthenticatedUser = Depends(get_current_user), ): - version = await create_branch( - session, - owner_id=user.sub, - parent_version_id=payload.parent_version_id, - branch_name=payload.branch_name, - version_label=payload.version_label, - patches=payload.patches, - ) + try: + version = await create_branch( + session, + owner_id=user.sub, + parent_version_id=payload.parent_version_id, + branch_name=payload.branch_name, + version_label=payload.version_label, + patches=payload.patches, + ) + except PatchValidationError as exc: + raise HTTPException(status_code=422, detail=str(exc)) from exc if not version: raise HTTPException(status_code=404, detail="Parent version not found") return VersionResponse.model_validate(version) diff --git a/apps/backend/fastapi/app/core/config.py b/apps/backend/fastapi/app/core/config.py index 879d0da..3975c55 100644 --- a/apps/backend/fastapi/app/core/config.py +++ b/apps/backend/fastapi/app/core/config.py @@ -57,6 +57,13 @@ class Settings(BaseSettings): return [origin.strip() for origin in value.split(",") if origin.strip()] return value + @field_validator("storage_endpoint_url", mode="before") + @classmethod + def _empty_endpoint_to_none(cls, value): + if isinstance(value, str) and not value.strip(): + return None + return value + @lru_cache(maxsize=1) def get_settings() -> Settings: diff --git a/apps/backend/fastapi/app/services/documents.py b/apps/backend/fastapi/app/services/documents.py index 6bc0022..710cc8c 100644 --- a/apps/backend/fastapi/app/services/documents.py +++ b/apps/backend/fastapi/app/services/documents.py @@ -23,20 +23,22 @@ async def create_document( structured = parse_docx_bytes(file_bytes, version_label="root") doc = CvDocument(owner_id=owner_id, title=title, description=description) + session.add(doc) + await session.flush() # persist doc so version FK is satisfied + version = CvVersion( - document=doc, + document_id=doc.id, branch_name="root", version_label="root", artifact_docx_key=artifact_key, structured_blocks=[block.model_dump() for block in structured.blocks], metadata_json={"ingested": True}, ) - doc.versions.append(version) - doc.root_version_id = version.id + session.add(version) + await session.flush() # persist version so root_version_id FK is satisfied - session.add(doc) + doc.root_version_id = version.id await session.commit() - await session.refresh(doc) stmt = ( select(CvDocument) diff --git a/apps/webapp/src/libs/api.ts b/apps/webapp/src/libs/api.ts index c744664..c50c201 100644 --- a/apps/webapp/src/libs/api.ts +++ b/apps/webapp/src/libs/api.ts @@ -92,6 +92,11 @@ async function req(path: string, init?: RequestInit): Promise { headers: { accept: 'application/json', ...getAuthHeader(), ...init?.headers }, }); if (!res.ok) { + if (res.status === 401 && typeof window !== 'undefined') { + document.cookie = 'oidc_token_pub=; max-age=0; path=/'; + document.cookie = 'oidc_token=; max-age=0; path=/'; + window.location.href = '/login'; + } const detail = await res.text().catch(() => res.statusText); throw new Error(detail || `HTTP ${res.status}`); }