diff options
| author | nsfisis <nsfisis@gmail.com> | 2024-08-17 18:59:55 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2024-08-17 18:59:55 +0900 |
| commit | f926ef682de637b717d3b0cc0eaee43c59e83c95 (patch) | |
| tree | a6cc6852ecdfe5643d336b77e9956fe6383d53ef /backend/auth/auth.go | |
| parent | 29721ab9971c401d5fb5d2a2cfd730b156a8e195 (diff) | |
| download | phperkaigi-2025-albatross-f926ef682de637b717d3b0cc0eaee43c59e83c95.tar.gz phperkaigi-2025-albatross-f926ef682de637b717d3b0cc0eaee43c59e83c95.tar.zst phperkaigi-2025-albatross-f926ef682de637b717d3b0cc0eaee43c59e83c95.zip | |
feat(backend): allow login/signup with email address
Diffstat (limited to 'backend/auth/auth.go')
| -rw-r--r-- | backend/auth/auth.go | 74 |
1 files changed, 40 insertions, 34 deletions
diff --git a/backend/auth/auth.go b/backend/auth/auth.go index 4224675..0e55d8d 100644 --- a/backend/auth/auth.go +++ b/backend/auth/auth.go @@ -3,8 +3,6 @@ package auth import ( "context" "errors" - "fmt" - "strings" "time" "github.com/jackc/pgx/v5" @@ -18,7 +16,6 @@ var ( ErrInvalidRegistrationToken = errors.New("invalid registration token") ErrNoRegistrationToken = errors.New("no registration token") ErrForteeLoginTimeout = errors.New("fortee login timeout") - ErrForteeEmailUsed = errors.New("fortee email used") ) const ( @@ -33,17 +30,12 @@ func Login( registrationToken *string, ) (int, error) { userAuth, err := queries.GetUserAuthByUsername(ctx, username) - if err != nil { - if errors.Is(err, pgx.ErrNoRows) { - err := signup(ctx, queries, username, password, registrationToken) - if err != nil { - return 0, err - } - return Login(ctx, queries, username, password, nil) - } + if err != nil && !errors.Is(err, pgx.ErrNoRows) { return 0, err } + if userAuth.AuthType == "password" { + // Authenticate with password. passwordHash := userAuth.PasswordHash if passwordHash == nil { panic("inconsistant data") @@ -53,41 +45,60 @@ func Login( return 0, err } return int(userAuth.UserID), nil - } else if userAuth.AuthType == "fortee" { - if err := verifyForteeAccount(ctx, username, password); err != nil { - return 0, err + } + + // Authenticate with fortee. + return verifyForteeAccountOrSignup(ctx, queries, username, password, registrationToken) +} + +func verifyForteeAccountOrSignup( + ctx context.Context, + queries *db.Queries, + username string, + password string, + registrationToken *string, +) (int, error) { + canonicalizedUsername, err := verifyForteeAccount(ctx, username, password) + if err != nil { + return 0, err + } + userID, err := queries.GetUserIDByUsername(ctx, canonicalizedUsername) + if err != nil { + if errors.Is(err, pgx.ErrNoRows) { + return signup( + ctx, + queries, + canonicalizedUsername, + registrationToken, + ) } - return int(userAuth.UserID), nil + return 0, err } - panic(fmt.Sprintf("unexpected auth type: %s", userAuth.AuthType)) + return int(userID), nil } func signup( ctx context.Context, queries *db.Queries, username string, - password string, registrationToken *string, -) error { +) (int, error) { if err := verifyRegistrationToken(ctx, queries, registrationToken); err != nil { - return err - } - if err := verifyForteeAccount(ctx, username, password); err != nil { - return err + return 0, err } // TODO: transaction userID, err := queries.CreateUser(ctx, username) if err != nil { - return err + return 0, err } if err := queries.CreateUserAuth(ctx, db.CreateUserAuthParams{ UserID: userID, AuthType: "fortee", }); err != nil { - return err + return 0, err } - return nil + return int(userID), nil } func verifyRegistrationToken(ctx context.Context, queries *db.Queries, registrationToken *string) error { @@ -104,18 +115,13 @@ func verifyRegistrationToken(ctx context.Context, queries *db.Queries, registrat return nil } -func verifyForteeAccount(ctx context.Context, username string, password string) error { - // fortee API allows login with email address, but this system disallows it. - if strings.Contains(username, "@") { - return ErrForteeEmailUsed - } - +func verifyForteeAccount(ctx context.Context, username string, password string) (string, error) { ctx, cancel := context.WithTimeout(ctx, forteeAPITimeout) defer cancel() - err := fortee.LoginFortee(ctx, username, password) + canonicalizedUsername, err := fortee.LoginFortee(ctx, username, password) if errors.Is(err, context.DeadlineExceeded) { - return ErrForteeLoginTimeout + return "", ErrForteeLoginTimeout } - return err + return canonicalizedUsername, err } |
