diff --git a/app/controlplane/pkg/biz/project.go b/app/controlplane/pkg/biz/project.go index 84a19d373..93153c134 100644 --- a/app/controlplane/pkg/biz/project.go +++ b/app/controlplane/pkg/biz/project.go @@ -45,7 +45,7 @@ type ProjectsRepo interface { // UpdateMemberRoleInProject updates the role of a user or group in a project. UpdateMemberRoleInProject(ctx context.Context, orgID uuid.UUID, projectID uuid.UUID, memberID uuid.UUID, membershipType authz.MembershipType, newRole authz.Role) (*ProjectMembership, error) // FindProjectMembershipByProjectAndID finds a project membership by project ID and member ID (user or group). - FindProjectMembershipByProjectAndID(ctx context.Context, projectID uuid.UUID, memberID uuid.UUID, membershipType authz.MembershipType) (*ProjectMembership, error) + FindProjectMembershipByProjectAndID(ctx context.Context, orgID uuid.UUID, projectID uuid.UUID, memberID uuid.UUID, membershipType authz.MembershipType) (*ProjectMembership, error) } // ProjectUseCase is a use case for projects @@ -252,7 +252,7 @@ func (uc *ProjectUseCase) addUserToProject(ctx context.Context, orgID uuid.UUID, userUUID := uuid.MustParse(userMembership.User.ID) // Check if the user is already a member of the project - existingMembership, err := uc.projectsRepository.FindProjectMembershipByProjectAndID(ctx, projectID, userUUID, authz.MembershipTypeUser) + existingMembership, err := uc.projectsRepository.FindProjectMembershipByProjectAndID(ctx, orgID, projectID, userUUID, authz.MembershipTypeUser) if err != nil && !IsNotFound(err) { return nil, fmt.Errorf("failed to check existing membership: %w", err) } @@ -289,7 +289,7 @@ func (uc *ProjectUseCase) addGroupToProject(ctx context.Context, orgID uuid.UUID } // Check if the group already has membership in the project - existingMembership, err := uc.projectsRepository.FindProjectMembershipByProjectAndID(ctx, projectID, resolvedGroupID, authz.MembershipTypeGroup) + existingMembership, err := uc.projectsRepository.FindProjectMembershipByProjectAndID(ctx, orgID, projectID, resolvedGroupID, authz.MembershipTypeGroup) if err != nil && !IsNotFound(err) { return nil, fmt.Errorf("failed to check existing group membership: %w", err) } @@ -371,7 +371,7 @@ func (uc *ProjectUseCase) removeUserFromProject(ctx context.Context, orgID uuid. userUUID := uuid.MustParse(userMembership.User.ID) // Check if the user is a member of the project - existingMembership, err := uc.projectsRepository.FindProjectMembershipByProjectAndID(ctx, projectID, userUUID, authz.MembershipTypeUser) + existingMembership, err := uc.projectsRepository.FindProjectMembershipByProjectAndID(ctx, orgID, projectID, userUUID, authz.MembershipTypeUser) if err != nil && !IsNotFound(err) { return fmt.Errorf("failed to check existing membership: %w", err) } @@ -406,7 +406,7 @@ func (uc *ProjectUseCase) removeGroupFromProject(ctx context.Context, orgID uuid } // Check if the group has membership in the project - existingMembership, err := uc.projectsRepository.FindProjectMembershipByProjectAndID(ctx, projectID, resolvedGroupID, authz.MembershipTypeGroup) + existingMembership, err := uc.projectsRepository.FindProjectMembershipByProjectAndID(ctx, orgID, projectID, resolvedGroupID, authz.MembershipTypeGroup) if err != nil && !IsNotFound(err) { return fmt.Errorf("failed to check existing group membership: %w", err) } @@ -526,7 +526,8 @@ func (uc *ProjectUseCase) verifyRequesterHasPermissions(ctx context.Context, org for _, m := range requesterMemberships { if m.ResourceType == authz.ResourceTypeProject && m.ResourceID == projectID && - m.Role == authz.RoleProjectAdmin { + m.Role == authz.RoleProjectAdmin && + m.OrganizationID == orgID { hasProjectAdminRole = true break } @@ -610,7 +611,7 @@ func (uc *ProjectUseCase) updateUserRoleInProject(ctx context.Context, orgID uui userUUID := uuid.MustParse(userMembership.User.ID) // Check if the user is a member of the project - existingMembership, err := uc.projectsRepository.FindProjectMembershipByProjectAndID(ctx, projectID, userUUID, authz.MembershipTypeUser) + existingMembership, err := uc.projectsRepository.FindProjectMembershipByProjectAndID(ctx, orgID, projectID, userUUID, authz.MembershipTypeUser) if err != nil && !IsNotFound(err) { return fmt.Errorf("failed to check existing membership: %w", err) } @@ -652,7 +653,7 @@ func (uc *ProjectUseCase) updateGroupRoleInProject(ctx context.Context, orgID uu } // Check if the group has membership in the project - existingMembership, err := uc.projectsRepository.FindProjectMembershipByProjectAndID(ctx, projectID, resolvedGroupID, authz.MembershipTypeGroup) + existingMembership, err := uc.projectsRepository.FindProjectMembershipByProjectAndID(ctx, orgID, projectID, resolvedGroupID, authz.MembershipTypeGroup) if err != nil && !IsNotFound(err) { return fmt.Errorf("failed to check existing group membership: %w", err) } diff --git a/app/controlplane/pkg/data/membership.go b/app/controlplane/pkg/data/membership.go index 72401f72e..7538fb39d 100644 --- a/app/controlplane/pkg/data/membership.go +++ b/app/controlplane/pkg/data/membership.go @@ -250,7 +250,7 @@ func (r *MembershipRepo) ListAllByUser(ctx context.Context, userID uuid.UUID) ([ mm, err := r.data.DB.Membership.Query().Where( membership.MembershipTypeEQ(authz.MembershipTypeUser), membership.MemberID(userID), - ).All(ctx) + ).WithOrganization().All(ctx) if err != nil { return nil, fmt.Errorf("failed to query memberships: %w", err) diff --git a/app/controlplane/pkg/data/project.go b/app/controlplane/pkg/data/project.go index 97a9beab5..a56a82540 100644 --- a/app/controlplane/pkg/data/project.go +++ b/app/controlplane/pkg/data/project.go @@ -198,6 +198,7 @@ func (r *ProjectRepo) AddMemberToProject(ctx context.Context, orgID uuid.UUID, p // Create the membership if _, err := r.data.DB.Membership.Create(). + SetOrganizationID(orgID). SetMembershipType(membershipType). SetMemberID(memberID). SetResourceType(authz.ResourceTypeProject). @@ -208,7 +209,7 @@ func (r *ProjectRepo) AddMemberToProject(ctx context.Context, orgID uuid.UUID, p } // Return the created membership - return r.FindProjectMembershipByProjectAndID(ctx, projectID, memberID, membershipType) + return r.FindProjectMembershipByProjectAndID(ctx, orgID, projectID, memberID, membershipType) } // RemoveMemberFromProject removes a user or group from a project @@ -223,7 +224,7 @@ func (r *ProjectRepo) RemoveMemberFromProject(ctx context.Context, orgID uuid.UU } // Find the membership to delete - m, err := r.queryMembership(projectID, memberID, membershipType).Only(ctx) + m, err := r.queryMembership(orgID, projectID, memberID, membershipType).Only(ctx) if err != nil { if ent.IsNotFound(err) { @@ -241,9 +242,9 @@ func (r *ProjectRepo) RemoveMemberFromProject(ctx context.Context, orgID uuid.UU } // FindProjectMembershipByProjectAndID finds a project membership by project ID and member ID (user or group) -func (r *ProjectRepo) FindProjectMembershipByProjectAndID(ctx context.Context, projectID uuid.UUID, memberID uuid.UUID, membershipType authz.MembershipType) (*biz.ProjectMembership, error) { +func (r *ProjectRepo) FindProjectMembershipByProjectAndID(ctx context.Context, orgID uuid.UUID, projectID uuid.UUID, memberID uuid.UUID, membershipType authz.MembershipType) (*biz.ProjectMembership, error) { // Find the membership - m, err := r.queryMembership(projectID, memberID, membershipType).Only(ctx) + m, err := r.queryMembership(orgID, projectID, memberID, membershipType).Only(ctx) if err != nil { if ent.IsNotFound(err) { @@ -302,7 +303,7 @@ func (r *ProjectRepo) UpdateMemberRoleInProject(ctx context.Context, orgID uuid. } // Find the membership to update - m, err := r.queryMembership(projectID, memberID, membershipType).Only(ctx) + m, err := r.queryMembership(orgID, projectID, memberID, membershipType).Only(ctx) if err != nil { if ent.IsNotFound(err) { @@ -321,9 +322,12 @@ func (r *ProjectRepo) UpdateMemberRoleInProject(ctx context.Context, orgID uuid. } // queryMembership is a helper function to build a common membership query -func (r *ProjectRepo) queryMembership(projectID uuid.UUID, memberID uuid.UUID, membershipType authz.MembershipType) *ent.MembershipQuery { +func (r *ProjectRepo) queryMembership(orgID uuid.UUID, projectID uuid.UUID, memberID uuid.UUID, membershipType authz.MembershipType) *ent.MembershipQuery { return r.data.DB.Membership.Query(). Where( + membership.HasOrganizationWith( + organization.ID(orgID), + ), membership.MembershipTypeEQ(membershipType), membership.MemberID(memberID), membership.ResourceTypeEQ(authz.ResourceTypeProject),