aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/src/meshbay_hub/db/models.py
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/db/models.py')
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/db/models.py19
1 files changed, 19 insertions, 0 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/db/models.py b/packages/meshbay-hub/src/meshbay_hub/db/models.py
index 1e652a6..dbc0f10 100644
--- a/packages/meshbay-hub/src/meshbay_hub/db/models.py
+++ b/packages/meshbay-hub/src/meshbay_hub/db/models.py
@@ -429,6 +429,25 @@ class MailQuota(Base):
last_sent: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
+class KnownBrowser(Base):
+ """A browser this account has signed in from, for the sign-in lockout.
+
+ Its own failure counter, which a stranger cannot spend: the lockout keyed by
+ username alone let anyone who knew a name keep its owner out of every
+ browser, four requests an hour. Only a hash of the token is kept. It is not
+ a credential — a sign-in presenting it still needs the passphrase.
+ """
+
+ __tablename__ = "known_browsers"
+
+ id: Mapped[str] = mapped_column(String(36), primary_key=True, default=_uuid)
+ user_id: Mapped[str] = mapped_column(ForeignKey("users.id"), nullable=False,
+ index=True)
+ token_hash: Mapped[str] = mapped_column(String(64), unique=True, nullable=False)
+ created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=_now)
+ last_used_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=_now)
+
+
class LoginThrottle(Base):
"""Wrong passphrases per username, for the sign-in lockout (`login_throttle.py`).