mirror of
https://github.com/velocitatem/cvfs.git
synced 2026-05-31 08:43:37 +00:00
feat(dashboard): complete CV branching dashboard with auth and full editing workflow
- Visual branch heritage tree with colored dots and connecting lines, depth-aware expand/collapse - Dashboard 3-tab layout: Content (inline block editing + patch staging), Patches (diff view), Submissions (AI suggestions) - Inline block editing: click to edit any CV block, stage edits, save as named branch with pre-filled patches - Submissions tab: create applications, request AI tailoring suggestions, accept/reject per suggestion - Simple hardcoded login (username/password via env vars LOGIN_USER/LOGIN_PASS, defaults admin/admin) - Authentik OIDC integration: authorize redirect + callback exchange, configurable via NEXT_PUBLIC_AUTHENTIK_* - Middleware protecting /dashboard with session cookie verification (HMAC-SHA256) - Auth API routes: /api/auth/login, /api/auth/logout, /api/auth/callback, /api/auth/token - Backend: GET/PATCH submission routes for listing submissions and accepting/rejecting AI suggestions - API client: OIDC bearer token forwarding from client-readable cookie https://claude.ai/code/session_01CdisLhbC2kVt2hxfJ7TNPf
This commit is contained in:
@@ -9,14 +9,43 @@ from app.schemas import (
|
||||
SubmissionCreateRequest,
|
||||
SubmissionResponse,
|
||||
SuggestionResponse,
|
||||
SuggestionUpdateRequest,
|
||||
)
|
||||
from app.services.submissions import (
|
||||
create_submission,
|
||||
get_submission,
|
||||
list_submissions,
|
||||
request_ai_suggestions,
|
||||
update_suggestion,
|
||||
)
|
||||
from app.services.submissions import create_submission, request_ai_suggestions
|
||||
from dlib.auth import AuthenticatedUser
|
||||
|
||||
|
||||
router = APIRouter(prefix="/submissions", tags=["submissions"])
|
||||
|
||||
|
||||
@router.get("", response_model=list[SubmissionResponse])
|
||||
async def list_submissions_endpoint(
|
||||
version_id: str | None = None,
|
||||
session: AsyncSession = Depends(get_db),
|
||||
user: AuthenticatedUser = Depends(get_current_user),
|
||||
):
|
||||
items = await list_submissions(session, owner_id=user.sub, version_id=version_id)
|
||||
return [SubmissionResponse.model_validate(s) for s in items]
|
||||
|
||||
|
||||
@router.get("/{submission_id}", response_model=SubmissionResponse)
|
||||
async def get_submission_endpoint(
|
||||
submission_id: str,
|
||||
session: AsyncSession = Depends(get_db),
|
||||
user: AuthenticatedUser = Depends(get_current_user),
|
||||
):
|
||||
submission = await get_submission(session, owner_id=user.sub, submission_id=submission_id)
|
||||
if not submission:
|
||||
raise HTTPException(status_code=404, detail="Submission not found")
|
||||
return SubmissionResponse.model_validate(submission)
|
||||
|
||||
|
||||
@router.post("", response_model=SubmissionResponse)
|
||||
async def create_submission_endpoint(
|
||||
payload: SubmissionCreateRequest,
|
||||
@@ -54,3 +83,23 @@ async def request_submissions_ai(
|
||||
if suggestions is None:
|
||||
raise HTTPException(status_code=404, detail="Submission not found")
|
||||
return [SuggestionResponse.model_validate(item) for item in suggestions]
|
||||
|
||||
|
||||
@router.patch("/{submission_id}/suggestions/{suggestion_id}", response_model=SuggestionResponse)
|
||||
async def update_suggestion_endpoint(
|
||||
submission_id: str,
|
||||
suggestion_id: str,
|
||||
payload: SuggestionUpdateRequest,
|
||||
session: AsyncSession = Depends(get_db),
|
||||
user: AuthenticatedUser = Depends(get_current_user),
|
||||
):
|
||||
suggestion = await update_suggestion(
|
||||
session,
|
||||
owner_id=user.sub,
|
||||
submission_id=submission_id,
|
||||
suggestion_id=suggestion_id,
|
||||
accepted=payload.accepted,
|
||||
)
|
||||
if not suggestion:
|
||||
raise HTTPException(status_code=404, detail="Suggestion not found")
|
||||
return SuggestionResponse.model_validate(suggestion)
|
||||
|
||||
Reference in New Issue
Block a user