jira-ai-fixer/app/api/integrations.py

135 lines
4.6 KiB
Python

"""Integration management endpoints."""
from typing import List
import secrets
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from app.core.database import get_db
from app.models.integration import Integration, IntegrationType, IntegrationStatus
from app.models.organization import OrganizationMember
from app.schemas.integration import IntegrationCreate, IntegrationRead, IntegrationUpdate
from app.api.deps import get_current_user, require_role
router = APIRouter()
@router.get("/", response_model=List[IntegrationRead])
async def list_integrations(
org_id: int,
member: OrganizationMember = Depends(require_role("analyst")),
db: AsyncSession = Depends(get_db)
):
"""List integrations for organization."""
result = await db.execute(
select(Integration).where(Integration.organization_id == org_id)
)
return result.scalars().all()
@router.post("/", response_model=IntegrationRead, status_code=status.HTTP_201_CREATED)
async def create_integration(
org_id: int,
integration_in: IntegrationCreate,
member: OrganizationMember = Depends(require_role("admin")),
db: AsyncSession = Depends(get_db)
):
"""Create a new integration."""
# Generate webhook secret
webhook_secret = secrets.token_hex(32)
integration = Integration(
organization_id=org_id,
name=integration_in.name,
type=integration_in.type,
base_url=integration_in.base_url,
api_key=integration_in.api_key,
webhook_secret=webhook_secret,
callback_url=integration_in.callback_url,
auto_analyze=integration_in.auto_analyze,
config=integration_in.config or {},
status=IntegrationStatus.ACTIVE
)
db.add(integration)
await db.commit()
await db.refresh(integration)
return integration
@router.get("/{integration_id}", response_model=IntegrationRead)
async def get_integration(
org_id: int,
integration_id: int,
member: OrganizationMember = Depends(require_role("analyst")),
db: AsyncSession = Depends(get_db)
):
"""Get integration details."""
result = await db.execute(
select(Integration)
.where(Integration.id == integration_id)
.where(Integration.organization_id == org_id)
)
integration = result.scalar_one_or_none()
if not integration:
raise HTTPException(status_code=404, detail="Integration not found")
return integration
@router.patch("/{integration_id}", response_model=IntegrationRead)
async def update_integration(
org_id: int,
integration_id: int,
integration_update: IntegrationUpdate,
member: OrganizationMember = Depends(require_role("admin")),
db: AsyncSession = Depends(get_db)
):
"""Update integration."""
result = await db.execute(
select(Integration)
.where(Integration.id == integration_id)
.where(Integration.organization_id == org_id)
)
integration = result.scalar_one_or_none()
if not integration:
raise HTTPException(status_code=404, detail="Integration not found")
for field, value in integration_update.dict(exclude_unset=True).items():
setattr(integration, field, value)
return integration
@router.delete("/{integration_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_integration(
org_id: int,
integration_id: int,
member: OrganizationMember = Depends(require_role("admin")),
db: AsyncSession = Depends(get_db)
):
"""Delete integration."""
result = await db.execute(
select(Integration)
.where(Integration.id == integration_id)
.where(Integration.organization_id == org_id)
)
integration = result.scalar_one_or_none()
if not integration:
raise HTTPException(status_code=404, detail="Integration not found")
await db.delete(integration)
@router.post("/{integration_id}/test")
async def test_integration(
org_id: int,
integration_id: int,
member: OrganizationMember = Depends(require_role("admin")),
db: AsyncSession = Depends(get_db)
):
"""Test integration connection."""
result = await db.execute(
select(Integration)
.where(Integration.id == integration_id)
.where(Integration.organization_id == org_id)
)
integration = result.scalar_one_or_none()
if not integration:
raise HTTPException(status_code=404, detail="Integration not found")
# TODO: Implement actual connection test based on integration type
return {"status": "ok", "message": "Connection successful"}