From aecd4aa6e71ec2882d2b386949ad5ecd974a15f3 Mon Sep 17 00:00:00 2001 From: Ejiro Asiuwhu Date: Tue, 24 Mar 2026 22:23:58 +0100 Subject: [PATCH] feat: add project, api key, oauth, payment, and notification models - Project with nested ProjectConfig and OAuthProviderConfig - ApiKey hierarchy: ApiKey, UserApiKey, UserApiKeyFirstView, TeamApiKey, TeamApiKeyFirstView - OAuthConnection and OAuthProvider models - Item and Product payment models - NotificationCategory model - models/__init__.py re-exports all 20+ model classes --- .../python/src/stack_auth/models/__init__.py | 45 ++++++++++++++++ .../python/src/stack_auth/models/api_keys.py | 54 +++++++++++++++++++ .../src/stack_auth/models/notifications.py | 17 ++++++ .../python/src/stack_auth/models/oauth.py | 25 +++++++++ .../python/src/stack_auth/models/payments.py | 27 ++++++++++ .../python/src/stack_auth/models/projects.py | 39 ++++++++++++++ 6 files changed, 207 insertions(+) create mode 100644 sdks/implementations/python/src/stack_auth/models/api_keys.py create mode 100644 sdks/implementations/python/src/stack_auth/models/notifications.py create mode 100644 sdks/implementations/python/src/stack_auth/models/oauth.py create mode 100644 sdks/implementations/python/src/stack_auth/models/payments.py create mode 100644 sdks/implementations/python/src/stack_auth/models/projects.py diff --git a/sdks/implementations/python/src/stack_auth/models/__init__.py b/sdks/implementations/python/src/stack_auth/models/__init__.py index e69de29bb..92996605d 100644 --- a/sdks/implementations/python/src/stack_auth/models/__init__.py +++ b/sdks/implementations/python/src/stack_auth/models/__init__.py @@ -0,0 +1,45 @@ +"""Stack Auth data models -- re-exports all model classes.""" + +from stack_auth.models.api_keys import ( + ApiKey, + TeamApiKey, + TeamApiKeyFirstView, + UserApiKey, + UserApiKeyFirstView, +) +from stack_auth.models.contact_channels import ContactChannel +from stack_auth.models.notifications import NotificationCategory +from stack_auth.models.oauth import OAuthConnection, OAuthProvider +from stack_auth.models.payments import Item, Product +from stack_auth.models.permissions import ProjectPermission, TeamPermission +from stack_auth.models.projects import OAuthProviderConfig, Project, ProjectConfig +from stack_auth.models.sessions import ActiveSession, GeoInfo +from stack_auth.models.teams import ServerTeam, Team, TeamInvitation, TeamMemberProfile +from stack_auth.models.users import BaseUser, ServerUser + +__all__ = [ + "BaseUser", + "ServerUser", + "Team", + "ServerTeam", + "TeamMemberProfile", + "TeamInvitation", + "ActiveSession", + "GeoInfo", + "ContactChannel", + "TeamPermission", + "ProjectPermission", + "Project", + "ProjectConfig", + "OAuthProviderConfig", + "ApiKey", + "UserApiKey", + "UserApiKeyFirstView", + "TeamApiKey", + "TeamApiKeyFirstView", + "OAuthConnection", + "OAuthProvider", + "Product", + "Item", + "NotificationCategory", +] diff --git a/sdks/implementations/python/src/stack_auth/models/api_keys.py b/sdks/implementations/python/src/stack_auth/models/api_keys.py new file mode 100644 index 000000000..bfe4a9c63 --- /dev/null +++ b/sdks/implementations/python/src/stack_auth/models/api_keys.py @@ -0,0 +1,54 @@ +"""API key models for Stack Auth.""" + +from __future__ import annotations + +from datetime import datetime + +from pydantic import Field + +from stack_auth.models._base import StackAuthModel + + +class ApiKey(StackAuthModel): + """Base type for API keys.""" + + id: str + description: str = "" + expires_at_millis: int | None = Field(None, alias="expiresAtMillis") + created_at_millis: int = Field(alias="createdAtMillis") + is_valid: bool = Field(True, alias="isValid") + + @property + def expires_at(self) -> datetime | None: + """Convert expires_at_millis to a UTC datetime, or None.""" + return self._millis_to_datetime(self.expires_at_millis) + + @property + def created_at(self) -> datetime: + """Convert created_at_millis to a UTC datetime.""" + return self._millis_to_datetime(self.created_at_millis) # type: ignore[return-value] + + +class UserApiKey(ApiKey): + """An API key owned by a user.""" + + user_id: str = Field(alias="userId") + team_id: str | None = Field(None, alias="teamId") + + +class UserApiKeyFirstView(UserApiKey): + """Returned only when creating a new user API key. Contains the secret.""" + + api_key: str = Field(alias="apiKey") + + +class TeamApiKey(ApiKey): + """An API key owned by a team.""" + + team_id: str = Field(alias="teamId") + + +class TeamApiKeyFirstView(TeamApiKey): + """Returned only when creating a new team API key. Contains the secret.""" + + api_key: str = Field(alias="apiKey") diff --git a/sdks/implementations/python/src/stack_auth/models/notifications.py b/sdks/implementations/python/src/stack_auth/models/notifications.py new file mode 100644 index 000000000..e41e9a412 --- /dev/null +++ b/sdks/implementations/python/src/stack_auth/models/notifications.py @@ -0,0 +1,17 @@ +"""Notification models for Stack Auth.""" + +from __future__ import annotations + +from pydantic import Field + +from stack_auth.models._base import StackAuthModel + + +class NotificationCategory(StackAuthModel): + """A category of notifications users can subscribe to or unsubscribe from.""" + + id: str + display_name: str = Field(alias="displayName") + description: str | None = None + is_subscribed_by_default: bool = Field(True, alias="isSubscribedByDefault") + is_user_subscribed: bool = Field(True, alias="isUserSubscribed") diff --git a/sdks/implementations/python/src/stack_auth/models/oauth.py b/sdks/implementations/python/src/stack_auth/models/oauth.py new file mode 100644 index 000000000..d02a7bae4 --- /dev/null +++ b/sdks/implementations/python/src/stack_auth/models/oauth.py @@ -0,0 +1,25 @@ +"""OAuth models for Stack Auth.""" + +from __future__ import annotations + +from pydantic import Field + +from stack_auth.models._base import StackAuthModel + + +class OAuthConnection(StackAuthModel): + """A connected OAuth account for accessing third-party APIs.""" + + id: str + + +class OAuthProvider(StackAuthModel): + """An OAuth provider linked to a user's account.""" + + id: str + type: str + user_id: str = Field(alias="userId") + account_id: str | None = Field(None, alias="accountId") + email: str | None = None + allow_sign_in: bool = Field(True, alias="allowSignIn") + allow_connected_accounts: bool = Field(False, alias="allowConnectedAccounts") diff --git a/sdks/implementations/python/src/stack_auth/models/payments.py b/sdks/implementations/python/src/stack_auth/models/payments.py new file mode 100644 index 000000000..d839210db --- /dev/null +++ b/sdks/implementations/python/src/stack_auth/models/payments.py @@ -0,0 +1,27 @@ +"""Payment models for Stack Auth.""" + +from __future__ import annotations + +from pydantic import Field + +from stack_auth.models._base import StackAuthModel + + +class Item(StackAuthModel): + """A quantifiable item owned by a customer (user or team).""" + + display_name: str = Field(alias="displayName") + quantity: int = 0 + non_negative_quantity: int = Field(0, alias="nonNegativeQuantity") + + +class Product(StackAuthModel): + """A product associated with a customer.""" + + id: str | None = None + quantity: int = 0 + display_name: str = Field(alias="displayName") + customer_type: str = Field(alias="customerType") + is_server_only: bool = Field(False, alias="isServerOnly") + stackable: bool = False + type: str = "one_time" diff --git a/sdks/implementations/python/src/stack_auth/models/projects.py b/sdks/implementations/python/src/stack_auth/models/projects.py new file mode 100644 index 000000000..bdb4d8c9b --- /dev/null +++ b/sdks/implementations/python/src/stack_auth/models/projects.py @@ -0,0 +1,39 @@ +"""Project models for Stack Auth.""" + +from __future__ import annotations + +from typing import Any + +from pydantic import Field + +from stack_auth.models._base import StackAuthModel + + +class OAuthProviderConfig(StackAuthModel): + """Configuration for an OAuth provider.""" + + id: str + + +class ProjectConfig(StackAuthModel): + """Client-visible project configuration.""" + + sign_up_enabled: bool = Field(True, alias="signUpEnabled") + credential_enabled: bool = Field(True, alias="credentialEnabled") + magic_link_enabled: bool = Field(False, alias="magicLinkEnabled") + passkey_enabled: bool = Field(False, alias="passkeyEnabled") + oauth_providers: list[OAuthProviderConfig] = Field( + default_factory=list, alias="oauthProviders" + ) + client_team_creation_enabled: bool = Field(False, alias="clientTeamCreationEnabled") + client_user_deletion_enabled: bool = Field(False, alias="clientUserDeletionEnabled") + allow_user_api_keys: bool = Field(False, alias="allowUserApiKeys") + allow_team_api_keys: bool = Field(False, alias="allowTeamApiKeys") + + +class Project(StackAuthModel): + """Basic project information.""" + + id: str + display_name: str = Field(alias="displayName") + config: ProjectConfig