(ctx context.Context, request *v1pb.LoginRequest)
| 519 | } |
| 520 | |
| 521 | func (s *AuthService) getAndVerifyUser(ctx context.Context, request *v1pb.LoginRequest) (*store.UserMessage, error) { |
| 522 | // Check if user is locked out due to too many failed password attempts. |
| 523 | if err := s.checkPasswordLockout(ctx, request.Email); err != nil { |
| 524 | return nil, err |
| 525 | } |
| 526 | |
| 527 | // GetAccountByEmail is cross-workspace, which is correct for login. |
| 528 | // Email is globally unique (PK). The token gets workspace from account.Workspace (SA/WI) |
| 529 | // or from the default workspace (END_USER). |
| 530 | account, err := s.store.GetAccountByEmail(ctx, request.Email) |
| 531 | if err != nil { |
| 532 | return nil, connect.NewError(connect.CodeInternal, errors.Wrapf(err, "failed to get user by email %q", request.Email)) |
| 533 | } |
| 534 | if account == nil { |
| 535 | return nil, invalidCredentialsError |
| 536 | } |
| 537 | // Compare the stored hashed password, with the hashed version of the password that was received. |
| 538 | if err := bcrypt.CompareHashAndPassword([]byte(account.PasswordHash), []byte(request.Password)); err != nil { |
| 539 | // If the two passwords don't match, return a 401 status. |
| 540 | return nil, invalidCredentialsError |
| 541 | } |
| 542 | |
| 543 | // Convert AccountMessage to UserMessage for downstream use. |
| 544 | user, err := s.store.ResolvePrincipalAsUser(ctx, account) |
| 545 | if err != nil { |
| 546 | return nil, connect.NewError(connect.CodeInternal, errors.Wrapf(err, "failed to resolve principal %q", account.Email)) |
| 547 | } |
| 548 | if user == nil { |
| 549 | return nil, connect.NewError(connect.CodeUnauthenticated, errors.Errorf("user %q not found", account.Email)) |
| 550 | } |
| 551 | return user, nil |
| 552 | } |
| 553 | |
| 554 | // getOrCreateUserWithIDP authenticates a user via an identity provider (SSO). |
| 555 | // Login API has allow_without_credential, so there's no workspace in the token context. |
no test coverage detected