feat: group name unique per org
Instead of group names being wholly unique (enforced by the db), group names are unique within the org (enforced by endpoint logic).
This commit is contained in:
parent
3f7abc5986
commit
dad23733e8
3 changed files with 52 additions and 1 deletions
34
.alembic/versions/2026-06-15_group_name_unique_per_org.py
Normal file
34
.alembic/versions/2026-06-15_group_name_unique_per_org.py
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
"""group name unique per org
|
||||
|
||||
Revision ID: 98e20aae555c
|
||||
Revises: b6c8614ef799
|
||||
Create Date: 2026-06-15 11:05:16.673658
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = '98e20aae555c'
|
||||
down_revision: Union[str, Sequence[str], None] = 'b6c8614ef799'
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
"""Upgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_constraint(op.f('group_name_key'), 'group', type_='unique')
|
||||
op.create_unique_constraint('uniq_group_name_org_id', 'group', ['name', 'org_id'])
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
"""Downgrade schema."""
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_constraint('uniq_group_name_org_id', 'group', type_='unique')
|
||||
op.create_unique_constraint(op.f('group_name_key'), 'group', ['name'], postgresql_nulls_not_distinct=False)
|
||||
# ### end Alembic commands ###
|
||||
|
|
@ -56,10 +56,18 @@ class Permission(Base):
|
|||
class Group(Base):
|
||||
__tablename__ = "group"
|
||||
id = Column(Integer, primary_key=True)
|
||||
name = Column(String, nullable=False, unique=True)
|
||||
name = Column(String, nullable=False)
|
||||
|
||||
org_id = Column(Integer, ForeignKey("organisation.id", ondelete="CASCADE"))
|
||||
|
||||
__table_args__ = (
|
||||
UniqueConstraint(
|
||||
"name",
|
||||
"org_id",
|
||||
name="uniq_group_name_org_id",
|
||||
),
|
||||
)
|
||||
|
||||
user_rel = relationship("User", secondary="user_groups", back_populates="group_rel")
|
||||
|
||||
org_rel = relationship("Organisation", back_populates="group_rel")
|
||||
|
|
|
|||
|
|
@ -283,6 +283,15 @@ async def test_post_group_conflict(default_client: AsyncClient):
|
|||
assert resp.status_code == 409
|
||||
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_post_group_non_conflict(default_client: AsyncClient):
|
||||
resp = await default_client.post(
|
||||
"/iam/group", json={"organisation_id": 2, "name": "Org One Group"}
|
||||
)
|
||||
|
||||
assert resp.status_code == 201
|
||||
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_put_group_perm_success(default_client: AsyncClient):
|
||||
resp = await default_client.put(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue