Skip to content

Commit

Permalink
Return the webhook URL to the service creator/getter
Browse files Browse the repository at this point in the history
I wish there was a cleaner way to do this:
fastapi/fastapi#10864

Signed-off-by: Aurélien Bompard <[email protected]>
  • Loading branch information
abompard committed Aug 21, 2024
1 parent 3b98d52 commit 52f3e64
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 9 deletions.
1 change: 1 addition & 0 deletions tests/test_service/test_service_get.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ async def test_service_lookup(client, authenticated, db_service):
"token": db_service.token,
"type": db_service.type,
"uuid": db_service.uuid,
"webhook_url": f"http://test/api/v1/messages/{db_service.uuid}",
},
}

Expand Down
1 change: 1 addition & 0 deletions tests/test_service/test_service_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ async def test_service_list(client, authenticated, db_service):
"token": db_service.token,
"type": db_service.type,
"uuid": db_service.uuid,
"webhook_url": f"http://test/api/v1/messages/{db_service.uuid}",
},
],
}
20 changes: 18 additions & 2 deletions webhook_to_fedora_messaging/endpoints/models/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,15 @@
from enum import Enum
from typing import List, Optional

from pydantic import BaseModel, ConfigDict
from pydantic import (
BaseModel,
ConfigDict,
HttpUrl,
model_validator,
ValidationError,
ValidationInfo,
)
from starlette.requests import Request


class ServiceType(str, Enum):
Expand All @@ -25,7 +33,15 @@ class ServiceBase(BaseModel, ABC):


class ServiceExternal(ServiceBase):
pass
webhook_url: HttpUrl | None = None

@model_validator(mode="after")
def build_url(cls, data: "ServiceExternal", info: ValidationInfo):
if data.webhook_url is None and info.context is None:
raise ValidationError("The request must be set in the context of model_validate()")
request: Request = info.context["request"]
data.webhook_url = HttpUrl(str(request.url_for("create_message", uuid=data.uuid)))
return data


class ServiceInternal(ServiceBase):
Expand Down
19 changes: 13 additions & 6 deletions webhook_to_fedora_messaging/endpoints/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from sqlalchemy import select
from sqlalchemy.exc import IntegrityError, NoResultFound
from sqlalchemy.ext.asyncio import AsyncSession
from starlette.requests import Request
from starlette.status import (
HTTP_200_OK,
HTTP_201_CREATED,
Expand Down Expand Up @@ -32,6 +33,7 @@
@router.post("", status_code=HTTP_201_CREATED, response_model=ServiceResult, tags=["services"])
async def create_service(
body: ServiceRequest,
request: Request,
session: AsyncSession = Depends(get_session), # noqa : B008
user: User = Depends(current_user), # noqa : B008
):
Expand All @@ -51,11 +53,12 @@ async def create_service(
logger.exception("Uniqueness constraint failed")
raise HTTPException(HTTP_409_CONFLICT, "This service already exists") from expt
(await made_service.awaitable_attrs.users).append(user)
return {"data": made_service}
return ServiceResult.model_validate({"data": made_service}, context={"request": request})


@router.get("", status_code=HTTP_200_OK, response_model=ServiceManyResult, tags=["services"])
async def list_services(
request: Request,
session: AsyncSession = Depends(get_session), # noqa : B008
user: User = Depends(current_user), # noqa : B008
):
Expand All @@ -64,24 +67,26 @@ async def list_services(
"""
query = select(Service).where(Service.users.contains(user))
service_data = await session.scalars(query)
return {"data": service_data}
return ServiceManyResult.model_validate({"data": service_data}, context={"request": request})


@router.get("/{uuid}", status_code=HTTP_200_OK, response_model=ServiceResult, tags=["services"])
async def get_service(
request: Request,
session: AsyncSession = Depends(get_session), # noqa : B008
service: Service = Depends(authorized_service_from_uuid), # noqa : B008
):
"""
Return the service with the specified UUID
"""
return {"data": service}
return ServiceResult.model_validate({"data": service}, context={"request": request})


@router.put(
"/{uuid}/revoke", status_code=HTTP_202_ACCEPTED, response_model=ServiceResult, tags=["services"]
)
async def revoke_service(
request: Request,
session: AsyncSession = Depends(get_session), # noqa : B008
service: Service = Depends(authorized_service_from_uuid), # noqa : B008
):
Expand All @@ -90,14 +95,15 @@ async def revoke_service(
"""
service.disabled = True
await session.flush()
return {"data": service}
return ServiceResult.model_validate({"data": service}, context={"request": request})


@router.put(
"/{uuid}", status_code=HTTP_202_ACCEPTED, response_model=ServiceResult, tags=["services"]
)
async def update_service(
body: ServiceUpdate,
request: Request,
session: AsyncSession = Depends(get_session), # noqa : B008
service: Service = Depends(authorized_service_from_uuid), # noqa : B008
):
Expand Down Expand Up @@ -125,7 +131,7 @@ async def update_service(

await session.flush()

return {"data": service}
return ServiceResult.model_validate({"data": service}, context={"request": request})


@router.put(
Expand All @@ -135,6 +141,7 @@ async def update_service(
tags=["services"],
)
async def regenerate_token(
request: Request,
session: AsyncSession = Depends(get_session), # noqa : B008
service: Service = Depends(authorized_service_from_uuid), # noqa : B008
):
Expand All @@ -143,4 +150,4 @@ async def regenerate_token(
"""
service.token = uuid4().hex
await session.flush()
return {"data": service}
return ServiceResult.model_validate({"data": service}, context={"request": request})
2 changes: 1 addition & 1 deletion webhook_to_fedora_messaging/fasjson.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ async def search_users(
async def get_username_from_github(self, username):
try:
users = await self.search_users(github_username=username)
except httpx.ReadTimeout:
except httpx.TimeoutException:
log.exception("Timeout fetching the FAS user with Github username %r", username)
return None
if len(users) == 1:
Expand Down

0 comments on commit 52f3e64

Please sign in to comment.