diff --git a/server/polar/article/endpoints.py b/server/polar/article/endpoints.py index cc46b5dbe0..97b9133470 100644 --- a/server/polar/article/endpoints.py +++ b/server/polar/article/endpoints.py @@ -9,6 +9,7 @@ from polar.kit.pagination import ListResource, PaginationParamsQuery from polar.models.article import ArticleVisibility from polar.openapi import IN_DEVELOPMENT_ONLY, APITag +from polar.organization.schemas import OrganizationID from polar.postgres import AsyncSession, get_db_session from polar.routing import APIRouter @@ -33,7 +34,7 @@ async def list( auth_subject: auth.ArticlesReadOrAnonymous, pagination: PaginationParamsQuery, - organization_id: UUID4 | None = Query( + organization_id: OrganizationID | None = Query( None, description="Filter by organization ID." ), slug: str | None = Query(None, description="Filter by slug."), diff --git a/server/polar/benefit/endpoints.py b/server/polar/benefit/endpoints.py index 4ea8f43648..d1c6104d4e 100644 --- a/server/polar/benefit/endpoints.py +++ b/server/polar/benefit/endpoints.py @@ -10,6 +10,7 @@ from polar.models import Benefit from polar.models.benefit import BenefitType from polar.openapi import APITag +from polar.organization.schemas import OrganizationID from polar.postgres import AsyncSession, get_db_session from polar.posthog import posthog from polar.routing import APIRouter @@ -35,7 +36,7 @@ async def list( auth_subject: auth.BenefitsRead, pagination: PaginationParamsQuery, - organization_id: UUID4 | None = Query( + organization_id: OrganizationID | None = Query( None, description="Filter by organization ID." ), type: BenefitType | None = Query( diff --git a/server/polar/file/endpoints.py b/server/polar/file/endpoints.py index e77f254c27..d23fbe2223 100644 --- a/server/polar/file/endpoints.py +++ b/server/polar/file/endpoints.py @@ -10,6 +10,7 @@ from polar.models import File, Organization from polar.openapi import APITag from polar.organization.resolver import get_payload_organization +from polar.organization.schemas import OrganizationID from polar.organization.service import organization as organization_service from polar.postgres import AsyncSession, get_db_session from polar.routing import APIRouter @@ -48,7 +49,7 @@ async def list( auth_subject: auth.CreatorFilesWrite, pagination: PaginationParamsQuery, - organization_id: UUID4 | None = None, + organization_id: OrganizationID | None = None, ids: ListOfFileIDs | None = Query( None, description=("List of file IDs to get. "), diff --git a/server/polar/metrics/endpoints.py b/server/polar/metrics/endpoints.py index e4a12fa1a3..2516c52beb 100644 --- a/server/polar/metrics/endpoints.py +++ b/server/polar/metrics/endpoints.py @@ -6,6 +6,7 @@ from polar.exceptions import PolarRequestValidationError from polar.models.product_price import ProductPriceType from polar.openapi import APITag +from polar.organization.schemas import OrganizationID from polar.postgres import AsyncSession, get_db_session from polar.product.schemas import ProductID from polar.routing import APIRouter @@ -29,7 +30,7 @@ async def get( ), end_date: date = Query(..., description="End date."), interval: Interval = Query(..., description="Interval between two timestamps."), - organization_id: UUID4 | None = Query( + organization_id: OrganizationID | None = Query( None, description="Filter by organization ID." ), product_id: ProductID | None = Query(None, description="Filter by product ID."), diff --git a/server/polar/order/endpoints.py b/server/polar/order/endpoints.py index 774a566f5b..79775481e7 100644 --- a/server/polar/order/endpoints.py +++ b/server/polar/order/endpoints.py @@ -8,6 +8,7 @@ from polar.models import Order from polar.models.product_price import ProductPriceType from polar.openapi import APITag +from polar.organization.schemas import OrganizationID from polar.postgres import AsyncSession, get_db_session from polar.product.schemas import ProductID from polar.routing import APIRouter @@ -29,7 +30,7 @@ async def list( auth_subject: auth.OrdersRead, pagination: PaginationParamsQuery, sorting: sorting.ListSorting, - organization_id: UUID4 | None = Query( + organization_id: OrganizationID | None = Query( None, description="Filter by organization ID." ), product_id: ProductID | None = Query(None, description="Filter by product ID."), diff --git a/server/polar/organization/endpoints.py b/server/polar/organization/endpoints.py index 1c17f1ff7c..1d03a3dd6a 100644 --- a/server/polar/organization/endpoints.py +++ b/server/polar/organization/endpoints.py @@ -1,9 +1,7 @@ -from typing import Annotated from uuid import UUID import structlog -from fastapi import Depends, HTTPException, Path, Query -from pydantic import UUID4 +from fastapi import Depends, HTTPException, Query from polar.auth.models import Subject from polar.authz.service import AccessType, Authz @@ -31,6 +29,7 @@ OrganizationBadgeSettingsUpdate, OrganizationCustomer, OrganizationCustomerType, + OrganizationID, OrganizationSetAccount, OrganizationStripePortalSession, OrganizationUpdate, @@ -45,7 +44,6 @@ router = APIRouter(tags=["organizations"]) -OrganizationID = Annotated[UUID4, Path(description="The organization ID.")] OrganizationNotFound = { "description": "Organization not found.", "model": ResourceNotFound.schema(), @@ -75,7 +73,7 @@ async def to_schema( @router.get( - "/organizations", + "/organizations/", response_model=ListResource[OrganizationSchema], description="List organizations that the authenticated user is a member of. Requires authentication.", # noqa: E501 summary="List organizations", diff --git a/server/polar/organization/schemas.py b/server/polar/organization/schemas.py index 8aac9eb821..9d3a738c39 100644 --- a/server/polar/organization/schemas.py +++ b/server/polar/organization/schemas.py @@ -4,15 +4,22 @@ from typing import Annotated, Self from uuid import UUID +from fastapi import Path from pydantic import UUID4, Field, HttpUrl from polar.config import settings from polar.currency.schemas import CurrencyAmount from polar.enums import Platforms from polar.integrations.github import types -from polar.kit.schemas import EmptyStrToNoneValidator, Schema +from polar.kit.schemas import EmptyStrToNoneValidator, Schema, SelectorWidget from polar.models.organization import Organization as OrganizationModel +OrganizationID = Annotated[ + UUID4, + Path(description="The organization ID."), + SelectorWidget("/v1/organizations", "Organization", "name"), +] + class OrganizationFeatureSettings(Schema): articles_enabled: bool = Field( diff --git a/server/polar/product/endpoints.py b/server/polar/product/endpoints.py index 1fb5788a8d..4376bcca3a 100644 --- a/server/polar/product/endpoints.py +++ b/server/polar/product/endpoints.py @@ -9,6 +9,7 @@ from polar.models import Product from polar.models.product import SubscriptionTierType from polar.openapi import APITag +from polar.organization.schemas import OrganizationID from polar.postgres import AsyncSession, get_db_session from polar.routing import APIRouter @@ -31,7 +32,7 @@ async def list( pagination: PaginationParamsQuery, auth_subject: auth.CreatorProductsReadOrAnonymous, - organization_id: Sequence[UUID4] | None = Query( + organization_id: Sequence[OrganizationID] | None = Query( None, description="Filter by organization ID." ), include_archived: bool = Query( diff --git a/server/polar/subscription/endpoints.py b/server/polar/subscription/endpoints.py index 0bfd5e7490..489c686f6e 100644 --- a/server/polar/subscription/endpoints.py +++ b/server/polar/subscription/endpoints.py @@ -19,6 +19,7 @@ from polar.models import Subscription from polar.models.product import SubscriptionTierType from polar.openapi import APITag +from polar.organization.schemas import OrganizationID from polar.organization.service import organization as organization_service from polar.postgres import AsyncSession, get_db_session from polar.product.schemas import ProductID @@ -50,7 +51,7 @@ async def list( auth_subject: auth.SubscriptionsRead, pagination: PaginationParamsQuery, sorting: SearchSorting, - organization_id: UUID4 | None = Query( + organization_id: OrganizationID | None = Query( None, description="Filter by organization ID." ), product_id: ProductID | None = Query(None, description="Filter by product ID."), @@ -214,7 +215,7 @@ async def subscriptions_import( @router.get("/export", summary="Export Subscriptions") async def export( auth_subject: auth.SubscriptionsRead, - organization_id: UUID4 | None = Query( + organization_id: OrganizationID | None = Query( None, description="Filter by organization ID." ), session: AsyncSession = Depends(get_db_session), diff --git a/server/polar/webhook/endpoints.py b/server/polar/webhook/endpoints.py index d966a88525..758526eafd 100644 --- a/server/polar/webhook/endpoints.py +++ b/server/polar/webhook/endpoints.py @@ -8,6 +8,7 @@ from polar.exceptions import NotPermitted, ResourceNotFound, Unauthorized from polar.kit.pagination import ListResource, PaginationParamsQuery from polar.models import WebhookEndpoint +from polar.organization.schemas import OrganizationID from polar.postgres import AsyncSession, get_db_session from polar.routing import APIRouter @@ -32,7 +33,7 @@ async def list_webhook_endpoints( pagination: PaginationParamsQuery, auth_subject: WebhooksRead, - organization_id: UUID4 | None = Query( + organization_id: OrganizationID | None = Query( None, description="Filter by organization ID." ), user_id: UUID4 | None = Query(None, description="Filter by user ID."),