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
This commit is contained in:
Ejiro Asiuwhu
2026-03-24 22:23:58 +01:00
parent 28171d43cf
commit aecd4aa6e7
6 changed files with 207 additions and 0 deletions
@@ -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",
]
@@ -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")
@@ -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")
@@ -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")
@@ -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"
@@ -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