Compare commits
No commits in common. "3433ba39ee93b3330b8c9d551860e93a45c438f1" and "3f7abc5986b791e9c5d213f0fbae7ad8fb09a633" have entirely different histories.
3433ba39ee
...
3f7abc5986
6 changed files with 2 additions and 109 deletions
|
|
@ -1,34 +0,0 @@
|
||||||
"""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,18 +56,10 @@ class Permission(Base):
|
||||||
class Group(Base):
|
class Group(Base):
|
||||||
__tablename__ = "group"
|
__tablename__ = "group"
|
||||||
id = Column(Integer, primary_key=True)
|
id = Column(Integer, primary_key=True)
|
||||||
name = Column(String, nullable=False)
|
name = Column(String, nullable=False, unique=True)
|
||||||
|
|
||||||
org_id = Column(Integer, ForeignKey("organisation.id", ondelete="CASCADE"))
|
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")
|
user_rel = relationship("User", secondary="user_groups", back_populates="group_rel")
|
||||||
|
|
||||||
org_rel = relationship("Organisation", back_populates="group_rel")
|
org_rel = relationship("Organisation", back_populates="group_rel")
|
||||||
|
|
|
||||||
|
|
@ -8,14 +8,12 @@ Exports:
|
||||||
from typing import Annotated
|
from typing import Annotated
|
||||||
from datetime import datetime, timedelta, timezone
|
from datetime import datetime, timedelta, timezone
|
||||||
|
|
||||||
|
from src.iam.schemas import IAMCAoRRequest
|
||||||
from src.service.models import Service
|
from src.service.models import Service
|
||||||
from src.database import db_dependency
|
from src.database import db_dependency
|
||||||
from src.exceptions import UnauthorizedException
|
from src.exceptions import UnauthorizedException
|
||||||
from src.utils import send_email, generate_jwt
|
from src.utils import send_email, generate_jwt
|
||||||
|
|
||||||
from src.iam.schemas import IAMCAoRRequest
|
|
||||||
from src.iam.models import Group
|
|
||||||
|
|
||||||
|
|
||||||
from fastapi import Request, Depends
|
from fastapi import Request, Depends
|
||||||
|
|
||||||
|
|
@ -66,49 +64,3 @@ async def send_user_group_invitation(
|
||||||
subject=subject,
|
subject=subject,
|
||||||
body=body,
|
body=body,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
async def create_default_user_group(db: db_dependency, org_model):
|
|
||||||
new_group = Group(name="Default Users", org_id=org_model.id)
|
|
||||||
db.add(new_group)
|
|
||||||
db.flush()
|
|
||||||
# Grant default permissions here
|
|
||||||
db.flush()
|
|
||||||
return new_group
|
|
||||||
|
|
||||||
|
|
||||||
async def assign_default_user_group(db: db_dependency, org_model, user_model):
|
|
||||||
group_model = None
|
|
||||||
for group in org_model.group_rel:
|
|
||||||
if group.name == "Default Users":
|
|
||||||
group_model = group
|
|
||||||
break
|
|
||||||
|
|
||||||
if group_model is None:
|
|
||||||
group_model = await create_default_user_group(db=db, org_model=org_model)
|
|
||||||
|
|
||||||
user_model.group_rel.append(group_model)
|
|
||||||
db.flush()
|
|
||||||
|
|
||||||
|
|
||||||
async def create_default_root_group(db: db_dependency, org_model):
|
|
||||||
new_group = Group(name="Root User", org_id=org_model.id)
|
|
||||||
db.add(new_group)
|
|
||||||
db.flush()
|
|
||||||
# Grant default permissions here
|
|
||||||
db.flush()
|
|
||||||
return new_group
|
|
||||||
|
|
||||||
|
|
||||||
async def assign_default_root_group(db: db_dependency, org_model, user_model):
|
|
||||||
group_model = None
|
|
||||||
for group in org_model.group_rel:
|
|
||||||
if group.name == "Root User":
|
|
||||||
group_model = group
|
|
||||||
break
|
|
||||||
|
|
||||||
if group_model is None:
|
|
||||||
group_model = await create_default_root_group(db=db, org_model=org_model)
|
|
||||||
|
|
||||||
user_model.group_rel.append(group_model)
|
|
||||||
db.flush()
|
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,6 @@ from src.contact.models import Contact
|
||||||
from src.contact.schemas import ContactAddress
|
from src.contact.schemas import ContactAddress
|
||||||
from src.contact.exceptions import ContactNotFoundException
|
from src.contact.exceptions import ContactNotFoundException
|
||||||
from src.database import db_dependency
|
from src.database import db_dependency
|
||||||
from src.iam.service import assign_default_user_group, assign_default_root_group
|
|
||||||
from src.organisation.schemas_questionnaires import QuestionnaireQuestionsVersion0
|
from src.organisation.schemas_questionnaires import QuestionnaireQuestionsVersion0
|
||||||
from src.user.dependencies import (
|
from src.user.dependencies import (
|
||||||
user_model_body_dependency,
|
user_model_body_dependency,
|
||||||
|
|
@ -184,10 +183,6 @@ async def create_org(
|
||||||
# Adds currently logged-in user to org users list and sets them as root_user
|
# Adds currently logged-in user to org users list and sets them as root_user
|
||||||
org_model.user_rel.append(user_model)
|
org_model.user_rel.append(user_model)
|
||||||
org_model.root_user_rel = user_model
|
org_model.root_user_rel = user_model
|
||||||
|
|
||||||
# Creates default user and default root IAM groups and assigns them
|
|
||||||
await assign_default_user_group(db, org_model, user_model)
|
|
||||||
await assign_default_root_group(db, org_model, user_model)
|
|
||||||
for contact_type in [
|
for contact_type in [
|
||||||
"billing_contact_id",
|
"billing_contact_id",
|
||||||
"security_contact_id",
|
"security_contact_id",
|
||||||
|
|
@ -352,7 +347,6 @@ async def add_user_to_org(
|
||||||
raise ConflictException(message="User already a part of this organisation")
|
raise ConflictException(message="User already a part of this organisation")
|
||||||
org_model.user_rel.append(user_model)
|
org_model.user_rel.append(user_model)
|
||||||
db.flush()
|
db.flush()
|
||||||
await assign_default_user_group(db=db, org_model=org_model, user_model=user_model)
|
|
||||||
response = {
|
response = {
|
||||||
"organisation": org_model,
|
"organisation": org_model,
|
||||||
"users": [{"id": user.id, "email": user.email} for user in org_model.user_rel],
|
"users": [{"id": user.id, "email": user.email} for user in org_model.user_rel],
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ Endpoints:
|
||||||
|
|
||||||
from fastapi import APIRouter, status, BackgroundTasks
|
from fastapi import APIRouter, status, BackgroundTasks
|
||||||
|
|
||||||
from src.iam.service import assign_default_user_group
|
|
||||||
from src.organisation.exceptions import OrgNotFoundException
|
from src.organisation.exceptions import OrgNotFoundException
|
||||||
from src.user.schemas import (
|
from src.user.schemas import (
|
||||||
UserResponse,
|
UserResponse,
|
||||||
|
|
@ -200,7 +199,6 @@ async def accept_invitation(
|
||||||
|
|
||||||
org_model.user_rel.append(user_model)
|
org_model.user_rel.append(user_model)
|
||||||
db.flush()
|
db.flush()
|
||||||
await assign_default_user_group(db=db, org_model=org_model, user_model=user_model)
|
|
||||||
|
|
||||||
response = {
|
response = {
|
||||||
"organisation": org_model,
|
"organisation": org_model,
|
||||||
|
|
|
||||||
|
|
@ -283,15 +283,6 @@ async def test_post_group_conflict(default_client: AsyncClient):
|
||||||
assert resp.status_code == 409
|
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
|
@pytest.mark.anyio
|
||||||
async def test_put_group_perm_success(default_client: AsyncClient):
|
async def test_put_group_perm_success(default_client: AsyncClient):
|
||||||
resp = await default_client.put(
|
resp = await default_client.put(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue