Added functions to fetch requirements from db.

Added functionality to create requirements on page
This commit is contained in:
gulimabr
2025-11-30 15:35:36 -03:00
parent bbbe65067b
commit eb70598cab
11 changed files with 1383 additions and 148 deletions

View File

@@ -1,15 +1,19 @@
from contextlib import asynccontextmanager
from typing import List
from fastapi import FastAPI, Depends, Request
from typing import List, Optional
from fastapi import FastAPI, Depends, Request, HTTPException, status
from fastapi.middleware.cors import CORSMiddleware
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from fastapi.responses import RedirectResponse
from sqlalchemy.ext.asyncio import AsyncSession
from src.models import TokenResponse, UserInfo, GroupResponse
from src.models import (
TokenResponse, UserInfo, GroupResponse,
TagResponse, RequirementResponse, PriorityResponse,
RequirementCreateRequest, RequirementUpdateRequest
)
from src.controller import AuthController
from src.config import get_openid, get_settings
from src.database import init_db, close_db, get_db
from src.repositories import RoleRepository, GroupRepository
from src.repositories import RoleRepository, GroupRepository, TagRepository, RequirementRepository, PriorityRepository
import logging
# Configure logging
@@ -176,3 +180,254 @@ async def get_groups(db: AsyncSession = Depends(get_db)):
group_repo = GroupRepository(db)
groups = await group_repo.get_all()
return [GroupResponse.model_validate(g) for g in groups]
# ===========================================
# Tags Endpoints
# ===========================================
@app.get("/api/tags", response_model=List[TagResponse])
async def get_tags(db: AsyncSession = Depends(get_db)):
"""
Get all tags.
Returns:
List of all tags with their codes and descriptions.
"""
tag_repo = TagRepository(db)
tags = await tag_repo.get_all()
return [TagResponse.model_validate(t) for t in tags]
@app.get("/api/tags/{tag_id}", response_model=TagResponse)
async def get_tag(tag_id: int, db: AsyncSession = Depends(get_db)):
"""
Get a specific tag by ID.
Args:
tag_id: The tag ID
Returns:
The tag if found.
"""
tag_repo = TagRepository(db)
tag = await tag_repo.get_by_id(tag_id)
if not tag:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Tag with id {tag_id} not found"
)
return TagResponse.model_validate(tag)
# ===========================================
# Priorities Endpoints
# ===========================================
@app.get("/api/priorities", response_model=List[PriorityResponse])
async def get_priorities(db: AsyncSession = Depends(get_db)):
"""
Get all priorities.
Returns:
List of all priorities ordered by priority_num.
"""
priority_repo = PriorityRepository(db)
priorities = await priority_repo.get_all()
return [PriorityResponse.model_validate(p) for p in priorities]
# ===========================================
# Requirements Endpoints
# ===========================================
def _build_requirement_response(req) -> RequirementResponse:
"""Helper function to build RequirementResponse from a Requirement model."""
# Determine validation status from latest validation
validation_status = "Not Validated"
if req.validations:
# Get the latest validation
latest_validation = max(req.validations, key=lambda v: v.created_at or req.created_at)
validation_status = latest_validation.status.status_name if latest_validation.status else "Not Validated"
return RequirementResponse(
id=req.id,
req_name=req.req_name,
req_desc=req.req_desc,
version=req.version,
created_at=req.created_at,
updated_at=req.updated_at,
tag=TagResponse.model_validate(req.tag),
priority=req.priority if req.priority else None,
groups=[GroupResponse.model_validate(g) for g in req.groups],
validation_status=validation_status,
)
@app.get("/api/requirements", response_model=List[RequirementResponse])
async def get_requirements(
group_id: Optional[int] = None,
tag_id: Optional[int] = None,
db: AsyncSession = Depends(get_db)
):
"""
Get all requirements, optionally filtered by group or tag.
Args:
group_id: Optional group ID to filter by
tag_id: Optional tag ID to filter by
Returns:
List of all requirements with their related data.
"""
req_repo = RequirementRepository(db)
if group_id:
requirements = await req_repo.get_by_group_id(group_id)
elif tag_id:
requirements = await req_repo.get_by_tag_id(tag_id)
else:
requirements = await req_repo.get_all()
return [_build_requirement_response(req) for req in requirements]
@app.get("/api/requirements/{requirement_id}", response_model=RequirementResponse)
async def get_requirement(requirement_id: int, db: AsyncSession = Depends(get_db)):
"""
Get a specific requirement by ID.
Args:
requirement_id: The requirement ID
Returns:
The requirement if found.
"""
req_repo = RequirementRepository(db)
requirement = await req_repo.get_by_id(requirement_id)
if not requirement:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Requirement with id {requirement_id} not found"
)
return _build_requirement_response(requirement)
@app.post("/api/requirements", response_model=RequirementResponse, status_code=status.HTTP_201_CREATED)
async def create_requirement(
request: Request,
req_data: RequirementCreateRequest,
db: AsyncSession = Depends(get_db)
):
"""
Create a new requirement.
Args:
req_data: The requirement data
Returns:
The created requirement.
"""
# Get the current user from cookie
user_info = AuthController.get_current_user(request)
# Get the user's database ID
from src.repositories import UserRepository
user_repo = UserRepository(db)
user = await user_repo.get_by_sub(user_info.sub)
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="User not found in database"
)
req_repo = RequirementRepository(db)
requirement = await req_repo.create(
user_id=user.id,
tag_id=req_data.tag_id,
req_name=req_data.req_name,
req_desc=req_data.req_desc,
priority_id=req_data.priority_id,
group_ids=req_data.group_ids,
)
await db.commit()
return _build_requirement_response(requirement)
@app.put("/api/requirements/{requirement_id}", response_model=RequirementResponse)
async def update_requirement(
requirement_id: int,
request: Request,
req_data: RequirementUpdateRequest,
db: AsyncSession = Depends(get_db)
):
"""
Update an existing requirement.
Args:
requirement_id: The requirement ID to update
req_data: The updated requirement data
Returns:
The updated requirement.
"""
# Get the current user from cookie
user_info = AuthController.get_current_user(request)
# Get the user's database ID
from src.repositories import UserRepository
user_repo = UserRepository(db)
user = await user_repo.get_by_sub(user_info.sub)
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="User not found in database"
)
req_repo = RequirementRepository(db)
requirement = await req_repo.update(
requirement_id=requirement_id,
editor_id=user.id,
req_name=req_data.req_name,
req_desc=req_data.req_desc,
tag_id=req_data.tag_id,
priority_id=req_data.priority_id,
group_ids=req_data.group_ids,
)
if not requirement:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Requirement with id {requirement_id} not found"
)
await db.commit()
return _build_requirement_response(requirement)
@app.delete("/api/requirements/{requirement_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_requirement(
requirement_id: int,
request: Request,
db: AsyncSession = Depends(get_db)
):
"""
Delete a requirement.
Args:
requirement_id: The requirement ID to delete
"""
# Verify user is authenticated
AuthController.get_current_user(request)
req_repo = RequirementRepository(db)
deleted = await req_repo.delete(requirement_id)
if not deleted:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Requirement with id {requirement_id} not found"
)
await db.commit()