UpdateEmail updates a user's email address.
(ctx context.Context, request *connect.Request[v1pb.UpdateEmailRequest])
| 650 | |
| 651 | // UpdateEmail updates a user's email address. |
| 652 | func (s *UserService) UpdateEmail(ctx context.Context, request *connect.Request[v1pb.UpdateEmailRequest]) (*connect.Response[v1pb.User], error) { |
| 653 | if s.profile.SaaS { |
| 654 | return nil, connect.NewError(connect.CodeUnimplemented, errors.Errorf("CreateUser is not available in SaaS mode, add users via workspace IAM policy instead")) |
| 655 | } |
| 656 | |
| 657 | callerUser, ok := GetUserFromContext(ctx) |
| 658 | if !ok { |
| 659 | return nil, connect.NewError(connect.CodePermissionDenied, errors.Errorf("failed to get caller user")) |
| 660 | } |
| 661 | ok, err := s.iamManager.CheckPermission(ctx, permission.UsersUpdateEmail, callerUser, common.GetWorkspaceIDFromContext(ctx)) |
| 662 | if err != nil { |
| 663 | return nil, connect.NewError(connect.CodeInternal, errors.Errorf("failed to check permission with error: %v", err.Error())) |
| 664 | } |
| 665 | if !ok { |
| 666 | return nil, connect.NewError(connect.CodePermissionDenied, errors.Errorf("user does not have permission %q", permission.UsersUpdateEmail)) |
| 667 | } |
| 668 | |
| 669 | // Get user by email from the name field |
| 670 | email, err := common.GetUserEmail(request.Msg.Name) |
| 671 | if err != nil { |
| 672 | return nil, connect.NewError(connect.CodeInvalidArgument, err) |
| 673 | } |
| 674 | user, err := s.store.GetUserByEmail(ctx, email) |
| 675 | if err != nil { |
| 676 | return nil, connect.NewError(connect.CodeInternal, errors.Wrapf(err, "failed to get user")) |
| 677 | } |
| 678 | if user == nil { |
| 679 | return nil, connect.NewError(connect.CodeNotFound, errors.Errorf("user not found")) |
| 680 | } |
| 681 | if user.MemberDeleted { |
| 682 | return nil, connect.NewError(connect.CodeNotFound, errors.Errorf("user has been deleted")) |
| 683 | } |
| 684 | |
| 685 | // Check if new email is the same as current email (no-op) |
| 686 | if user.Email == request.Msg.Email { |
| 687 | return nil, connect.NewError(connect.CodeInvalidArgument, errors.Errorf("new email is the same as current email")) |
| 688 | } |
| 689 | |
| 690 | // Validate email format and domain restrictions |
| 691 | if err := validateEmailWithDomains(ctx, s.licenseService, s.store, common.GetWorkspaceIDFromContext(ctx), request.Msg.Email, false); err != nil { |
| 692 | return nil, err |
| 693 | } |
| 694 | |
| 695 | // Check if email already exists |
| 696 | existedUser, err := s.store.GetUserByEmail(ctx, request.Msg.Email) |
| 697 | if err != nil { |
| 698 | return nil, connect.NewError(connect.CodeInternal, errors.Wrapf(err, "failed to find user by email")) |
| 699 | } |
| 700 | if existedUser != nil && existedUser.ID != user.ID { |
| 701 | return nil, connect.NewError(connect.CodeAlreadyExists, errors.Errorf("email %s already exists", request.Msg.Email)) |
| 702 | } |
| 703 | |
| 704 | // Update the email |
| 705 | user, err = s.store.UpdateUserEmail(ctx, user, request.Msg.Email) |
| 706 | if err != nil { |
| 707 | return nil, connect.NewError(connect.CodeInternal, errors.Wrapf(err, "failed to update user email")) |
| 708 | } |
| 709 |
nothing calls this directly
no test coverage detected