(ctx context.Context, req *adminv1.RemoveOrganizationMemberUserRequest)
| 525 | } |
| 526 | |
| 527 | func (s *Server) RemoveOrganizationMemberUser(ctx context.Context, req *adminv1.RemoveOrganizationMemberUserRequest) (*adminv1.RemoveOrganizationMemberUserResponse, error) { |
| 528 | observability.AddRequestAttributes(ctx, |
| 529 | attribute.String("args.org", req.Org), |
| 530 | attribute.String("args.email", req.Email), |
| 531 | ) |
| 532 | |
| 533 | org, err := s.admin.DB.FindOrganizationByName(ctx, req.Org) |
| 534 | if err != nil { |
| 535 | return nil, err |
| 536 | } |
| 537 | |
| 538 | user, err := s.admin.DB.FindUserByEmail(ctx, req.Email) |
| 539 | if err != nil { |
| 540 | if !errors.Is(err, database.ErrNotFound) { |
| 541 | return nil, err |
| 542 | } |
| 543 | |
| 544 | // Only admins can remove pending invites. |
| 545 | // NOTE: If we change invites to accept/decline (instead of auto-accept on signup), we need to revisit this. |
| 546 | claims := auth.GetClaims(ctx) |
| 547 | if !claims.OrganizationPermissions(ctx, org.ID).ManageOrgMembers { |
| 548 | return nil, status.Error(codes.PermissionDenied, "not allowed to remove org members") |
| 549 | } |
| 550 | |
| 551 | // Check if there is a pending invite |
| 552 | invite, err := s.admin.DB.FindOrganizationInvite(ctx, org.ID, req.Email) |
| 553 | if err != nil { |
| 554 | return nil, err |
| 555 | } |
| 556 | |
| 557 | err = s.admin.DB.DeleteOrganizationInvite(ctx, invite.ID) |
| 558 | if err != nil { |
| 559 | return nil, err |
| 560 | } |
| 561 | |
| 562 | return &adminv1.RemoveOrganizationMemberUserResponse{}, nil |
| 563 | } |
| 564 | |
| 565 | // The caller must either have ManageOrgMembers permission or be the user being removed. |
| 566 | claims := auth.GetClaims(ctx) |
| 567 | isManager := claims.OrganizationPermissions(ctx, org.ID).ManageOrgMembers |
| 568 | isSelf := claims.OwnerType() == auth.OwnerTypeUser && claims.OwnerID() == user.ID |
| 569 | if !isManager && !isSelf { |
| 570 | return nil, status.Error(codes.PermissionDenied, "not allowed to remove org members") |
| 571 | } |
| 572 | |
| 573 | if org.BillingEmail == user.Email { |
| 574 | return nil, status.Error(codes.FailedPrecondition, "this user is the billing email for the organization, please update the billing email before removing") |
| 575 | } |
| 576 | |
| 577 | // Check admin status edge cases |
| 578 | isAdmin, isLastAdmin, err := s.admin.DB.FindOrganizationMemberUserAdminStatus(ctx, org.ID, user.ID) |
| 579 | if err != nil { |
| 580 | return nil, err |
| 581 | } |
| 582 | if isAdmin && !claims.OrganizationPermissions(ctx, org.ID).ManageOrgAdmins { |
| 583 | return nil, status.Error(codes.PermissionDenied, "as a non-admin you are not allowed to remove an admin member") |
| 584 | } |
nothing calls this directly
no test coverage detected