cluster_access.py 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. from datetime import datetime
  2. from typing import Optional
  3. from sqlmodel import (
  4. Column,
  5. Field,
  6. ForeignKey,
  7. Integer,
  8. SQLModel,
  9. UniqueConstraint,
  10. )
  11. from gpustack.schemas.common import UTCDateTime
  12. from gpustack.schemas.principals import PrincipalType
  13. class ClusterAccess(SQLModel, table=True):
  14. """Grant a single principal access to a cluster.
  15. Polymorphic ``(principal_type, principal_id)`` was collapsed into a
  16. single ``principal_id`` FK pointing at ``principals``; the kind is
  17. available via the joined principals row when callers need to render
  18. or branch on it.
  19. """
  20. __tablename__ = 'cluster_access'
  21. __table_args__ = (
  22. UniqueConstraint(
  23. 'cluster_id', 'principal_id', name='uix_cluster_access_cluster_principal'
  24. ),
  25. )
  26. id: Optional[int] = Field(default=None, primary_key=True)
  27. cluster_id: int = Field(
  28. sa_column=Column(
  29. Integer,
  30. ForeignKey("clusters.id", ondelete="CASCADE"),
  31. nullable=False,
  32. ),
  33. )
  34. principal_id: int = Field(
  35. sa_column=Column(
  36. Integer,
  37. ForeignKey("principals.id", ondelete="CASCADE"),
  38. nullable=False,
  39. ),
  40. )
  41. granted_by: Optional[int] = Field(
  42. default=None,
  43. sa_column=Column(
  44. Integer,
  45. ForeignKey("users.id", ondelete="SET NULL"),
  46. nullable=True,
  47. ),
  48. )
  49. created_at: Optional[datetime] = Field(
  50. default=None,
  51. sa_column=Column(UTCDateTime, nullable=False),
  52. )
  53. class ClusterAccessPublic(SQLModel):
  54. cluster_id: int
  55. principal_id: int
  56. # Discriminator kept on the public payload so the UI can render
  57. # "User Alice" vs "Org Acme" vs "Group Engineers" without doing a
  58. # second principals lookup. Resolved server-side from the principals
  59. # row.
  60. principal_type: PrincipalType
  61. # Human-readable label for the principal — username for USER,
  62. # name for ORG / GROUP. Same rationale: server has the join cheaply.
  63. principal_name: Optional[str] = None
  64. # For GROUP principals, the parent ORG. NULL for USER and ORG.
  65. principal_parent_id: Optional[int] = None
  66. granted_by: Optional[int] = None
  67. created_at: datetime