Private
Public Access
Add resizable room panel, searchable user picker, and direct room membership
Room info panel is now user-resizable (fixing a layout clip at narrow widths), and every user-selection spot (room membership, admin ownership transfer) uses a new searchable UserPicker instead of raw text input or prompt(). Member rows fold role + actions into a single inline dropdown instead of a row of buttons, so the member list stays usable as rooms grow. Room invites (the accept/decline flow) are replaced by adding a user to a room directly -- an admin/owner picks someone and they're a member immediately, with a "you've been added" notification email instead of an invite email. Drops the now-unused room_invites table.
This commit is contained in:
@@ -2,7 +2,7 @@ from app.models.admin_audit_log import AdminAuditLog
|
||||
from app.models.api_token import ApiToken
|
||||
from app.models.base import Base
|
||||
from app.models.event_subscription import EventSubscription
|
||||
from app.models.invite import InviteStatus, RoomInvite
|
||||
from app.models.invite import InviteStatus
|
||||
from app.models.membership import RoomMembership, RoomRole
|
||||
from app.models.message import Message
|
||||
from app.models.message_image import MessageImage
|
||||
@@ -23,7 +23,6 @@ __all__ = [
|
||||
"Message",
|
||||
"MessageImage",
|
||||
"MessageReaction",
|
||||
"RoomInvite",
|
||||
"InviteStatus",
|
||||
"SiteInvite",
|
||||
"SmtpSettings",
|
||||
|
||||
@@ -1,53 +1,7 @@
|
||||
import enum
|
||||
import uuid
|
||||
from datetime import datetime, timedelta, timezone
|
||||
|
||||
from sqlalchemy import CheckConstraint, DateTime, Enum, ForeignKey, String, func
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
|
||||
from app.models.base import Base
|
||||
|
||||
DEFAULT_INVITE_LIFETIME = timedelta(days=7)
|
||||
|
||||
|
||||
def _default_expires_at() -> datetime:
|
||||
return datetime.now(timezone.utc) + DEFAULT_INVITE_LIFETIME
|
||||
|
||||
|
||||
class InviteStatus(str, enum.Enum):
|
||||
pending = "pending"
|
||||
accepted = "accepted"
|
||||
revoked = "revoked"
|
||||
|
||||
|
||||
class RoomInvite(Base):
|
||||
__tablename__ = "room_invites"
|
||||
__table_args__ = (
|
||||
CheckConstraint(
|
||||
"target_user_id IS NOT NULL OR target_email IS NOT NULL",
|
||||
name="room_invites_target_required",
|
||||
),
|
||||
)
|
||||
|
||||
id: Mapped[uuid.UUID] = mapped_column(primary_key=True, default=uuid.uuid4)
|
||||
room_id: Mapped[uuid.UUID] = mapped_column(ForeignKey("rooms.id"), index=True, nullable=False)
|
||||
invited_by: Mapped[uuid.UUID] = mapped_column(ForeignKey("users.id"), nullable=False)
|
||||
token: Mapped[str] = mapped_column(String(64), unique=True, index=True, nullable=False)
|
||||
target_user_id: Mapped[uuid.UUID | None] = mapped_column(ForeignKey("users.id"), index=True)
|
||||
# Stored per the documented schema but not actionable yet: there's no
|
||||
# email-delivery mechanism anywhere in the stack. Phase 2 only creates
|
||||
# invites via target_user_id (existing users, looked up by username).
|
||||
target_email: Mapped[str | None] = mapped_column(String(255))
|
||||
expires_at: Mapped[datetime] = mapped_column(
|
||||
DateTime(timezone=True), default=_default_expires_at, nullable=False
|
||||
)
|
||||
status: Mapped[InviteStatus] = mapped_column(
|
||||
Enum(InviteStatus, name="invite_status"), default=InviteStatus.pending, nullable=False
|
||||
)
|
||||
created_at: Mapped[datetime] = mapped_column(
|
||||
DateTime(timezone=True), server_default=func.now(), nullable=False
|
||||
)
|
||||
|
||||
room = relationship("Room")
|
||||
inviter = relationship("User", foreign_keys=[invited_by])
|
||||
target_user = relationship("User", foreign_keys=[target_user_id])
|
||||
|
||||
@@ -16,7 +16,7 @@ def _default_expires_at() -> datetime:
|
||||
|
||||
class SiteInvite(Base):
|
||||
"""An admin-issued invite for someone with no account yet -- distinct
|
||||
from RoomInvite, which targets an existing user for a specific room."""
|
||||
from adding an existing user directly to a room."""
|
||||
|
||||
__tablename__ = "site_invites"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user