MCPcopy Index your code
hub / github.com/chainloop-dev/chainloop / ListMembers

Method ListMembers

app/controlplane/pkg/data/project.go:127–206  ·  view source on GitHub ↗

ListMembers lists all members of a project (both users and groups)

(ctx context.Context, orgID uuid.UUID, projectID uuid.UUID, paginationOpts *pagination.OffsetPaginationOpts)

Source from the content-addressed store, hash-verified

125
126// ListMembers lists all members of a project (both users and groups)
127func (r *ProjectRepo) ListMembers(ctx context.Context, orgID uuid.UUID, projectID uuid.UUID, paginationOpts *pagination.OffsetPaginationOpts) ([]*biz.ProjectMembership, int, error) {
128 ctx, span := otelx.Start(ctx, projectRepoTracer, "ProjectRepo.ListMembers")
129 defer span.End()
130
131 // Check if the project exists and belongs to the organization
132 existingProject, err := r.FindProjectByOrgIDAndID(ctx, orgID, projectID)
133 if err != nil {
134 return nil, 0, fmt.Errorf("failed to find project: %w", err)
135 }
136 if existingProject == nil {
137 return nil, 0, biz.NewErrNotFound("project")
138 }
139
140 // Build the query with base conditions for all membership types
141 query := r.data.DB.Membership.Query().
142 Where(
143 membership.ResourceTypeEQ(authz.ResourceTypeProject),
144 membership.ResourceID(projectID),
145 ).WithParent()
146
147 // Get total count before applying pagination
148 totalCount, err := query.Count(ctx)
149 if err != nil {
150 return nil, 0, fmt.Errorf("failed to count project members: %w", err)
151 }
152
153 // Apply pagination
154 if paginationOpts != nil {
155 query = query.
156 Order(ent.Desc(membership.FieldCreatedAt)).
157 Limit(paginationOpts.Limit()).
158 Offset(paginationOpts.Offset())
159 }
160
161 // Execute the query
162 memberships, err := query.All(ctx)
163 if err != nil {
164 return nil, 0, fmt.Errorf("failed to list project members: %w", err)
165 }
166
167 // Convert to biz.ProjectMembership objects
168 result := make([]*biz.ProjectMembership, 0, len(memberships))
169 for _, m := range memberships {
170 var mems *biz.ProjectMembership
171
172 switch m.MembershipType {
173 case authz.MembershipTypeUser:
174 u, uErr := r.data.DB.User.Get(ctx, m.MemberID)
175 if uErr != nil {
176 // Skip orphaned rows whose member_id no longer points at a real user.
177 // memberships.member_id is polymorphic with no FK, so deletes that bypass
178 // the app-level cascade can leave dangling rows here.
179 if ent.IsNotFound(uErr) {
180 r.log.Warnf("orphaned project membership %s references missing user %s, skipping", m.ID, m.MemberID)
181 totalCount--
182 continue
183 }
184 return nil, 0, fmt.Errorf("failed to find user: %w", uErr)

Callers

nothing calls this directly

Calls 15

StartFunction · 0.92
NewErrNotFoundFunction · 0.92
ResourceTypeEQFunction · 0.92
ResourceIDFunction · 0.92
DescFunction · 0.92
IsNotFoundFunction · 0.92
WithParentMethod · 0.80
GetMethod · 0.65
WhereMethod · 0.45
QueryMethod · 0.45

Tested by

no test coverage detected