99 lines
2.7 KiB
Go
99 lines
2.7 KiB
Go
package handlers
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
|
|
"git.haelnorr.com/h/golib/cookies"
|
|
"git.haelnorr.com/h/golib/hws"
|
|
"git.haelnorr.com/h/golib/hwsauth"
|
|
"github.com/pkg/errors"
|
|
"github.com/uptrace/bun"
|
|
|
|
"git.haelnorr.com/h/oslstats/internal/config"
|
|
"git.haelnorr.com/h/oslstats/internal/db"
|
|
"git.haelnorr.com/h/oslstats/internal/respond"
|
|
"git.haelnorr.com/h/oslstats/internal/store"
|
|
"git.haelnorr.com/h/oslstats/internal/throw"
|
|
authview "git.haelnorr.com/h/oslstats/internal/view/authview"
|
|
)
|
|
|
|
func Register(
|
|
s *hws.Server,
|
|
auth *hwsauth.Authenticator[*db.User, bun.Tx],
|
|
conn *db.DB,
|
|
cfg *config.Config,
|
|
store *store.Store,
|
|
) http.Handler {
|
|
return http.HandlerFunc(
|
|
func(w http.ResponseWriter, r *http.Request) {
|
|
attempts, exceeded, track := store.TrackRedirect(r, "/register", 3)
|
|
|
|
if exceeded {
|
|
err := track.Error(attempts)
|
|
store.ClearRedirectTrack(r, "/register")
|
|
throw.BadRequest(s, w, r, "Cookies appear to be blocked or disabled. Please enable cookies in your browser and try again", err)
|
|
return
|
|
}
|
|
|
|
sessionCookie, err := r.Cookie("registration_session")
|
|
if err != nil {
|
|
http.Redirect(w, r, "/login", http.StatusSeeOther)
|
|
return
|
|
}
|
|
details, ok := store.GetRegistrationSession(sessionCookie.Value)
|
|
if !ok {
|
|
http.Redirect(w, r, "/login", http.StatusSeeOther)
|
|
return
|
|
}
|
|
|
|
store.ClearRedirectTrack(r, "/register")
|
|
|
|
if r.Method == "GET" {
|
|
renderSafely(authview.RegisterPage(details.DiscordUser.Username), s, r, w)
|
|
return
|
|
}
|
|
username := r.FormValue("username")
|
|
unique := false
|
|
var user *db.User
|
|
if ok := conn.WithNotifyTx(s, w, r, func(ctx context.Context, tx bun.Tx) (bool, error) {
|
|
unique, err = db.IsUnique(ctx, tx, (*db.User)(nil), "username", username)
|
|
if err != nil {
|
|
return false, errors.Wrap(err, "db.IsUsernameUnique")
|
|
}
|
|
if !unique {
|
|
return true, nil
|
|
}
|
|
user, err = db.CreateUser(ctx, tx, username, details.DiscordUser, db.NewAudit(r, nil))
|
|
if err != nil {
|
|
return false, errors.Wrap(err, "db.CreateUser")
|
|
}
|
|
err = user.UpdateDiscordToken(ctx, tx, details.Token)
|
|
if err != nil {
|
|
return false, errors.Wrap(err, "db.UpdateDiscordToken")
|
|
}
|
|
if shouldGrantAdmin(user, cfg.RBAC) {
|
|
err := ensureUserHasAdminRole(ctx, tx, user)
|
|
if err != nil {
|
|
return false, errors.Wrap(err, "ensureUserHasAdminRole")
|
|
}
|
|
}
|
|
return true, nil
|
|
}); !ok {
|
|
return
|
|
}
|
|
if !unique {
|
|
respond.Conflict(w, errors.New("username is taken"))
|
|
} else {
|
|
err = auth.Login(w, r, user, true)
|
|
if err != nil {
|
|
throw.InternalServiceError(s, w, r, "Login failed", err)
|
|
return
|
|
}
|
|
pageFrom := cookies.CheckPageFrom(w, r)
|
|
respond.HXRedirect(w, "%s", pageFrom)
|
|
}
|
|
},
|
|
)
|
|
}
|