DeleteUser deletes a user.
(ctx context.Context, request *connect.Request[v1pb.DeleteUserRequest])
| 510 | |
| 511 | // DeleteUser deletes a user. |
| 512 | func (s *UserService) DeleteUser(ctx context.Context, request *connect.Request[v1pb.DeleteUserRequest]) (*connect.Response[emptypb.Empty], error) { |
| 513 | if s.profile.SaaS { |
| 514 | return nil, connect.NewError(connect.CodeUnimplemented, errors.Errorf("CreateUser is not available in SaaS mode, add users via workspace IAM policy instead")) |
| 515 | } |
| 516 | |
| 517 | callerUser, ok := GetUserFromContext(ctx) |
| 518 | if !ok { |
| 519 | return nil, connect.NewError(connect.CodePermissionDenied, errors.Errorf("failed to get caller user")) |
| 520 | } |
| 521 | ok, err := s.iamManager.CheckPermission(ctx, permission.UsersDelete, callerUser, common.GetWorkspaceIDFromContext(ctx)) |
| 522 | if err != nil { |
| 523 | return nil, connect.NewError(connect.CodeInternal, errors.Errorf("failed to check permission with error: %v", err.Error())) |
| 524 | } |
| 525 | if !ok { |
| 526 | return nil, connect.NewError(connect.CodePermissionDenied, errors.Errorf("user does not have permission %q", permission.UsersDelete)) |
| 527 | } |
| 528 | |
| 529 | email, err := common.GetUserEmail(request.Msg.Name) |
| 530 | if err != nil { |
| 531 | return nil, connect.NewError(connect.CodeInvalidArgument, err) |
| 532 | } |
| 533 | if err := validateEndUserEmail(email); err != nil { |
| 534 | return nil, err |
| 535 | } |
| 536 | user, err := s.store.GetUserByEmail(ctx, email) |
| 537 | if err != nil { |
| 538 | return nil, connect.NewError(connect.CodeInternal, errors.Wrapf(err, "failed to get user")) |
| 539 | } |
| 540 | if user == nil { |
| 541 | return nil, connect.NewError(connect.CodeNotFound, errors.Errorf("user %q not found", email)) |
| 542 | } |
| 543 | if user.MemberDeleted { |
| 544 | return nil, connect.NewError(connect.CodeNotFound, errors.Errorf("user %q has been deleted", email)) |
| 545 | } |
| 546 | |
| 547 | // Check if there is still workspace admin if the current user is deleted. |
| 548 | policy, err := s.store.GetWorkspaceIamPolicy(ctx, common.GetWorkspaceIDFromContext(ctx)) |
| 549 | if err != nil { |
| 550 | return nil, err |
| 551 | } |
| 552 | hasExtraWorkspaceAdmin, err := s.hasExtraWorkspaceAdmin(ctx, policy.Policy, user) |
| 553 | if err != nil { |
| 554 | return nil, err |
| 555 | } |
| 556 | if !hasExtraWorkspaceAdmin { |
| 557 | return nil, connect.NewError(connect.CodeInvalidArgument, errors.Errorf("workspace must have at least one admin")) |
| 558 | } |
| 559 | |
| 560 | if _, err := s.store.UpdateUser(ctx, user, &store.UpdateUserMessage{Delete: &deletePatch}); err != nil { |
| 561 | return nil, connect.NewError(connect.CodeInternal, err) |
| 562 | } |
| 563 | return connect.NewResponse(&emptypb.Empty{}), nil |
| 564 | } |
| 565 | |
| 566 | func (s *UserService) hasExtraWorkspaceAdmin(ctx context.Context, policy *storepb.IamPolicy, user *store.UserMessage) (bool, error) { |
| 567 | workspaceAdminRole := common.FormatRole(store.WorkspaceAdminRole) |
nothing calls this directly
no test coverage detected