MCPcopy Create free account
hub / github.com/bytebase/bytebase / SendEmailLoginCode

Method SendEmailLoginCode

backend/api/v1/auth_service.go:1628–1664  ·  view source on GitHub ↗

SendEmailLoginCode sends a 6-digit verification code. Always returns success (no email enumeration). Rate limit: 60-sec resend cooldown enforced atomically via the store — effective cap ≈ 60 sends/hour/email.

(ctx context.Context, req *connect.Request[v1pb.SendEmailLoginCodeRequest])

Source from the content-addressed store, hash-verified

1626// (no email enumeration). Rate limit: 60-sec resend cooldown enforced atomically
1627// via the store — effective cap ≈ 60 sends/hour/email.
1628func (s *AuthService) SendEmailLoginCode(ctx context.Context, req *connect.Request[v1pb.SendEmailLoginCodeRequest]) (*connect.Response[emptypb.Empty], error) {
1629 email := strings.ToLower(strings.TrimSpace(req.Msg.Email))
1630 if email == "" {
1631 return nil, connect.NewError(connect.CodeInvalidArgument, errors.Errorf("email is required"))
1632 }
1633 workspaceID, err := parseOptionalWorkspace(req.Msg.Workspace)
1634 if err != nil {
1635 return nil, connect.NewError(connect.CodeInvalidArgument, err)
1636 }
1637
1638 // Gate on AllowEmailCodeSignin — no point emailing a code the workspace won't accept.
1639 // getAccountRestriction handles all cases (including empty workspace for brand-new SaaS
1640 // signup, where it resolves via EMAIL_CONFIG + SaaS override).
1641 restriction, err := getAccountRestriction(ctx, s.store, s.licenseService, s.profile.SaaS, workspaceID)
1642 if err != nil {
1643 return nil, err
1644 }
1645 if !restriction.AllowEmailCodeSignin {
1646 return nil, connect.NewError(connect.CodeFailedPrecondition, errors.Errorf("email code login is not enabled for this workspace"))
1647 }
1648
1649 // Send synchronously so the caller learns about actionable failures (missing EMAIL
1650 // setting, SMTP unreachable, etc.). No enumeration risk here: LOGIN always attempts to
1651 // send regardless of whether the email exists (sign-up is handled on verify).
1652 if err := s.sendEmailVerificationCode(
1653 ctx,
1654 req.Msg.Workspace,
1655 email,
1656 storepb.EmailVerificationCodePurpose_LOGIN,
1657 "[Bytebase] Your sign-in code",
1658 "Hi,\n\nYour sign-in code is: %s\n\nThis code expires in %d minutes. If you didn't request this, you can safely ignore this email.\n\n— Bytebase",
1659 ); err != nil {
1660 return nil, connect.NewError(connect.CodeInternal, err)
1661 }
1662
1663 return connect.NewResponse(&emptypb.Empty{}), nil
1664}
1665
1666// resolvePreLoginEmailSetting returns the EMAIL setting to use for unauthenticated flows
1667// (email-code sign-in, password reset). Resolution order:

Callers

nothing calls this directly

Calls 4

parseOptionalWorkspaceFunction · 0.85
getAccountRestrictionFunction · 0.85
ErrorfMethod · 0.80

Tested by

no test coverage detected