feat(cloud-console): add user authentication and administration
This commit is contained in:
@@ -1,13 +1,20 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timedelta
|
||||
from typing import TYPE_CHECKING, Any, Literal, Protocol
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from cloud.plugins import PluginManifest
|
||||
from cloud.pool import HostRegistration, PooledDevice
|
||||
from cloud.scheduler import ScheduledTask, ScheduledTaskStatus
|
||||
from cloud.user_auth import (
|
||||
AuthAuditEvent,
|
||||
AuthenticatedUserSession,
|
||||
LoginThrottle,
|
||||
UserAccount,
|
||||
UserSession,
|
||||
)
|
||||
|
||||
|
||||
AttemptStatus = Literal["assigned", "dispatched", "done", "failed", "expired"]
|
||||
@@ -28,6 +35,14 @@ class DeviceEnrollmentConflictError(RuntimeError):
|
||||
"""Raised when a local device enrollment conflicts with stored identity."""
|
||||
|
||||
|
||||
class UserConflictError(RuntimeError):
|
||||
"""Raised when a user operation violates a durable identity invariant."""
|
||||
|
||||
|
||||
class LastAdministratorConflictError(UserConflictError):
|
||||
"""Raised when a write would remove the last enabled administrator."""
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class HostEnrollment:
|
||||
host_id: str
|
||||
@@ -183,6 +198,91 @@ class CloudRepository(Protocol):
|
||||
|
||||
def get_plugin(self, name: str) -> tuple[PluginManifest, bool] | None: ...
|
||||
|
||||
def create_user(self, user: UserAccount) -> UserAccount: ...
|
||||
|
||||
def get_user(self, user_id: str) -> UserAccount | None: ...
|
||||
|
||||
def get_user_by_normalized_username(
|
||||
self,
|
||||
username_normalized: str,
|
||||
) -> UserAccount | None: ...
|
||||
|
||||
def list_users(self, *, limit: int, offset: int) -> list[UserAccount]: ...
|
||||
|
||||
def update_user(
|
||||
self,
|
||||
user_id: str,
|
||||
*,
|
||||
display_name: str | None = None,
|
||||
role: str | None = None,
|
||||
enabled: bool | None = None,
|
||||
updated_at: datetime,
|
||||
) -> UserAccount: ...
|
||||
|
||||
def rehash_user_password(
|
||||
self,
|
||||
user_id: str,
|
||||
*,
|
||||
password_hash: str,
|
||||
updated_at: datetime,
|
||||
) -> UserAccount: ...
|
||||
|
||||
def update_user_password(
|
||||
self,
|
||||
user_id: str,
|
||||
*,
|
||||
password_hash: str,
|
||||
must_change_password: bool,
|
||||
updated_at: datetime,
|
||||
revoke_sessions: bool,
|
||||
) -> UserAccount: ...
|
||||
|
||||
def mark_user_login(self, user_id: str, *, now: datetime) -> UserAccount: ...
|
||||
|
||||
def create_user_session(self, session: UserSession) -> None: ...
|
||||
|
||||
def get_authenticated_user_session(
|
||||
self,
|
||||
token_digest: str,
|
||||
*,
|
||||
now: datetime,
|
||||
) -> AuthenticatedUserSession | None: ...
|
||||
|
||||
def touch_user_session(
|
||||
self,
|
||||
session_id: str,
|
||||
*,
|
||||
last_seen_at: datetime,
|
||||
idle_expires_at: datetime,
|
||||
) -> UserSession: ...
|
||||
|
||||
def revoke_user_session(self, session_id: str, *, revoked_at: datetime) -> bool: ...
|
||||
|
||||
def revoke_user_sessions(self, user_id: str, *, revoked_at: datetime) -> int: ...
|
||||
|
||||
def get_login_throttle(
|
||||
self,
|
||||
username_normalized: str,
|
||||
client_bucket: str,
|
||||
) -> LoginThrottle | None: ...
|
||||
|
||||
def record_login_failure(
|
||||
self,
|
||||
*,
|
||||
username_normalized: str,
|
||||
client_bucket: str,
|
||||
now: datetime,
|
||||
failure_limit: int,
|
||||
failure_window: timedelta,
|
||||
block_duration: timedelta,
|
||||
) -> LoginThrottle: ...
|
||||
|
||||
def clear_login_throttle(self, username_normalized: str, client_bucket: str) -> None: ...
|
||||
|
||||
def record_auth_audit(self, event: AuthAuditEvent) -> None: ...
|
||||
|
||||
def cleanup_auth_state(self, *, now: datetime, limit: int) -> int: ...
|
||||
|
||||
def list_reserved_device_ids(self, *, now: datetime) -> set[str]: ...
|
||||
|
||||
def assign_task(
|
||||
|
||||
Reference in New Issue
Block a user