Files
core-api/src/db/models/group.py
T
Jeroen SchweitzerandClaude Opus 4.5 e85c9a123d
Build and Push / build (release) Successful in 50s
feat: add groups management API
- GET /auth/groups - list groups with search/pagination
- POST /auth/groups/sync-from-authentik - bulk sync from Authentik
- Group model and database migration

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-01 22:28:06 +01:00

86 lines
2.3 KiB
Python

"""
Group Model
Represents groups synced from Authentik.
Groups are used for access control and user organization.
"""
import uuid
from datetime import datetime
from typing import TYPE_CHECKING, List
from sqlalchemy import String, Boolean, DateTime, func, Table, Column, ForeignKey
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm import Mapped, mapped_column, relationship
from src.db.database import Base
# Association table for User-Group many-to-many relationship
user_groups = Table(
"user_groups",
Base.metadata,
Column("user_id", UUID(as_uuid=True), ForeignKey("users.id", ondelete="CASCADE"), primary_key=True),
Column("group_id", UUID(as_uuid=True), ForeignKey("groups.id", ondelete="CASCADE"), primary_key=True),
)
class Group(Base):
"""
Group model synced from Authentik
Groups are fetched from Authentik admin API and cached locally.
They represent organizational units for access control.
"""
__tablename__ = "groups"
id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True),
primary_key=True,
default=uuid.uuid4,
)
authentik_id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True),
unique=True,
nullable=False,
index=True,
comment="Authentik group UUID",
)
name: Mapped[str] = mapped_column(
String(255),
unique=True,
nullable=False,
index=True,
)
is_superuser: Mapped[bool] = mapped_column(
Boolean,
default=False,
nullable=False,
comment="Whether members of this group have superuser privileges",
)
parent_name: Mapped[str | None] = mapped_column(
String(255),
nullable=True,
comment="Parent group name for hierarchy",
)
member_count: Mapped[int] = mapped_column(
default=0,
nullable=False,
comment="Number of users in this group",
)
created_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
server_default=func.now(),
nullable=False,
)
synced_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
server_default=func.now(),
onupdate=func.now(),
nullable=False,
comment="Last sync from Authentik",
)
def __repr__(self) -> str:
return f"<Group {self.name}>"