satupeta-main/app/api/v1/routes/credential_route.py

222 lines
6.5 KiB
Python
Raw Normal View History

2026-01-27 02:11:58 +00:00
from typing import Optional
from uuid import UUID
from fastapi import APIRouter, Depends, Path, Query, status
from app.api.dependencies.auth import get_current_active_admin, get_current_active_user
from app.api.dependencies.factory import Factory
from app.core.params import CommonParams
from app.schemas.base import PaginatedResponse
from app.schemas.credential_schema import (
CredentialCreateSchema,
CredentialSchema,
CredentialUpdateSchema,
CredentialWithSensitiveDataSchema,
)
from app.schemas.user_schema import UserSchema
from app.services import CredentialService
router = APIRouter()
@router.post(
"/credentials",
summary="Buat kredensial baru",
status_code=status.HTTP_201_CREATED,
)
async def create_credential(
data: CredentialCreateSchema,
current_user: UserSchema = Depends(get_current_active_admin),
service: CredentialService = Depends(Factory().get_credential_service),
):
"""
Buat kredensial baru dengan data yang terenkripsi.
Endpoint ini hanya dapat diakses oleh admin.
**Data sensitive yang didukung:**
- Database:
- host, port, username, password, database_name
- MinIO:
- endpoint, access_key, secret_key, secure, bucket_name
- API:
- base_url, api_key
- SSH:
- host, port, username, password (atau private_key)
- SMTP:
- host, port, username, password, use_tls
- FTP:
- host, port, username, password
"""
result = await service.create_credential(
name=data.name,
credential_type=data.credential_type,
sensitive_data=data.sensitive_data,
credential_metadata=data.credential_metadata,
description=data.description,
is_default=data.is_default,
user_id=current_user.id,
)
return result
@router.get(
"/credentials",
response_model=PaginatedResponse[CredentialSchema],
summary="Dapatkan daftar kredensial",
dependencies=[Depends(get_current_active_user)],
)
async def get_credentials(
credential_type: Optional[str] = Query(None, description="Filter berdasarkan tipe kredensial"),
include_inactive: bool = Query(False, description="Sertakan kredensial yang tidak aktif"),
params: CommonParams = Depends(),
service: CredentialService = Depends(Factory().get_credential_service),
):
"""
Dapatkan daftar kredensial dengan filtering and pagination.
"""
filter_params = params.filter or []
sort = params.sort
search = params.search
group_by = params.group_by
limit = params.limit
offset = params.offset
if credential_type:
filter_params.append(f"credential_type={credential_type}")
if not include_inactive:
filter_params.append(f"is_active=true")
credentials, total = await service.find_all(
filters=filter_params, sort=sort, search=search, group_by=group_by, limit=limit, offset=offset
)
return PaginatedResponse(
items=[credential for credential in credentials],
total=total,
limit=limit,
offset=offset,
has_more=offset + limit < total,
)
@router.get(
"/credentials/{credential_id}",
response_model=CredentialSchema,
summary="Dapatkan kredensial dengan data terdekripsi",
dependencies=[Depends(get_current_active_user)],
)
async def get_credential(
credential_id: UUID = Path(..., description="ID kredensial"),
service: CredentialService = Depends(Factory().get_credential_service),
):
"""
Dapatkan kredensial dengan data sensitif yang sudah didekripsi.
Endpoint ini hanya dapat diakses oleh admin.
"""
credential = await service.find_by_id(credential_id)
return credential
@router.get(
"/credentials/{credential_id}/decrypted",
response_model=CredentialWithSensitiveDataSchema,
summary="Dapatkan kredensial dengan data terdekripsi",
dependencies=[Depends(get_current_active_user)],
)
async def get_credential_decrypted(
credential_id: UUID = Path(..., description="ID kredensial"),
service: CredentialService = Depends(Factory().get_credential_service),
):
"""
Dapatkan kredensial dengan data sensitif yang sudah didekripsi.
Endpoint ini hanya dapat diakses oleh admin.
"""
credential = await service.get_credential_with_decrypted_data(credential_id)
return credential
@router.patch(
"/credentials/{credential_id}",
summary="Update kredensial",
)
async def update_credential(
credential_id: UUID,
data: CredentialUpdateSchema,
current_user: UserSchema = Depends(get_current_active_admin),
service: CredentialService = Depends(Factory().get_credential_service),
):
"""
Update kredensial.
Data sensitif bisa diupdate secara parsial. Field yang tidak disebutkan
dalam data.sensitive_data tidak akan diubah.
Endpoint ini hanya dapat diakses oleh admin.
"""
updated = await service.update_credential(credential_id, data.dict(exclude_unset=True), current_user.id)
return updated
@router.delete("/credentials/{credential_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_credential(
credential_id: UUID,
user: UserSchema = Depends(get_current_active_admin),
service: CredentialService = Depends(Factory().get_credential_service),
):
await service.delete(user, credential_id)
# @router.post(
# "/{credential_id}/test",
# response_model=CredentialTestResult,
# summary="Test koneksi menggunakan kredensial"
# )
# async def test_credential(
# credential_id: UUID,
# current_user: UserSchema = Depends(get_current_active_user),
# service: CredentialService = Depends(Factory().get_credential_service)
# ):
# """
# Test koneksi menggunakan kredensial.
# Hasil test berisi flag sukses dan detail tambahan.
# """
# result = await service.test_credential(
# service.db, credential_id, current_user.id
# )
# return result
# @router.delete(
# "/{credential_id}",
# status_code=status.HTTP_204_NO_CONTENT,
# summary="Hapus kredensial"
# )
# async def delete_credential(
# credential_id: UUID,
# current_user: UserSchema = Depends(get_current_admin_user),
# service: CredentialService = Depends(Factory().get_credential_service)
# ):
# """
# Hapus kredensial secara permanen.
# Endpoint ini hanya dapat diakses oleh admin.
# """
# credential = await service.find_by_id(service.db, credential_id)
# if not credential:
# raise HTTPException(
# status_code=status.HTTP_404_NOT_FOUND,
# detail="Credential not found"
# )
# await service.delete(service.db, credential_id)
# return None