Skip to content

Commit

Permalink
Make team name and (member name, team id) unique. Remove the need for…
Browse files Browse the repository at this point in the history
… appending id to names whem creating graph since we ensured that they are unique
  • Loading branch information
StreetLamb committed Apr 22, 2024
1 parent 7c46d37 commit bcedcf3
Show file tree
Hide file tree
Showing 7 changed files with 1,934 additions and 24 deletions.
23 changes: 21 additions & 2 deletions backend/app/api/routes/members.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import Any

from fastapi import APIRouter, HTTPException
from fastapi import APIRouter, Depends, HTTPException
from sqlmodel import func, select

from app.api.deps import CurrentUser, SessionDep
Expand All @@ -17,6 +17,24 @@
router = APIRouter()


def validate_unique_name_in_team(
session: SessionDep, team_id: int, id: int, member_in: MemberCreate | MemberUpdate
):
"""Check if (name, team_id) is unique"""
if member_in.name is None:
return
statement = select(Member).where(
Member.name == member_in.name,
Member.belongs_to == team_id,
Member.id != id,
)
member_unique = session.exec(statement).first()
if member_unique:
raise HTTPException(
status_code=400, detail="Member with this name already exists"
)


@router.get("/", response_model=MembersOut)
def read_members(
session: SessionDep,
Expand Down Expand Up @@ -94,6 +112,7 @@ def create_member(
current_user: CurrentUser,
team_id: int,
member_in: MemberCreate,
_: bool = Depends(validate_unique_name_in_team),
) -> Any:
"""
Create new member.
Expand All @@ -102,7 +121,6 @@ def create_member(
team = session.get(Team, team_id)
if team.owner_id != current_user.id:
raise HTTPException(status_code=400, detail="Not enough permissions")
print(member_in)
member = Member.model_validate(member_in, update={"belongs_to": team_id})
session.add(member)
session.commit()
Expand All @@ -118,6 +136,7 @@ def update_member(
team_id: int,
id: int,
member_in: MemberUpdate,
_: bool = Depends(validate_unique_name_in_team),
) -> Any:
"""
Update a member.
Expand Down
25 changes: 22 additions & 3 deletions backend/app/api/routes/teams.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import Any

from fastapi import APIRouter, HTTPException
from fastapi import APIRouter, Depends, HTTPException
from fastapi.responses import StreamingResponse
from sqlmodel import func, select

Expand Down Expand Up @@ -62,6 +62,16 @@
router = APIRouter()


async def validate_unique_name(session: SessionDep, team_in: TeamCreate | TeamUpdate):
"""Validate that team name is unique"""
if team_in.name is None:
return
statement = select(Team).where(Team.name == team_in.name)
team = session.exec(statement).first()
if team:
raise HTTPException(status_code=400, detail="Team name already exists")


@router.get("/", response_model=TeamsOut)
def read_teams(
session: SessionDep, current_user: CurrentUser, skip: int = 0, limit: int = 100
Expand Down Expand Up @@ -107,7 +117,11 @@ def read_team(session: SessionDep, current_user: CurrentUser, id: int) -> Any:

@router.post("/", response_model=TeamOut)
def create_team(
*, session: SessionDep, current_user: CurrentUser, team_in: TeamCreate
*,
session: SessionDep,
current_user: CurrentUser,
team_in: TeamCreate,
_: bool = Depends(validate_unique_name),
) -> Any:
"""
Create new team and it's team leader
Expand Down Expand Up @@ -136,7 +150,12 @@ def create_team(

@router.put("/{id}", response_model=TeamOut)
def update_team(
*, session: SessionDep, current_user: CurrentUser, id: int, team_in: TeamUpdate
*,
session: SessionDep,
current_user: CurrentUser,
id: int,
team_in: TeamUpdate,
_: bool = Depends(validate_unique_name),
) -> Any:
"""
Update a team.
Expand Down
9 changes: 5 additions & 4 deletions backend/app/core/graph/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,16 +59,17 @@ def convert_team_to_dict(team: Team, members: list[MemberModel]):
member_id = queue.popleft()
member = members_lookup[member_id]
if member.type == "root" or member.type == "leader":
leader_name = f"{member.name}-{team.id}"
leader_name = member.name
# Create the team definitions
teams[leader_name] = {
"name": f"{team.name}-{team.id}",
"name": team.name,
"members": {},
}
# If member is not root team leader, add as a member
if member.type != "root":
member_name = f"{member.name}-{team.id}"
leader_name = f"{members_lookup[member.source].name}-{team.id}"
member_name = member.name
leader = members_lookup[member.source]
leader_name = leader.name
teams[leader_name]["members"][member_name] = {
"type": member.type,
"name": member_name,
Expand Down
5 changes: 5 additions & 0 deletions backend/app/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from pydantic import BaseModel
from pydantic import Field as PydanticField
from sqlalchemy import UniqueConstraint
from sqlmodel import Field, Relationship, SQLModel


Expand Down Expand Up @@ -152,6 +153,7 @@ class TeamChat(BaseModel):

class Team(TeamBase, table=True):
id: int | None = Field(default=None, primary_key=True)
name: str = Field(regex=r"^[a-zA-Z0-9_-]{1,64}$", unique=True)
owner_id: int | None = Field(default=None, foreign_key="user.id", nullable=False)
owner: User | None = Relationship(back_populates="teams")
members: list["Member"] = Relationship(
Expand Down Expand Up @@ -206,6 +208,9 @@ class MemberUpdate(MemberBase):


class Member(MemberBase, table=True):
__table_args__ = (
UniqueConstraint("name", "belongs_to", name="unique_team_and_name"),
)
id: int | None = Field(default=None, primary_key=True)
belongs_to: int | None = Field(default=None, foreign_key="team.id", nullable=False)
belongs: Team | None = Relationship(back_populates="members")
Expand Down
Loading

0 comments on commit bcedcf3

Please sign in to comment.