2024-12-06 18:41:03 +00:00
|
|
|
package providers
|
2024-10-06 21:30:39 +01:00
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"database/sql"
|
|
|
|
"errors"
|
2024-12-06 18:41:03 +00:00
|
|
|
"github.com/1f349/lavender/auth"
|
2025-01-19 12:04:25 +00:00
|
|
|
"github.com/1f349/lavender/auth/authContext"
|
2025-02-24 17:17:28 +00:00
|
|
|
"github.com/1f349/lavender/auth/process"
|
2024-10-06 21:30:39 +01:00
|
|
|
"github.com/1f349/lavender/database"
|
|
|
|
"net/http"
|
|
|
|
)
|
|
|
|
|
2025-01-25 19:49:57 +00:00
|
|
|
type passwordLoginDB interface {
|
2025-03-13 22:41:57 +00:00
|
|
|
GetUser(ctx context.Context, subject string) (database.User, error)
|
2024-10-06 21:30:39 +01:00
|
|
|
CheckLogin(ctx context.Context, un, pw string) (database.CheckLoginResult, error)
|
|
|
|
}
|
|
|
|
|
2025-01-25 19:49:57 +00:00
|
|
|
var (
|
|
|
|
_ auth.Provider = (*PasswordLogin)(nil)
|
|
|
|
_ auth.Form = (*PasswordLogin)(nil)
|
|
|
|
)
|
2024-10-06 21:30:39 +01:00
|
|
|
|
2025-01-25 19:49:57 +00:00
|
|
|
type PasswordLogin struct {
|
|
|
|
DB passwordLoginDB
|
2024-10-06 21:30:39 +01:00
|
|
|
}
|
|
|
|
|
2025-03-13 23:05:05 +00:00
|
|
|
func (p *PasswordLogin) AccessState() process.State { return process.StateBase }
|
2024-10-06 21:30:39 +01:00
|
|
|
|
2025-03-13 23:05:05 +00:00
|
|
|
func (p *PasswordLogin) Name() string { return "password" }
|
2024-10-06 21:30:39 +01:00
|
|
|
|
2025-03-13 23:05:05 +00:00
|
|
|
func (p *PasswordLogin) RenderTemplate(ctx authContext.TemplateContext) error {
|
2024-12-09 18:40:18 +00:00
|
|
|
// TODO(melon): rewrite this
|
2025-01-19 12:04:25 +00:00
|
|
|
req := ctx.Request()
|
|
|
|
redirect := req.FormValue("redirect")
|
|
|
|
if redirect == "" {
|
|
|
|
redirect = "/"
|
|
|
|
}
|
|
|
|
ctx.Render(struct {
|
|
|
|
UserEmail string
|
|
|
|
Redirect string
|
|
|
|
}{
|
2025-03-13 23:05:05 +00:00
|
|
|
UserEmail: ctx.LoginProcessData().Email,
|
2025-01-19 12:04:25 +00:00
|
|
|
Redirect: redirect,
|
|
|
|
})
|
|
|
|
return nil
|
2024-10-06 21:30:39 +01:00
|
|
|
}
|
|
|
|
|
2025-03-13 23:05:05 +00:00
|
|
|
func (p *PasswordLogin) AttemptLogin(ctx authContext.FormContext) error {
|
2025-01-19 12:04:25 +00:00
|
|
|
req := ctx.Request()
|
2025-03-13 23:05:05 +00:00
|
|
|
un := req.FormValue("email")
|
2024-10-06 21:30:39 +01:00
|
|
|
pw := req.FormValue("password")
|
|
|
|
if len(pw) < 8 {
|
2024-12-06 18:41:03 +00:00
|
|
|
return auth.BasicUserSafeError(http.StatusBadRequest, "Password too short")
|
2024-10-06 21:30:39 +01:00
|
|
|
}
|
|
|
|
|
2025-03-13 23:05:05 +00:00
|
|
|
login, err := p.DB.CheckLogin(ctx.Context(), un, pw)
|
2024-10-06 21:30:39 +01:00
|
|
|
switch {
|
|
|
|
case err == nil:
|
2025-03-13 23:05:05 +00:00
|
|
|
user, err := p.DB.GetUser(ctx.Context(), login.Subject)
|
2025-03-13 22:41:57 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
ctx.SetUser(&user)
|
|
|
|
ctx.UpdateSession(process.LoginProcessData{
|
|
|
|
State: process.StateBasic,
|
|
|
|
Email: un,
|
|
|
|
})
|
|
|
|
return nil
|
2024-10-06 21:30:39 +01:00
|
|
|
case errors.Is(err, sql.ErrNoRows):
|
2024-12-06 18:41:03 +00:00
|
|
|
return auth.BasicUserSafeError(http.StatusForbidden, "Username or password is invalid")
|
2024-10-06 21:30:39 +01:00
|
|
|
default:
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|