(ctx context.Context, req *adminv1.AddUsergroupMemberUserRequest)
| 581 | } |
| 582 | |
| 583 | func (s *Server) AddUsergroupMemberUser(ctx context.Context, req *adminv1.AddUsergroupMemberUserRequest) (*adminv1.AddUsergroupMemberUserResponse, error) { |
| 584 | observability.AddRequestAttributes(ctx, |
| 585 | attribute.String("args.org", req.Org), |
| 586 | attribute.String("args.usergroup", req.Usergroup), |
| 587 | attribute.String("args.email", req.Email), |
| 588 | ) |
| 589 | |
| 590 | group, err := s.admin.DB.FindUsergroupByName(ctx, req.Org, req.Usergroup) |
| 591 | if err != nil { |
| 592 | return nil, err |
| 593 | } |
| 594 | |
| 595 | claims := auth.GetClaims(ctx) |
| 596 | if !claims.OrganizationPermissions(ctx, group.OrgID).ManageOrgMembers { |
| 597 | return nil, status.Error(codes.PermissionDenied, "not allowed to add user group members") |
| 598 | } |
| 599 | |
| 600 | if group.Managed { |
| 601 | return nil, status.Error(codes.FailedPrecondition, "cannot edit managed user group") |
| 602 | } |
| 603 | |
| 604 | currentRole, err := s.admin.DB.FindOrganizationMemberUsergroupRole(ctx, group.ID, group.OrgID) |
| 605 | if err != nil && !errors.Is(err, database.ErrNotFound) { |
| 606 | return nil, err |
| 607 | } |
| 608 | if currentRole != nil && currentRole.Admin && !claims.OrganizationPermissions(ctx, group.OrgID).ManageOrgAdmins { |
| 609 | return nil, status.Error(codes.PermissionDenied, "as a non-admin you are not allowed to edit a group that has an admin role") |
| 610 | } |
| 611 | // NOTE: In theory, the group could be admin on a project that the current user is not admin on. |
| 612 | // We don't check for that because it's complicated and not a big leak of permissions. |
| 613 | |
| 614 | user, err := s.admin.DB.FindUserByEmail(ctx, req.Email) |
| 615 | if err != nil { |
| 616 | if !errors.Is(err, database.ErrNotFound) { |
| 617 | return nil, err |
| 618 | } |
| 619 | // did not find user, check if there is any pending invite |
| 620 | invite, err := s.admin.DB.FindOrganizationInvite(ctx, group.OrgID, req.Email) |
| 621 | if err != nil { |
| 622 | if !errors.Is(err, database.ErrNotFound) { |
| 623 | return nil, err |
| 624 | } |
| 625 | // there is no pending invite return error |
| 626 | return nil, status.Error(codes.FailedPrecondition, "user is not a member of the organization") |
| 627 | } |
| 628 | // add group to the invite, dedupe the group ids |
| 629 | if !slices.Contains(invite.UsergroupIDs, group.ID) { |
| 630 | invite.UsergroupIDs = append(invite.UsergroupIDs, group.ID) |
| 631 | err = s.admin.DB.UpdateOrganizationInviteUsergroups(ctx, invite.ID, invite.UsergroupIDs) |
| 632 | if err != nil { |
| 633 | return nil, err |
| 634 | } |
| 635 | } |
| 636 | |
| 637 | return &adminv1.AddUsergroupMemberUserResponse{}, nil |
| 638 | } |
| 639 | |
| 640 | isOrgMember, err := s.admin.DB.CheckUserIsAnOrganizationMember(ctx, user.ID, group.OrgID) |
nothing calls this directly
no test coverage detected