Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions backend/app/alembic/versions/93d484f5798e_refactor_project_user.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
"""Refactor Project user

Revision ID: 93d484f5798e
Revises: b30727137e65
Create Date: 2025-10-10 17:55:46.327616

"""
from alembic import op
import sqlalchemy as sa
import sqlmodel.sql.sqltypes
from sqlalchemy.dialects import postgresql

# revision identifiers, used by Alembic.
revision = "93d484f5798e"
down_revision = "b30727137e65"
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table("projectuser")
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table(
"projectuser",
sa.Column("id", sa.INTEGER(), autoincrement=True, nullable=False),
sa.Column("project_id", sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column("is_admin", sa.BOOLEAN(), autoincrement=False, nullable=False),
sa.Column("is_deleted", sa.BOOLEAN(), autoincrement=False, nullable=False),
sa.Column(
"inserted_at",
postgresql.TIMESTAMP(),
server_default=sa.text("now()"),
autoincrement=False,
nullable=False,
),
sa.Column(
"updated_at", postgresql.TIMESTAMP(), autoincrement=False, nullable=False
),
sa.Column(
"deleted_at", postgresql.TIMESTAMP(), autoincrement=False, nullable=True
),
sa.Column("user_id", sa.INTEGER(), autoincrement=False, nullable=False),
sa.ForeignKeyConstraint(
["project_id"],
["project.id"],
name="projectuser_project_id_fkey",
ondelete="CASCADE",
),
sa.ForeignKeyConstraint(
["user_id"],
["user.id"],
name="projectuser_user_id_fkey",
ondelete="CASCADE",
),
sa.PrimaryKeyConstraint("id", name="projectuser_pkey"),
)
# ### end Alembic commands ###
71 changes: 0 additions & 71 deletions backend/app/api/deps.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
User,
UserProjectOrg,
UserOrganization,
ProjectUser,
Project,
Organization,
)
Expand Down Expand Up @@ -148,73 +147,3 @@ def get_current_active_superuser_org(current_user: CurrentUserOrg) -> User:
status_code=403, detail="The user doesn't have enough privileges"
)
return current_user


def verify_user_project_organization(
db: SessionDep,
current_user: CurrentUserOrg,
project_id: int,
organization_id: int,
) -> UserProjectOrg:
"""
Verify that the authenticated user is part of the project
and that the project belongs to the organization.
"""
if current_user.organization_id and current_user.organization_id != organization_id:
raise HTTPException(status_code=403, detail="User is not part of organization")

project_organization = db.exec(
select(Project, Organization)
.join(Organization, Project.organization_id == Organization.id)
.where(
Project.id == project_id,
Project.is_active == True,
Organization.id == organization_id,
Organization.is_active == True,
)
).first()

if not project_organization:
# Determine the exact error based on missing data
organization = db.exec(
select(Organization).where(Organization.id == organization_id)
).first()
if not organization:
raise HTTPException(status_code=404, detail="Organization not found")

if not organization.is_active:
raise HTTPException(
status_code=400, detail="Organization is not active"
) # Use 400 for inactive resources

project = db.exec(select(Project).where(Project.id == project_id)).first()
if not project:
raise HTTPException(status_code=404, detail="Project not found")

if not project.is_active:
raise HTTPException(
status_code=400, detail="Project is not active"
) # Use 400 for inactive resources

raise HTTPException(
status_code=403, detail="Project does not belong to the organization"
)

# Superuser bypasses all checks and If Api key request we give access to all the project in organization
if current_user.is_superuser or current_user.organization_id:
current_user.organization_id = organization_id
return UserProjectOrg(**current_user.model_dump(), project_id=project_id)

# Check if the user is part of the project
user_in_project = db.exec(
select(ProjectUser).where(
ProjectUser.user_id == current_user.id,
ProjectUser.project_id == project_id,
)
).first()

if not user_in_project:
raise HTTPException(status_code=403, detail="User is not part of the project")

current_user.organization_id = organization_id
return UserProjectOrg(**current_user.model_dump(), project_id=project_id)
2 changes: 0 additions & 2 deletions backend/app/api/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
organization,
openai_conversation,
project,
project_user,
responses,
private,
threads,
Expand All @@ -37,7 +36,6 @@
api_router.include_router(openai_conversation.router)
api_router.include_router(organization.router)
api_router.include_router(project.router)
api_router.include_router(project_user.router)
api_router.include_router(responses.router)
api_router.include_router(threads.router)
api_router.include_router(users.router)
Expand Down
115 changes: 0 additions & 115 deletions backend/app/api/routes/project_user.py

This file was deleted.

109 changes: 0 additions & 109 deletions backend/app/crud/project_user.py

This file was deleted.

5 changes: 0 additions & 5 deletions backend/app/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,6 @@
OrganizationUpdate,
)

from .project_user import (
ProjectUser,
ProjectUserPublic,
ProjectUsersPublic,
)
from .project import (
Project,
ProjectCreate,
Expand Down
Loading