Skip to content

Registration

leadr.registration

Modules:

leadr.registration.adapters

Modules:

  • orm – Registration ORM models.
leadr.registration.adapters.orm

Registration ORM models.

Classes:

leadr.registration.adapters.orm.JamCodeORM

Bases: Base

Jam Code ORM model.

Represents a promotional code in the database. Maps to the jam_codes table. Used for tracking game jam codes, marketing campaigns, and referrals.

Functions:

  • from_domain – Convert domain entity to ORM model.
  • to_domain – Convert ORM model to domain entity.

Attributes:

# leadr.registration.adapters.orm.JamCodeORM.active
active: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True, server_default='true')
# leadr.registration.adapters.orm.JamCodeORM.code
code: Mapped[str] = mapped_column(String(50), nullable=False, unique=True, index=True)
# leadr.registration.adapters.orm.JamCodeORM.created_at
created_at: Mapped[timestamp]
# leadr.registration.adapters.orm.JamCodeORM.current_uses
current_uses: Mapped[int] = mapped_column(Integer, nullable=False, default=0, server_default='0')
# leadr.registration.adapters.orm.JamCodeORM.deleted_at
deleted_at: Mapped[nullable_timestamp]
# leadr.registration.adapters.orm.JamCodeORM.description
description: Mapped[str] = mapped_column(String, nullable=False)
# leadr.registration.adapters.orm.JamCodeORM.expires_at
expires_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
# leadr.registration.adapters.orm.JamCodeORM.features
features: Mapped[dict[str, Any]] = mapped_column(JSON, nullable=False, default={}, server_default='{}')
# leadr.registration.adapters.orm.JamCodeORM.from_domain
from_domain(domain)

Convert domain entity to ORM model.

Parameters:

  • domain (JamCode) – The domain entity to convert.

Returns:

# leadr.registration.adapters.orm.JamCodeORM.id
id: Mapped[uuid_pk]
# leadr.registration.adapters.orm.JamCodeORM.max_uses
max_uses: Mapped[int | None] = mapped_column(Integer, nullable=True)
# leadr.registration.adapters.orm.JamCodeORM.to_domain
to_domain()

Convert ORM model to domain entity.

Returns:

  • JamCode – The domain entity instance.
# leadr.registration.adapters.orm.JamCodeORM.updated_at
updated_at: Mapped[timestamp] = mapped_column(onupdate=(func.now()))
leadr.registration.adapters.orm.JamCodeRedemptionORM

Bases: Base

Jam Code Redemption ORM model.

Represents a single use of a jam code during registration. Maps to the jam_code_redemptions table with foreign keys to jam_codes and accounts. Tracks which account redeemed which code and when.

Functions:

  • from_domain – Convert domain entity to ORM model.
  • to_domain – Convert ORM model to domain entity.

Attributes:

# leadr.registration.adapters.orm.JamCodeRedemptionORM.account_id
account_id: Mapped[UUID] = mapped_column(ForeignKey('accounts.id', ondelete='CASCADE'), nullable=False, index=True)
# leadr.registration.adapters.orm.JamCodeRedemptionORM.created_at
created_at: Mapped[timestamp]
# leadr.registration.adapters.orm.JamCodeRedemptionORM.deleted_at
deleted_at: Mapped[nullable_timestamp]
# leadr.registration.adapters.orm.JamCodeRedemptionORM.from_domain
from_domain(domain)

Convert domain entity to ORM model.

Parameters:

Returns:

# leadr.registration.adapters.orm.JamCodeRedemptionORM.id
id: Mapped[uuid_pk]
# leadr.registration.adapters.orm.JamCodeRedemptionORM.jam_code_id
jam_code_id: Mapped[UUID] = mapped_column(ForeignKey('jam_codes.id', ondelete='CASCADE'), nullable=False, index=True)
# leadr.registration.adapters.orm.JamCodeRedemptionORM.meta
meta: Mapped[dict[str, Any]] = mapped_column(JSON, nullable=False, default={}, server_default='{}')
# leadr.registration.adapters.orm.JamCodeRedemptionORM.redeemed_at
redeemed_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False)
# leadr.registration.adapters.orm.JamCodeRedemptionORM.to_domain
to_domain()

Convert ORM model to domain entity.

Returns:

# leadr.registration.adapters.orm.JamCodeRedemptionORM.updated_at
updated_at: Mapped[timestamp] = mapped_column(onupdate=(func.now()))
leadr.registration.adapters.orm.VerificationCodeORM

Bases: Base

Verification Code ORM model.

Represents an email verification code in the database. Maps to the verification_codes table. Used during account registration to verify email ownership.

Functions:

  • from_domain – Convert domain entity to ORM model.
  • to_domain – Convert ORM model to domain entity.

Attributes:

# leadr.registration.adapters.orm.VerificationCodeORM.code
code: Mapped[str] = mapped_column(String(6), nullable=False)
# leadr.registration.adapters.orm.VerificationCodeORM.code_type
code_type: Mapped[VerificationCodeTypeEnum] = mapped_column(Enum(VerificationCodeTypeEnum, name='verification_code_type', native_enum=True, values_callable=(lambda x: [(e.value) for e in x])), nullable=False, default=(VerificationCodeTypeEnum.REGISTRATION), server_default='registration')
# leadr.registration.adapters.orm.VerificationCodeORM.created_at
created_at: Mapped[timestamp]
# leadr.registration.adapters.orm.VerificationCodeORM.deleted_at
deleted_at: Mapped[nullable_timestamp]
# leadr.registration.adapters.orm.VerificationCodeORM.email
email: Mapped[str] = mapped_column(String, nullable=False, index=True)
# leadr.registration.adapters.orm.VerificationCodeORM.expires_at
expires_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False, index=True)
# leadr.registration.adapters.orm.VerificationCodeORM.from_domain
from_domain(domain)

Convert domain entity to ORM model.

Parameters:

Returns:

# leadr.registration.adapters.orm.VerificationCodeORM.id
id: Mapped[uuid_pk]
# leadr.registration.adapters.orm.VerificationCodeORM.status
status: Mapped[VerificationCodeStatusEnum] = mapped_column(Enum(VerificationCodeStatusEnum, name='verification_code_status', native_enum=True, values_callable=(lambda x: [(e.value) for e in x])), nullable=False, default=(VerificationCodeStatusEnum.PENDING), server_default='pending')
# leadr.registration.adapters.orm.VerificationCodeORM.to_domain
to_domain()

Convert ORM model to domain entity.

Returns:

# leadr.registration.adapters.orm.VerificationCodeORM.updated_at
updated_at: Mapped[timestamp] = mapped_column(onupdate=(func.now()))
# leadr.registration.adapters.orm.VerificationCodeORM.used_at
used_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
# leadr.registration.adapters.orm.VerificationCodeORM.user_id
user_id: Mapped[UUID | None] = mapped_column(ForeignKey('users.id', ondelete='CASCADE'), nullable=True, index=True)
leadr.registration.adapters.orm.VerificationCodeStatusEnum

Bases: str, Enum

Verification code status enum for database.

Attributes:

# leadr.registration.adapters.orm.VerificationCodeStatusEnum.EXPIRED
EXPIRED = 'expired'
# leadr.registration.adapters.orm.VerificationCodeStatusEnum.PENDING
PENDING = 'pending'
# leadr.registration.adapters.orm.VerificationCodeStatusEnum.USED
USED = 'used'
leadr.registration.adapters.orm.VerificationCodeTypeEnum

Bases: str, Enum

Verification code type enum for database.

Attributes:

# leadr.registration.adapters.orm.VerificationCodeTypeEnum.INVITE
INVITE = 'invite'
# leadr.registration.adapters.orm.VerificationCodeTypeEnum.REGISTRATION
REGISTRATION = 'registration'

leadr.registration.api

Modules:

  • routes – Public registration API routes.
  • schemas – API schemas for registration endpoints.
leadr.registration.api.routes

Public registration API routes.

Functions:

Attributes:

leadr.registration.api.routes.complete_registration
complete_registration(request, registration_service)

Complete registration or invite acceptance.

This endpoint handles two flows based on the verification token type:

Registration flow (new account):

  • Creates account with the specified name and slug
  • Creates user as account owner
  • Creates API key for CLI authentication
  • Optionally redeems jam code

Invite flow (joining existing account):

  • Activates the invited user (changes status from INVITED to ACTIVE)
  • Creates API key for CLI authentication
  • account_name and jam_code are ignored

The API key is returned in plaintext and should be stored securely by the client.

leadr.registration.api.routes.create_jam_code
create_jam_code(request, jam_code_service, auth)

Create a new jam code (superadmin only).

Jam codes can be used for promotional campaigns, game jams, or referral tracking. They can optionally have usage limits, expiration dates, and custom features.

leadr.registration.api.routes.get_jam_code
get_jam_code(jam_code_id, jam_code_service, auth)

Get a specific jam code by ID (superadmin only).

leadr.registration.api.routes.initiate_registration
initiate_registration(request, verification_service)

Initiate registration by sending a verification code to the provided email.

This endpoint is publicly accessible and requires no authentication. A 6-character verification code will be sent to the email address.

leadr.registration.api.routes.invite_user
invite_user(request, invite_service, auth)

Invite a user to the authenticated admin's account.

Creates a user with INVITED status and sends an invite email with a verification code. If the user already exists with INVITED status, resends the invite (invalidates old code, sends new one).

Requires admin authentication.

leadr.registration.api.routes.list_jam_codes
list_jam_codes(jam_code_service, auth, pagination)

List all jam codes (superadmin only).

Returns a paginated list of all jam codes, including their usage statistics.

leadr.registration.api.routes.public_router
public_router = APIRouter(prefix='/register')
leadr.registration.api.routes.resend_verification_code
resend_verification_code(request, verification_service)

Resend a verification code to the provided email.

This endpoint invalidates any existing codes for the email and sends a new one.

leadr.registration.api.routes.router
router = APIRouter()
leadr.registration.api.routes.update_jam_code
update_jam_code(jam_code_id, request, jam_code_service, auth)

Update a jam code (superadmin only).

Can update description, features, max uses, active status, and expiration.

leadr.registration.api.routes.verify_code
verify_code(request, verification_service)

Verify an email verification code and return a temporary token.

This endpoint validates the verification code and returns a short-lived token that can be used to complete the registration process. The response includes the type (REGISTRATION or INVITE) so the client can determine which fields to prompt for.

leadr.registration.api.schemas

API schemas for registration endpoints.

Classes:

leadr.registration.api.schemas.CompleteRegistrationRequest

Bases: BaseModel

Request to complete registration or invite acceptance.

Used for both new account registration and invited user activation. The verification token type determines which flow is executed.

Functions:

Attributes:

# leadr.registration.api.schemas.CompleteRegistrationRequest.account_name
account_name: str | None = Field(default=None, description='Name for the new account (required for registration, ignored for invite)')
# leadr.registration.api.schemas.CompleteRegistrationRequest.account_slug
account_slug: str | None = Field(default=None, description='Optional URL slug (auto-generated if not provided)')
# leadr.registration.api.schemas.CompleteRegistrationRequest.display_name
display_name: str | None = Field(default=None, description='Optional display name for user (auto-generated from email if not provided)')
# leadr.registration.api.schemas.CompleteRegistrationRequest.jam_code
jam_code: str | None = Field(default=None, description='Optional jam/promo code')
# leadr.registration.api.schemas.CompleteRegistrationRequest.normalize_display_name
normalize_display_name(value)

Convert empty/whitespace strings to None.

# leadr.registration.api.schemas.CompleteRegistrationRequest.verification_token
verification_token: str = Field(description='Token from code verification step')
leadr.registration.api.schemas.CompleteRegistrationResponse

Bases: BaseModel

Response after completing registration or invite acceptance.

Functions:

  • from_domain – Create response from domain entities.

Attributes:

# leadr.registration.api.schemas.CompleteRegistrationResponse.account_id
account_id: AccountID = Field(description='ID of the created account')
# leadr.registration.api.schemas.CompleteRegistrationResponse.account_name
account_name: str = Field(description='Name of the account')
# leadr.registration.api.schemas.CompleteRegistrationResponse.account_slug
account_slug: str = Field(description='URL slug of the account')
# leadr.registration.api.schemas.CompleteRegistrationResponse.api_key
api_key: str = Field(description='API key for authentication')
# leadr.registration.api.schemas.CompleteRegistrationResponse.display_name
display_name: str = Field(description='Display name of the created user')
# leadr.registration.api.schemas.CompleteRegistrationResponse.from_domain
from_domain(account, user, api_key)

Create response from domain entities.

Parameters:

  • account – Account domain entity.
  • user – User domain entity.
  • api_key (str) – API key string.

Returns:

leadr.registration.api.schemas.CreateJamCodeRequest

Bases: BaseModel

Request to create a new jam code.

Attributes:

# leadr.registration.api.schemas.CreateJamCodeRequest.code
code: str = Field(description='Alphanumeric code (3-50 characters)', min_length=3, max_length=50)
# leadr.registration.api.schemas.CreateJamCodeRequest.description
description: str = Field(description='Human-readable description')
# leadr.registration.api.schemas.CreateJamCodeRequest.expires_at
expires_at: datetime | None = Field(default=None, description='Expiration date (null = never)')
# leadr.registration.api.schemas.CreateJamCodeRequest.features
features: dict = Field(default_factory=dict, description='Features/config for this code')
# leadr.registration.api.schemas.CreateJamCodeRequest.max_uses
max_uses: int | None = Field(default=None, description='Maximum redemptions (null = unlimited)')
leadr.registration.api.schemas.InitiateRegistrationRequest

Bases: BaseModel

Request to initiate registration by sending verification code.

Attributes:

# leadr.registration.api.schemas.InitiateRegistrationRequest.email
email: EmailStr = Field(description='Email address to send verification code to')
leadr.registration.api.schemas.InitiateRegistrationResponse

Bases: BaseModel

Response after initiating registration.

Attributes:

# leadr.registration.api.schemas.InitiateRegistrationResponse.code_expires_in
code_expires_in: int = Field(description='Seconds until the code expires')
# leadr.registration.api.schemas.InitiateRegistrationResponse.message
message: str = Field(description='Success message')
leadr.registration.api.schemas.InviteUserRequest

Bases: BaseModel

Request to invite a user to an account.

Attributes:

# leadr.registration.api.schemas.InviteUserRequest.display_name
display_name: str | None = Field(default=None, description='Optional display name (defaults to email prefix if not provided)')
# leadr.registration.api.schemas.InviteUserRequest.email
email: EmailStr = Field(description='Email address to invite')
leadr.registration.api.schemas.InviteUserResponse

Bases: BaseModel

Response after inviting a user.

Functions:

  • from_domain – Create response from domain entity.

Attributes:

# leadr.registration.api.schemas.InviteUserResponse.email
email: str = Field(description='Email address of the invited user')
# leadr.registration.api.schemas.InviteUserResponse.from_domain
from_domain(user)

Create response from domain entity.

Parameters:

  • user – User domain entity.

Returns:

# leadr.registration.api.schemas.InviteUserResponse.message
message: str = Field(description='Success message')
# leadr.registration.api.schemas.InviteUserResponse.status
status: str = Field(description='User status (INVITED)')
# leadr.registration.api.schemas.InviteUserResponse.user_id
user_id: UserID = Field(description='ID of the invited user')
leadr.registration.api.schemas.JamCodeRedemptionResponse

Bases: BaseModel

Response representing a jam code redemption.

Functions:

  • from_domain – Create response from domain entity.

Attributes:

# leadr.registration.api.schemas.JamCodeRedemptionResponse.account_id
account_id: AccountID
# leadr.registration.api.schemas.JamCodeRedemptionResponse.from_domain
from_domain(redemption)

Create response from domain entity.

Parameters:

  • redemption – JamCodeRedemption domain entity.

Returns:

# leadr.registration.api.schemas.JamCodeRedemptionResponse.id
id: JamCodeRedemptionID
# leadr.registration.api.schemas.JamCodeRedemptionResponse.jam_code_id
jam_code_id: JamCodeID
# leadr.registration.api.schemas.JamCodeRedemptionResponse.meta
meta: dict
# leadr.registration.api.schemas.JamCodeRedemptionResponse.redeemed_at
redeemed_at: datetime
leadr.registration.api.schemas.JamCodeResponse

Bases: BaseModel

Response representing a jam code.

Functions:

  • from_domain – Create response from domain entity.

Attributes:

# leadr.registration.api.schemas.JamCodeResponse.active
active: bool
# leadr.registration.api.schemas.JamCodeResponse.code
code: str
# leadr.registration.api.schemas.JamCodeResponse.created_at
created_at: datetime
# leadr.registration.api.schemas.JamCodeResponse.current_uses
current_uses: int
# leadr.registration.api.schemas.JamCodeResponse.description
description: str
# leadr.registration.api.schemas.JamCodeResponse.expires_at
expires_at: datetime | None
# leadr.registration.api.schemas.JamCodeResponse.features
features: dict
# leadr.registration.api.schemas.JamCodeResponse.from_domain
from_domain(jam_code)

Create response from domain entity.

Parameters:

  • jam_code – JamCode domain entity.

Returns:

# leadr.registration.api.schemas.JamCodeResponse.id
id: JamCodeID
# leadr.registration.api.schemas.JamCodeResponse.max_uses
max_uses: int | None
# leadr.registration.api.schemas.JamCodeResponse.updated_at
updated_at: datetime
leadr.registration.api.schemas.UpdateJamCodeRequest

Bases: BaseModel

Request to update a jam code.

Attributes:

# leadr.registration.api.schemas.UpdateJamCodeRequest.active
active: bool | None = Field(default=None, description='New active status')
# leadr.registration.api.schemas.UpdateJamCodeRequest.description
description: str | None = Field(default=None, description='New description')
# leadr.registration.api.schemas.UpdateJamCodeRequest.expires_at
expires_at: datetime | None = Field(default=None, description='New expiration date')
# leadr.registration.api.schemas.UpdateJamCodeRequest.features
features: dict | None = Field(default=None, description='New features/config')
# leadr.registration.api.schemas.UpdateJamCodeRequest.max_uses
max_uses: int | None = Field(default=None, description='New max uses')
leadr.registration.api.schemas.VerifyCodeRequest

Bases: BaseModel

Request to verify an email verification code.

Attributes:

# leadr.registration.api.schemas.VerifyCodeRequest.code
code: str = Field(description='6-character verification code', min_length=6, max_length=6)
# leadr.registration.api.schemas.VerifyCodeRequest.email
email: EmailStr = Field(description='Email address')
leadr.registration.api.schemas.VerifyCodeResponse

Bases: BaseModel

Response after verifying a code.

Attributes:

# leadr.registration.api.schemas.VerifyCodeResponse.expires_in
expires_in: int = Field(description='Seconds until the token expires')
# leadr.registration.api.schemas.VerifyCodeResponse.type
type: str = Field(description='Type of verification: REGISTRATION for new accounts, INVITE for invited users')
# leadr.registration.api.schemas.VerifyCodeResponse.verification_token
verification_token: str = Field(description='Temporary token for completing registration')

leadr.registration.domain

Modules:

  • jam_code – Jam code domain models for promotional codes and special features.
  • jam_code_redemption – Jam code redemption domain models for tracking code usage.
  • verification_code – Verification code domain models for email verification during registration.
leadr.registration.domain.jam_code

Jam code domain models for promotional codes and special features.

Classes:

  • JamCode – Jam code domain entity.
leadr.registration.domain.jam_code.JamCode

Bases: Entity

Jam code domain entity.

Represents a promotional code that grants special features or access during registration. Codes can be used for game jams, marketing campaigns, or referral tracking. Supports optional usage limits, expiration dates, and custom feature flags stored as JSON.

Functions:

  • activate – Activate the jam code, allowing redemptions.
  • deactivate – Deactivate the jam code, preventing further redemptions.
  • get_feature – Get a feature value from the features dictionary.
  • has_uses_remaining – Check if the jam code has remaining uses.
  • increment_uses – Increment the usage count by one.
  • is_expired – Check if the jam code has expired.
  • is_valid – Check if the jam code is valid and can be redeemed.
  • restore – Restore a soft-deleted entity.
  • soft_delete – Mark entity as soft-deleted.
  • validate_code – Validate and normalize the jam code.

Attributes:

# leadr.registration.domain.jam_code.JamCode.activate
activate()

Activate the jam code, allowing redemptions.

Used to re-enable a previously deactivated code.

# leadr.registration.domain.jam_code.JamCode.active
active: bool = Field(default=True, description='Whether this code can currently be redeemed')
# leadr.registration.domain.jam_code.JamCode.code
code: str = Field(description='Alphanumeric code (3-50 characters, case-insensitive)', min_length=3, max_length=50)
# leadr.registration.domain.jam_code.JamCode.created_at
created_at: datetime = Field(default_factory=(lambda: datetime.now(UTC)), description='Timestamp when entity was created (UTC)')
# leadr.registration.domain.jam_code.JamCode.current_uses
current_uses: int = Field(default=0, description='Current number of times this code has been redeemed')
# leadr.registration.domain.jam_code.JamCode.deactivate
deactivate()

Deactivate the jam code, preventing further redemptions.

Used to manually disable a code (e.g., if it's compromised or no longer needed).

# leadr.registration.domain.jam_code.JamCode.deleted_at
deleted_at: datetime | None = Field(default=None, description='Timestamp when entity was soft-deleted (UTC), or null if active')
# leadr.registration.domain.jam_code.JamCode.description
description: str = Field(description="Human-readable description of this code's purpose")
# leadr.registration.domain.jam_code.JamCode.expires_at
expires_at: datetime | None = Field(default=None, description='When this code expires (None = never expires)')
# leadr.registration.domain.jam_code.JamCode.features
features: dict[str, Any] = Field(default_factory=dict, description='Custom features/config for this code (e.g., CLI templates, score limits)')
# leadr.registration.domain.jam_code.JamCode.get_feature
get_feature(key, default=None)

Get a feature value from the features dictionary.

Parameters:

  • key (str) – The feature key to retrieve.
  • default (Any) – Default value if the key doesn't exist.

Returns:

  • Any – The feature value or the default.
# leadr.registration.domain.jam_code.JamCode.has_uses_remaining
has_uses_remaining()

Check if the jam code has remaining uses.

Returns:

  • bool – True if the code has no usage limit or has not reached its limit.
# leadr.registration.domain.jam_code.JamCode.id
id: Any = Field(frozen=True, default_factory=uuid4, description='Unique identifier (auto-generated UUID or typed ID)')
# leadr.registration.domain.jam_code.JamCode.increment_uses
increment_uses()

Increment the usage count by one.

Called when a jam code is successfully redeemed during registration.

# leadr.registration.domain.jam_code.JamCode.is_deleted
is_deleted: bool

Check if entity is soft-deleted.

Returns:

  • bool – True if the entity has a deleted_at timestamp, False otherwise.
# leadr.registration.domain.jam_code.JamCode.is_expired
is_expired()

Check if the jam code has expired.

Returns:

  • bool – True if the code has an expiration date and it has passed.
# leadr.registration.domain.jam_code.JamCode.is_valid
is_valid()

Check if the jam code is valid and can be redeemed.

A code is valid if it's active, not expired, and has uses remaining.

Returns:

  • bool – True if the code can be used for registration.
# leadr.registration.domain.jam_code.JamCode.max_uses
max_uses: int | None = Field(default=None, description='Maximum number of redemptions allowed (None = unlimited)')
# leadr.registration.domain.jam_code.JamCode.model_config
model_config = ConfigDict(validate_assignment=True)
# leadr.registration.domain.jam_code.JamCode.restore
restore()

Restore a soft-deleted entity.

Clears the deleted_at timestamp, making the entity active again.

Example > > > account.soft_delete() > > > account.restore() > > > assert account.is_deleted is False
# leadr.registration.domain.jam_code.JamCode.soft_delete
soft_delete()

Mark entity as soft-deleted.

Sets the deleted_at timestamp to the current UTC time. Entities that are already deleted are not affected (deleted_at remains at original deletion time).

Example > > > account = Account(name="Test", slug="test") > > > account.soft_delete() > > > assert account.is_deleted is True
# leadr.registration.domain.jam_code.JamCode.updated_at
updated_at: datetime = Field(default_factory=(lambda: datetime.now(UTC)), description='Timestamp of last update (UTC)')
# leadr.registration.domain.jam_code.JamCode.validate_code
validate_code(v)

Validate and normalize the jam code.

Parameters:

  • v (str) – The code value to validate.

Returns:

  • str – The normalized (uppercase) code.

Raises:

  • ValueError – If the code contains non-alphanumeric characters.
leadr.registration.domain.jam_code_redemption

Jam code redemption domain models for tracking code usage.

Classes:

leadr.registration.domain.jam_code_redemption.JamCodeRedemption

Bases: Entity

Jam code redemption domain entity.

Represents a single use of a jam code during account registration. Tracks which account redeemed which code, when it was redeemed, and any associated metadata (e.g., CLI configuration, user agent).

Functions:

  • get_meta – Get a metadata value from the meta dictionary.
  • restore – Restore a soft-deleted entity.
  • soft_delete – Mark entity as soft-deleted.

Attributes:

# leadr.registration.domain.jam_code_redemption.JamCodeRedemption.account_id
account_id: AccountID = Field(description='ID of the account that redeemed the code')
# leadr.registration.domain.jam_code_redemption.JamCodeRedemption.created_at
created_at: datetime = Field(default_factory=(lambda: datetime.now(UTC)), description='Timestamp when entity was created (UTC)')
# leadr.registration.domain.jam_code_redemption.JamCodeRedemption.deleted_at
deleted_at: datetime | None = Field(default=None, description='Timestamp when entity was soft-deleted (UTC), or null if active')
# leadr.registration.domain.jam_code_redemption.JamCodeRedemption.get_meta
get_meta(key, default=None)

Get a metadata value from the meta dictionary.

Parameters:

  • key (str) – The metadata key to retrieve.
  • default (Any) – Default value if the key doesn't exist.

Returns:

  • Any – The metadata value or the default.
# leadr.registration.domain.jam_code_redemption.JamCodeRedemption.id
id: Any = Field(frozen=True, default_factory=uuid4, description='Unique identifier (auto-generated UUID or typed ID)')
# leadr.registration.domain.jam_code_redemption.JamCodeRedemption.is_deleted
is_deleted: bool

Check if entity is soft-deleted.

Returns:

  • bool – True if the entity has a deleted_at timestamp, False otherwise.
# leadr.registration.domain.jam_code_redemption.JamCodeRedemption.jam_code_id
jam_code_id: UUID = Field(description='ID of the jam code that was redeemed')
# leadr.registration.domain.jam_code_redemption.JamCodeRedemption.meta
meta: dict[str, Any] = Field(default_factory=dict, description='Additional metadata about the redemption (e.g., CLI config, user agent)')
# leadr.registration.domain.jam_code_redemption.JamCodeRedemption.model_config
model_config = ConfigDict(validate_assignment=True)
# leadr.registration.domain.jam_code_redemption.JamCodeRedemption.redeemed_at
redeemed_at: datetime = Field(default_factory=(lambda: datetime.now(UTC)), description='When the code was redeemed (UTC)')
# leadr.registration.domain.jam_code_redemption.JamCodeRedemption.restore
restore()

Restore a soft-deleted entity.

Clears the deleted_at timestamp, making the entity active again.

Example > > > account.soft_delete() > > > account.restore() > > > assert account.is_deleted is False
# leadr.registration.domain.jam_code_redemption.JamCodeRedemption.soft_delete
soft_delete()

Mark entity as soft-deleted.

Sets the deleted_at timestamp to the current UTC time. Entities that are already deleted are not affected (deleted_at remains at original deletion time).

Example > > > account = Account(name="Test", slug="test") > > > account.soft_delete() > > > assert account.is_deleted is True
# leadr.registration.domain.jam_code_redemption.JamCodeRedemption.updated_at
updated_at: datetime = Field(default_factory=(lambda: datetime.now(UTC)), description='Timestamp of last update (UTC)')
leadr.registration.domain.verification_code

Verification code domain models for email verification during registration.

Classes:

leadr.registration.domain.verification_code.VerificationCode

Bases: Entity

Verification code domain entity.

Represents a one-time email verification code used during registration or invite flows. Codes are 6-character alphanumeric strings with configurable expiration windows (10 minutes for registration, 24 hours for invites by default). Once used or expired, codes become invalid and cannot be reused.

The code_type field distinguishes between REGISTRATION codes (for new account signup) and INVITE codes (for invited users joining an existing account).

Functions:

  • is_expired – Check if the verification code has expired.
  • is_used – Check if the verification code has been used.
  • is_valid – Check if the verification code is valid and can be used.
  • mark_as_expired – Mark the verification code as expired.
  • mark_as_used – Mark the verification code as used.
  • restore – Restore a soft-deleted entity.
  • soft_delete – Mark entity as soft-deleted.
  • validate_code – Validate and normalize the verification code.

Attributes:

# leadr.registration.domain.verification_code.VerificationCode.code
code: str = Field(description='6-character alphanumeric verification code (case-insensitive)', min_length=6, max_length=6)
# leadr.registration.domain.verification_code.VerificationCode.code_type
code_type: VerificationCodeType = Field(default=(VerificationCodeType.REGISTRATION), description='Type of verification code (registration or invite)')
# leadr.registration.domain.verification_code.VerificationCode.created_at
created_at: datetime = Field(default_factory=(lambda: datetime.now(UTC)), description='Timestamp when entity was created (UTC)')
# leadr.registration.domain.verification_code.VerificationCode.deleted_at
deleted_at: datetime | None = Field(default=None, description='Timestamp when entity was soft-deleted (UTC), or null if active')
# leadr.registration.domain.verification_code.VerificationCode.email
email: EmailStr = Field(description='Email address this code was sent to')
# leadr.registration.domain.verification_code.VerificationCode.expires_at
expires_at: datetime = Field(description='When this code expires (UTC)')
# leadr.registration.domain.verification_code.VerificationCode.id
id: Any = Field(frozen=True, default_factory=uuid4, description='Unique identifier (auto-generated UUID or typed ID)')
# leadr.registration.domain.verification_code.VerificationCode.is_deleted
is_deleted: bool

Check if entity is soft-deleted.

Returns:

  • bool – True if the entity has a deleted_at timestamp, False otherwise.
# leadr.registration.domain.verification_code.VerificationCode.is_expired
is_expired()

Check if the verification code has expired.

Returns:

  • bool – True if the code's expiration time has passed.
# leadr.registration.domain.verification_code.VerificationCode.is_invite
is_invite: bool

Check if this is an invite code.

# leadr.registration.domain.verification_code.VerificationCode.is_registration
is_registration: bool

Check if this is a registration code.

# leadr.registration.domain.verification_code.VerificationCode.is_used
is_used()

Check if the verification code has been used.

Returns:

  • bool – True if the code status is USED.
# leadr.registration.domain.verification_code.VerificationCode.is_valid
is_valid()

Check if the verification code is valid and can be used.

A code is valid if it hasn't been used and hasn't expired.

Returns:

  • bool – True if the code is valid and can be used for verification.
# leadr.registration.domain.verification_code.VerificationCode.mark_as_expired
mark_as_expired()

Mark the verification code as expired.

Sets the status to EXPIRED. This is typically done when cleaning up old codes or when explicitly invalidating codes.

# leadr.registration.domain.verification_code.VerificationCode.mark_as_used
mark_as_used()

Mark the verification code as used.

Sets the status to USED and records the current timestamp in used_at. Once marked as used, the code cannot be reused.

# leadr.registration.domain.verification_code.VerificationCode.model_config
model_config = ConfigDict(validate_assignment=True)
# leadr.registration.domain.verification_code.VerificationCode.restore
restore()

Restore a soft-deleted entity.

Clears the deleted_at timestamp, making the entity active again.

Example > > > account.soft_delete() > > > account.restore() > > > assert account.is_deleted is False
# leadr.registration.domain.verification_code.VerificationCode.soft_delete
soft_delete()

Mark entity as soft-deleted.

Sets the deleted_at timestamp to the current UTC time. Entities that are already deleted are not affected (deleted_at remains at original deletion time).

Example > > > account = Account(name="Test", slug="test") > > > account.soft_delete() > > > assert account.is_deleted is True
# leadr.registration.domain.verification_code.VerificationCode.status
status: VerificationCodeStatus = VerificationCodeStatus.PENDING
# leadr.registration.domain.verification_code.VerificationCode.updated_at
updated_at: datetime = Field(default_factory=(lambda: datetime.now(UTC)), description='Timestamp of last update (UTC)')
# leadr.registration.domain.verification_code.VerificationCode.used_at
used_at: datetime | None = None
# leadr.registration.domain.verification_code.VerificationCode.user_id
user_id: UserID | None = Field(default=None, description='User ID for invite codes (links invite to existing user record)')
# leadr.registration.domain.verification_code.VerificationCode.validate_code
validate_code(v)

Validate and normalize the verification code.

Parameters:

  • v (str) – The code value to validate.

Returns:

  • str – The normalized (uppercase) code.

Raises:

  • ValueError – If the code contains non-alphanumeric characters.
leadr.registration.domain.verification_code.VerificationCodeStatus

Bases: Enum

Verification code status enumeration.

Attributes:

# leadr.registration.domain.verification_code.VerificationCodeStatus.EXPIRED
EXPIRED = 'expired'
# leadr.registration.domain.verification_code.VerificationCodeStatus.PENDING
PENDING = 'pending'
# leadr.registration.domain.verification_code.VerificationCodeStatus.USED
USED = 'used'
leadr.registration.domain.verification_code.VerificationCodeType

Bases: str, Enum

Verification code type enumeration.

Distinguishes between codes used for initial registration and codes used for user invitations.

Attributes:

  • INVITE – Code for invited user to join an existing account.
  • REGISTRATION – Code for new account registration flow.
# leadr.registration.domain.verification_code.VerificationCodeType.INVITE
INVITE = 'invite'

Code for invited user to join an existing account.

# leadr.registration.domain.verification_code.VerificationCodeType.REGISTRATION
REGISTRATION = 'registration'

Code for new account registration flow.

leadr.registration.services

Modules:

  • dependencies – Dependency injection for registration services.
  • invite_service – Invite service for managing user invitations to accounts.
  • jam_code_service – Jam code service for managing promotional codes.
  • registration_service – Registration service for orchestrating account creation and invite completion flows.
  • repositories – Registration repository services for verification codes and jam codes.
  • verification_service – Verification service for generating and validating email verification codes.
leadr.registration.services.dependencies

Dependency injection for registration services.

Functions:

Attributes:

leadr.registration.services.dependencies.EmailServiceDep
EmailServiceDep = Annotated[EmailService, Depends(get_email_service)]
leadr.registration.services.dependencies.InviteServiceDep
InviteServiceDep = Annotated[InviteService, Depends(get_invite_service)]
leadr.registration.services.dependencies.JamCodeServiceDep
JamCodeServiceDep = Annotated[JamCodeService, Depends(get_jam_code_service)]
leadr.registration.services.dependencies.RegistrationServiceDep
RegistrationServiceDep = Annotated[RegistrationService, Depends(get_registration_service)]
leadr.registration.services.dependencies.VerificationServiceDep
VerificationServiceDep = Annotated[VerificationService, Depends(get_verification_service)]
leadr.registration.services.dependencies.get_email_service
get_email_service(db)

Get EmailService dependency.

Parameters:

Returns:

leadr.registration.services.dependencies.get_invite_service
get_invite_service(db, account_service, user_service, verification_service, email_service)

Get InviteService dependency.

Parameters:

Returns:

leadr.registration.services.dependencies.get_jam_code_service
get_jam_code_service(db)

Get JamCodeService dependency.

Parameters:

Returns:

leadr.registration.services.dependencies.get_registration_service
get_registration_service(db, account_service, user_service, api_key_service, verification_service, jam_code_service, email_service)

Get RegistrationService dependency.

Parameters:

Returns:

leadr.registration.services.dependencies.get_verification_service
get_verification_service(db, email_service)

Get VerificationService dependency.

Parameters:

Returns:

leadr.registration.services.invite_service

Invite service for managing user invitations to accounts.

Classes:

Attributes:

leadr.registration.services.invite_service.InviteService
InviteService(db, account_service, user_service, verification_service, email_service)

Service for managing user invitations.

Coordinates the invite flow:

  1. Create invited user with INVITED status
  2. Create invite verification code
  3. Send invite email

Functions:

Attributes:

Parameters:

  • db (AsyncSession) – Database session.
  • account_service (AccountService) – Account service for fetching account info.
  • user_service (UserService) – User service for creating users.
  • verification_service (VerificationService) – Verification service for creating invite codes.
  • email_service (EmailService) – Email service for sending invite emails.
# leadr.registration.services.invite_service.InviteService.account_service
account_service = account_service
# leadr.registration.services.invite_service.InviteService.db
db = db
# leadr.registration.services.invite_service.InviteService.email_service
email_service = email_service
# leadr.registration.services.invite_service.InviteService.send_invite
send_invite(email, account_id, display_name=None)

Invite a user to an account.

Creates a user with INVITED status and sends an invite email with a verification code. If the user already exists with INVITED status, resends the invite (invalidates old code, creates new one).

Parameters:

  • email (str) – Email address to invite.
  • account_id (AccountID) – The account ID to invite the user to.
  • display_name (str | None) – Optional display name. Defaults to email prefix if not provided.

Returns:

  • User – The created or existing User entity with INVITED status.

Raises:

  • ValueError – If user already exists with non-INVITED status.
  • ValueError – If account doesn't exist.
# leadr.registration.services.invite_service.InviteService.user_service
user_service = user_service
# leadr.registration.services.invite_service.InviteService.verification_service
verification_service = verification_service
leadr.registration.services.invite_service.logger
logger = get_logger(__name__)
leadr.registration.services.jam_code_service

Jam code service for managing promotional codes.

Classes:

  • JamCodeService – Service for managing jam codes and redemptions.

Attributes:

leadr.registration.services.jam_code_service.JamCodeService
JamCodeService(db)

Service for managing jam codes and redemptions.

Functions:

Attributes:

Parameters:

# leadr.registration.services.jam_code_service.JamCodeService.create_jam_code
create_jam_code(code, description, features=None, max_uses=None, expires_at=None)

Create a new jam code.

Parameters:

  • code (str) – The code value (will be normalized to uppercase).
  • description (str) – Human-readable description.
  • features (dict | None) – Optional features dictionary.
  • max_uses (int | None) – Optional maximum number of redemptions.
  • expires_at (datetime | None) – Optional expiration date.

Returns:

  • JamCode – The created jam code.

Raises:

  • ValueError – If a jam code with this code already exists.
# leadr.registration.services.jam_code_service.JamCodeService.db
db = db
# leadr.registration.services.jam_code_service.JamCodeService.get_jam_code_by_id
get_jam_code_by_id(jam_code_id)

Get a jam code by its ID.

Parameters:

  • jam_code_id (UUID) – The jam code ID.

Returns:

  • JamCode | None – The jam code if found, None otherwise.
# leadr.registration.services.jam_code_service.JamCodeService.jam_code_repository
jam_code_repository = JamCodeRepository(db)
# leadr.registration.services.jam_code_service.JamCodeService.list_jam_codes
list_jam_codes(*, pagination)

List all jam codes with pagination.

Parameters:

Returns:

# leadr.registration.services.jam_code_service.JamCodeService.redeem_jam_code
redeem_jam_code(jam_code, account_id, meta=None)

Redeem a jam code for an account.

Parameters:

  • jam_code (JamCode) – The jam code to redeem.
  • account_id (AccountID) – The account redeeming the code.
  • meta (dict | None) – Optional metadata to store with the redemption.

Returns:

Raises:

  • ValueError – If the jam code has already been redeemed by this account.
# leadr.registration.services.jam_code_service.JamCodeService.redemption_repository
redemption_repository = JamCodeRedemptionRepository(db)
# leadr.registration.services.jam_code_service.JamCodeService.update_jam_code
update_jam_code(jam_code_id, description=None, features=None, max_uses=None, active=None, expires_at=None)

Update a jam code.

Parameters:

  • jam_code_id (UUID) – The jam code ID.
  • description (str | None) – Optional new description.
  • features (dict | None) – Optional new features dictionary.
  • max_uses (int | None) – Optional new max uses.
  • active (bool | None) – Optional new active status.
  • expires_at (datetime | None) – Optional new expiration date.

Returns:

  • JamCode – The updated jam code.

Raises:

  • ValueError – If the jam code doesn't exist.
# leadr.registration.services.jam_code_service.JamCodeService.validate_and_get_jam_code
validate_and_get_jam_code(code)

Validate a jam code and return it if valid.

Parameters:

  • code (str) – The jam code to validate.

Returns:

  • JamCode | None – The jam code if valid, None if invalid or not found.
leadr.registration.services.jam_code_service.logger
logger = get_logger(__name__)
leadr.registration.services.registration_service

Registration service for orchestrating account creation and invite completion flows.

Classes:

  • RegistrationService – Service for orchestrating registration and invite completion flows.

Attributes:

leadr.registration.services.registration_service.RegistrationService
RegistrationService(db, account_service, user_service, api_key_service, verification_service, jam_code_service, email_service)

Service for orchestrating registration and invite completion flows.

Handles two distinct flows:

  • Registration: Creates new account, user (as owner), and API key
  • Invite: Activates existing invited user and creates API key

Functions:

  • complete_registration – Complete the registration process and create account, user, and API key.

Attributes:

Parameters:

  • db (AsyncSession) – Database session.
  • account_service (AccountService) – Service for account operations.
  • user_service (UserService) – Service for user operations.
  • api_key_service (APIKeyService) – Service for API key operations.
  • verification_service (VerificationService) – Service for email verification.
  • jam_code_service (JamCodeService) – Service for jam code validation.
  • email_service (EmailService) – Service for sending emails.
# leadr.registration.services.registration_service.RegistrationService.account_service
account_service = account_service
# leadr.registration.services.registration_service.RegistrationService.api_key_service
api_key_service = api_key_service
# leadr.registration.services.registration_service.RegistrationService.complete_registration
complete_registration(verification_token, account_name=None, account_slug=None, jam_code=None, display_name=None)

Complete the registration process and create account, user, and API key.

For invite flow: If the verification token contains a user_id, this is an invite completion. The existing invited user is activated and an API key is created. Account creation is skipped.

For registration flow: A new account, user, and API key are created.

Parameters:

  • verification_token (str) – JWT token from email verification.
  • account_name (str | None) – Name for the new account (required for registration, ignored for invite).
  • account_slug (str | None) – Optional slug (will be auto-generated if not provided).
  • jam_code (str | None) – Optional jam code for promotional features (registration only).
  • display_name (str | None) – Optional display name (will use email prefix if not provided).

Returns:

Raises:

  • ValueError – If verification token is invalid or jam code is invalid.
  • ValueError – If account_name is missing for registration flow.
# leadr.registration.services.registration_service.RegistrationService.db
db = db
# leadr.registration.services.registration_service.RegistrationService.email_service
email_service = email_service
# leadr.registration.services.registration_service.RegistrationService.jam_code_service
jam_code_service = jam_code_service
# leadr.registration.services.registration_service.RegistrationService.user_service
user_service = user_service
# leadr.registration.services.registration_service.RegistrationService.verification_service
verification_service = verification_service
leadr.registration.services.registration_service.logger
logger = get_logger(__name__)
leadr.registration.services.repositories

Registration repository services for verification codes and jam codes.

Classes:

leadr.registration.services.repositories.JamCodeRedemptionRepository

Bases: BaseRepository[JamCodeRedemption, JamCodeRedemptionORM]

Jam code redemption repository for tracking code usage.

Functions:

  • create – Create a new entity in the database.
  • delete – Soft delete an entity by setting its deleted_at timestamp.
  • filter – Filter jam code redemptions by criteria with pagination.
  • find_by_account – Find all jam code redemptions for an account.
  • get_by_id – Get an entity by its ID.
  • has_redeemed – Check if an account has already redeemed a specific jam code.
  • update – Update an existing entity in the database.

Attributes:

# leadr.registration.services.repositories.JamCodeRedemptionRepository.SORTABLE_FIELDS
SORTABLE_FIELDS = {'id', 'account_id', 'jam_code_id', 'created_at'}
# leadr.registration.services.repositories.JamCodeRedemptionRepository.create
create(entity)

Create a new entity in the database.

Parameters:

Returns:

  • DomainEntityT – Created domain entity with refreshed data
# leadr.registration.services.repositories.JamCodeRedemptionRepository.delete
delete(entity_id)

Soft delete an entity by setting its deleted_at timestamp.

Parameters:

Raises:

# leadr.registration.services.repositories.JamCodeRedemptionRepository.filter
filter(account_id=None, *, pagination, **kwargs)

Filter jam code redemptions by criteria with pagination.

Parameters:

  • account_id (Any | None) – Optional account ID to filter by.
  • pagination (PaginationParams) – Pagination parameters (required).
  • **kwargs (Any) – Additional filter parameters.

Returns:

Raises:

# leadr.registration.services.repositories.JamCodeRedemptionRepository.find_by_account
find_by_account(account_id)

Find all jam code redemptions for an account.

Parameters:

  • account_id (AccountID) – The account ID.

Returns:

# leadr.registration.services.repositories.JamCodeRedemptionRepository.get_by_id
get_by_id(entity_id, include_deleted=False)

Get an entity by its ID.

Parameters:

  • entity_id (UUID4 | PrefixedID) – Entity ID to retrieve
  • include_deleted (bool) – If True, include soft-deleted entities. Defaults to False.

Returns:

  • DomainEntityT | None – Domain entity if found, None otherwise
# leadr.registration.services.repositories.JamCodeRedemptionRepository.has_redeemed
has_redeemed(account_id, jam_code_id)

Check if an account has already redeemed a specific jam code.

Parameters:

  • account_id (AccountID) – The account ID.
  • jam_code_id (UUID) – The jam code ID.

Returns:

  • bool – True if the account has redeemed this code, False otherwise.
# leadr.registration.services.repositories.JamCodeRedemptionRepository.session
session = session
# leadr.registration.services.repositories.JamCodeRedemptionRepository.update
update(entity)

Update an existing entity in the database.

Parameters:

  • entity (DomainEntityT) – Domain entity with updated data

Returns:

  • DomainEntityT – Updated domain entity with refreshed data

Raises:

leadr.registration.services.repositories.JamCodeRepository

Bases: BaseRepository[JamCode, JamCodeORM]

Jam code repository for managing promotional codes.

Functions:

  • create – Create a new entity in the database.
  • delete – Soft delete an entity by setting its deleted_at timestamp.
  • filter – Filter jam codes by criteria with pagination.
  • find_by_code – Find a jam code by its code value.
  • get_by_id – Get an entity by its ID.
  • update – Update an existing entity in the database.

Attributes:

# leadr.registration.services.repositories.JamCodeRepository.SORTABLE_FIELDS
SORTABLE_FIELDS = {'id', 'code', 'active', 'current_uses', 'max_uses', 'created_at', 'updated_at'}
# leadr.registration.services.repositories.JamCodeRepository.create
create(entity)

Create a new entity in the database.

Parameters:

Returns:

  • DomainEntityT – Created domain entity with refreshed data
# leadr.registration.services.repositories.JamCodeRepository.delete
delete(entity_id)

Soft delete an entity by setting its deleted_at timestamp.

Parameters:

Raises:

# leadr.registration.services.repositories.JamCodeRepository.filter
filter(account_id=None, *, pagination, **kwargs)

Filter jam codes by criteria with pagination.

Parameters:

  • account_id (Any | None) – Not used for jam codes (top-level entity).
  • pagination (PaginationParams) – Pagination parameters (required).
  • **kwargs (Any) – Filter parameters (code, etc.)

Returns:

Raises:

# leadr.registration.services.repositories.JamCodeRepository.find_by_code
find_by_code(code)

Find a jam code by its code value.

Parameters:

  • code (str) – The jam code to look up (case-insensitive).

Returns:

  • JamCode | None – The jam code if found, None otherwise.
# leadr.registration.services.repositories.JamCodeRepository.get_by_id
get_by_id(entity_id, include_deleted=False)

Get an entity by its ID.

Parameters:

  • entity_id (UUID4 | PrefixedID) – Entity ID to retrieve
  • include_deleted (bool) – If True, include soft-deleted entities. Defaults to False.

Returns:

  • DomainEntityT | None – Domain entity if found, None otherwise
# leadr.registration.services.repositories.JamCodeRepository.session
session = session
# leadr.registration.services.repositories.JamCodeRepository.update
update(entity)

Update an existing entity in the database.

Parameters:

  • entity (DomainEntityT) – Domain entity with updated data

Returns:

  • DomainEntityT – Updated domain entity with refreshed data

Raises:

leadr.registration.services.repositories.VerificationCodeRepository

Bases: BaseRepository[VerificationCode, VerificationCodeORM]

Verification code repository for managing email verification codes.

Functions:

  • create – Create a new entity in the database.
  • delete – Soft delete an entity by setting its deleted_at timestamp.
  • filter – Filter verification codes by criteria with pagination.
  • find_valid_code_by_email – Find a valid (pending) verification code by email and code value.
  • get_by_id – Get an entity by its ID.
  • get_pending_invite_for_user – Get a pending invite code for a specific user.
  • invalidate_codes_for_email – Mark all pending verification codes for an email as expired.
  • update – Update an existing entity in the database.

Attributes:

# leadr.registration.services.repositories.VerificationCodeRepository.SORTABLE_FIELDS
SORTABLE_FIELDS = {'id', 'email', 'status', 'created_at', 'updated_at', 'expires_at'}
# leadr.registration.services.repositories.VerificationCodeRepository.create
create(entity)

Create a new entity in the database.

Parameters:

Returns:

  • DomainEntityT – Created domain entity with refreshed data
# leadr.registration.services.repositories.VerificationCodeRepository.delete
delete(entity_id)

Soft delete an entity by setting its deleted_at timestamp.

Parameters:

Raises:

# leadr.registration.services.repositories.VerificationCodeRepository.filter
filter(account_id=None, *, pagination, **kwargs)

Filter verification codes by criteria with pagination.

Parameters:

  • account_id (Any | None) – Not used for verification codes (top-level entity).
  • pagination (PaginationParams) – Pagination parameters (required).
  • **kwargs (Any) – Filter parameters (email, status, etc.)

Returns:

Raises:

# leadr.registration.services.repositories.VerificationCodeRepository.find_valid_code_by_email
find_valid_code_by_email(email, code, code_type=None)

Find a valid (pending) verification code by email and code value.

Parameters:

  • email (str) – The email address.
  • code (str) – The verification code.
  • code_type (VerificationCodeTypeEnum | None) – Optional code type filter (REGISTRATION or INVITE).

Returns:

  • VerificationCode | None – The verification code if found and valid, None otherwise.
# leadr.registration.services.repositories.VerificationCodeRepository.get_by_id
get_by_id(entity_id, include_deleted=False)

Get an entity by its ID.

Parameters:

  • entity_id (UUID4 | PrefixedID) – Entity ID to retrieve
  • include_deleted (bool) – If True, include soft-deleted entities. Defaults to False.

Returns:

  • DomainEntityT | None – Domain entity if found, None otherwise
# leadr.registration.services.repositories.VerificationCodeRepository.get_pending_invite_for_user
get_pending_invite_for_user(user_id)

Get a pending invite code for a specific user.

Parameters:

  • user_id (UserID) – The user ID to look up invite code for.

Returns:

  • VerificationCode | None – The pending invite verification code if found, None otherwise.
# leadr.registration.services.repositories.VerificationCodeRepository.invalidate_codes_for_email
invalidate_codes_for_email(email)

Mark all pending verification codes for an email as expired.

Used when generating a new code to invalidate previous ones.

Parameters:

  • email (str) – The email address.
# leadr.registration.services.repositories.VerificationCodeRepository.session
session = session
# leadr.registration.services.repositories.VerificationCodeRepository.update
update(entity)

Update an existing entity in the database.

Parameters:

  • entity (DomainEntityT) – Domain entity with updated data

Returns:

  • DomainEntityT – Updated domain entity with refreshed data

Raises:

leadr.registration.services.verification_service

Verification service for generating and validating email verification codes.

Classes:

Attributes:

leadr.registration.services.verification_service.VerificationService
VerificationService(db, email_service)

Service for managing email verification codes.

Functions:

Attributes:

Parameters:

  • db (AsyncSession) – Database session.
  • email_service (EmailService) – Email service for sending verification codes.
# leadr.registration.services.verification_service.VerificationService.create_invite_code
create_invite_code(email, user_id)

Create an invite verification code for an existing user.

Invalidates any existing pending invite codes for the email before creating a new one.

Parameters:

  • email (str) – Email address to send the invite code to.
  • user_id (UserID) – The ID of the user being invited.

Returns:

# leadr.registration.services.verification_service.VerificationService.db
db = db
# leadr.registration.services.verification_service.VerificationService.email_service
email_service = email_service
# leadr.registration.services.verification_service.VerificationService.get_invite_user_id
get_invite_user_id(token)

Extract the user_id from an invite verification token.

Parameters:

  • token (str) – JWT verification token.

Returns:

  • UserID | None – The UserID if this is an invite token, None otherwise.

Raises:

  • ValueError – If the token is invalid or expired.
# leadr.registration.services.verification_service.VerificationService.initiate_verification
initiate_verification(email)

Generate and send a verification code to an email address.

Invalidates any existing pending codes for the email before creating a new one.

Parameters:

  • email (str) – Email address to send the verification code to.
# leadr.registration.services.verification_service.VerificationService.repository
repository = VerificationCodeRepository(db)
# leadr.registration.services.verification_service.VerificationService.validate_verification_token
validate_verification_token(token)

Validate a verification token and return the email.

Parameters:

  • token (str) – JWT verification token.

Returns:

  • str – The email address from the token.

Raises:

  • ValueError – If the token is invalid or expired.
# leadr.registration.services.verification_service.VerificationService.verify_code
verify_code(email, code)

Verify a code and return a short-lived verification token with its type.

Parameters:

  • email (str) – Email address to verify.
  • code (str) – Verification code to check.

Returns:

  • str – A tuple of (JWT verification token, VerificationCodeType).
  • VerificationCodeType – For invite codes, the token includes user_id.

Raises:

  • ValueError – If the code is invalid, expired, or already used.
leadr.registration.services.verification_service.logger
logger = get_logger(__name__)