first implementation
This commit is contained in:
parent
79458bcba4
commit
870804e7b9
24 changed files with 5485 additions and 184 deletions
|
|
@ -23,6 +23,17 @@ class Permission(str, PyEnum):
|
|||
|
||||
# Audit permissions
|
||||
VIEW_AUDIT = "view_audit"
|
||||
|
||||
# Invite permissions
|
||||
MANAGE_INVITES = "manage_invites"
|
||||
VIEW_OWN_INVITES = "view_own_invites"
|
||||
|
||||
|
||||
class InviteStatus(str, PyEnum):
|
||||
"""Status of an invite."""
|
||||
READY = "ready"
|
||||
SPENT = "spent"
|
||||
REVOKED = "revoked"
|
||||
|
||||
|
||||
# Role name constants
|
||||
|
|
@ -32,17 +43,19 @@ ROLE_REGULAR = "regular"
|
|||
# Role definitions with their permissions
|
||||
ROLE_DEFINITIONS: dict[str, RoleConfig] = {
|
||||
ROLE_ADMIN: {
|
||||
"description": "Administrator with audit access",
|
||||
"description": "Administrator with audit and invite management access",
|
||||
"permissions": [
|
||||
Permission.VIEW_AUDIT,
|
||||
Permission.MANAGE_INVITES,
|
||||
],
|
||||
},
|
||||
ROLE_REGULAR: {
|
||||
"description": "Regular user with counter and sum access",
|
||||
"description": "Regular user with counter, sum, and invite access",
|
||||
"permissions": [
|
||||
Permission.VIEW_COUNTER,
|
||||
Permission.INCREMENT_COUNTER,
|
||||
Permission.USE_SUM,
|
||||
Permission.VIEW_OWN_INVITES,
|
||||
],
|
||||
},
|
||||
}
|
||||
|
|
@ -107,6 +120,16 @@ class User(Base):
|
|||
signal: Mapped[str | None] = mapped_column(String(64), nullable=True)
|
||||
nostr_npub: Mapped[str | None] = mapped_column(String(63), nullable=True)
|
||||
|
||||
# Godfather (who invited this user) - null for seeded/admin users
|
||||
godfather_id: Mapped[int | None] = mapped_column(
|
||||
Integer, ForeignKey("users.id"), nullable=True
|
||||
)
|
||||
godfather: Mapped["User | None"] = relationship(
|
||||
"User",
|
||||
remote_side="User.id",
|
||||
foreign_keys=[godfather_id],
|
||||
)
|
||||
|
||||
# Relationship to roles
|
||||
roles: Mapped[list[Role]] = relationship(
|
||||
"Role",
|
||||
|
|
@ -165,3 +188,40 @@ class CounterRecord(Base):
|
|||
created_at: Mapped[datetime] = mapped_column(
|
||||
DateTime(timezone=True), default=lambda: datetime.now(UTC)
|
||||
)
|
||||
|
||||
|
||||
class Invite(Base):
|
||||
__tablename__ = "invites"
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||||
identifier: Mapped[str] = mapped_column(String(64), unique=True, nullable=False, index=True)
|
||||
status: Mapped[InviteStatus] = mapped_column(
|
||||
Enum(InviteStatus), nullable=False, default=InviteStatus.READY
|
||||
)
|
||||
|
||||
# Godfather - the user who owns this invite
|
||||
godfather_id: Mapped[int] = mapped_column(
|
||||
Integer, ForeignKey("users.id"), nullable=False, index=True
|
||||
)
|
||||
godfather: Mapped[User] = relationship(
|
||||
"User",
|
||||
foreign_keys=[godfather_id],
|
||||
lazy="selectin",
|
||||
)
|
||||
|
||||
# User who used this invite (null until spent)
|
||||
used_by_id: Mapped[int | None] = mapped_column(
|
||||
Integer, ForeignKey("users.id"), nullable=True
|
||||
)
|
||||
used_by: Mapped[User | None] = relationship(
|
||||
"User",
|
||||
foreign_keys=[used_by_id],
|
||||
lazy="selectin",
|
||||
)
|
||||
|
||||
# Timestamps
|
||||
created_at: Mapped[datetime] = mapped_column(
|
||||
DateTime(timezone=True), default=lambda: datetime.now(UTC)
|
||||
)
|
||||
spent_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
|
||||
revoked_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue