@@ -214,8 +214,8 @@ func (s *ProjectService) AddMember(ctx context.Context, req *pb.ProjectServiceAd
214214 return nil , errors .BadRequest ("invalid" , fmt .Sprintf ("invalid project reference: %s" , err .Error ()))
215215 }
216216
217- // Extract the user email from the oneof MembershipReference field
218- userEmail , err := s .extractUserEmailFromMembershipReference (req .GetMemberReference ())
217+ // Extract the user email and group reference from the membership reference field
218+ userEmail , groupReference , err := s .extractMembershipReference (req .GetMemberReference ())
219219 if err != nil {
220220 return nil , handleUseCaseErr (err , s .log )
221221 }
@@ -227,6 +227,7 @@ func (s *ProjectService) AddMember(ctx context.Context, req *pb.ProjectServiceAd
227227 opts := & biz.AddMemberToProjectOpts {
228228 ProjectReference : identityRef ,
229229 UserEmail : userEmail ,
230+ GroupReference : groupReference ,
230231 RequesterID : requesterUUID ,
231232 Role : role ,
232233 }
@@ -278,8 +279,8 @@ func (s *ProjectService) RemoveMember(ctx context.Context, req *pb.ProjectServic
278279 return nil , errors .BadRequest ("invalid" , fmt .Sprintf ("invalid project reference: %s" , err .Error ()))
279280 }
280281
281- // Extract the user email from the oneof MembershipReference field
282- userEmail , err := s .extractUserEmailFromMembershipReference (req .GetMemberReference ())
282+ // Extract the user email and group reference from the membership reference field
283+ userEmail , groupReference , err := s .extractMembershipReference (req .GetMemberReference ())
283284 if err != nil {
284285 return nil , handleUseCaseErr (err , s .log )
285286 }
@@ -288,6 +289,7 @@ func (s *ProjectService) RemoveMember(ctx context.Context, req *pb.ProjectServic
288289 opts := & biz.RemoveMemberFromProjectOpts {
289290 ProjectReference : identityRef ,
290291 UserEmail : userEmail ,
292+ GroupReference : groupReference ,
291293 RequesterID : requesterUUID ,
292294 }
293295
@@ -300,19 +302,41 @@ func (s *ProjectService) RemoveMember(ctx context.Context, req *pb.ProjectServic
300302 return & pb.ProjectServiceRemoveMemberResponse {}, nil
301303}
302304
303- // extractUserEmailFromMembershipReference extracts the user email from a membership reference
304- // Returns the user email and an error if the email is not provided or the membership reference is nil
305- func (s * ProjectService ) extractUserEmailFromMembershipReference (membershipRef * pb.ProjectMembershipReference ) (string , error ) {
305+ // extractMembershipReference extracts either a user email or a group reference from a membership reference
306+ // If both or neither are provided, returns an error
307+ func (s * ProjectService ) extractMembershipReference (membershipRef * pb.ProjectMembershipReference ) (string , * biz. IdentityReference , error ) {
306308 if membershipRef == nil {
307- return "" , biz .NewErrValidationStr ("membership reference is required" )
309+ return "" , nil , biz .NewErrValidationStr ("membership reference is required" )
308310 }
309311
312+ // Check if the membershipRef has a user email
310313 userEmail := membershipRef .GetUserEmail ()
311- if userEmail == "" {
312- return "" , biz .NewErrValidationStr ("user email is required" )
314+ groupRef := membershipRef .GetGroupReference ()
315+
316+ // Validate that exactly one of user email or group reference is provided
317+ if (userEmail == "" && groupRef == nil ) || (userEmail != "" && groupRef != nil ) {
318+ return "" , nil , biz .NewErrValidationStr ("exactly one of user email or group reference must be provided" )
319+ }
320+
321+ // If we have a user email, return it and nil for group reference
322+ if userEmail != "" {
323+ return userEmail , nil , nil
313324 }
314325
315- return userEmail , nil
326+ // Otherwise, create a new IdentityReference from the group reference
327+ identityRef := & biz.IdentityReference {}
328+ var err error
329+
330+ identityRef .ID , identityRef .Name , err = groupRef .Parse ()
331+ if err != nil {
332+ return "" , nil , errors .BadRequest ("invalid_group_reference" , fmt .Sprintf ("invalid group reference: %s" , err .Error ()))
333+ }
334+
335+ if identityRef .ID == nil && identityRef .Name == nil {
336+ return "" , nil , biz .NewErrValidationStr ("either group ID or name must be provided" )
337+ }
338+
339+ return "" , identityRef , nil
316340}
317341
318342// MapProjectMemberRoleToAuthzRole maps a ProjectMemberRole from protobuf to an authz.Role
@@ -343,12 +367,21 @@ func bizProjectMembershipToPb(m *biz.ProjectMembership) *pb.ProjectMember {
343367 }
344368
345369 pbMember := & pb.ProjectMember {
346- Subject : & pb.ProjectMember_User {
347- User : bizUserToPb (m .User ),
348- },
349370 Role : role ,
350371 }
351372
373+ if m .User != nil {
374+ pbMember .Subject = & pb.ProjectMember_User {
375+ User : bizUserToPb (m .User ),
376+ }
377+ }
378+
379+ if m .Group != nil {
380+ pbMember .Subject = & pb.ProjectMember_Group {
381+ Group : bizGroupToPb (m .Group ),
382+ }
383+ }
384+
352385 if m .CreatedAt != nil {
353386 pbMember .CreatedAt = timestamppb .New (* m .CreatedAt )
354387 }
0 commit comments