All checks were successful
Check / check (pull_request) Successful in 3m22s
Bump golangci-lint from v2.10.1 to v2.12.2 in the Dockerfile lint stage (tag+digest pin) and script/bootstrap release-archive pins (linux amd64/arm64 sha256s). Replace .golangci.yml with the canonical v2-layout config so linter settings (lll 88, funlen 80/50, cyclop 15, dupl 100) actually apply. Fix all findings surfaced by the new linter and config: - noctx: use httptest.NewRequestWithContext in all tests - gosec G710/G703: route app redirects through a path-escaping redirectToApp helper; annotate internal log path usage - goconst: introduce shared constants for template/JSON keys and repeated test literals - lll: wrap lines to the 88-column limit - dupl: extract shared helpers (generic findAllByAppID in models, deleteAppResource in handlers, parsePush in webhook payloads, table-driven/helper-based test dedup) - nolintlint: drop nolint directives made obsolete by the new limits Record the change in TODO.md; make check is green.
117 lines
2.8 KiB
Go
117 lines
2.8 KiB
Go
package handlers
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
"sneak.berlin/go/upaas/templates"
|
|
)
|
|
|
|
const (
|
|
// minPasswordLength is the minimum required password length.
|
|
minPasswordLength = 8
|
|
)
|
|
|
|
// HandleSetupGET returns the setup page handler.
|
|
func (h *Handlers) HandleSetupGET() http.HandlerFunc {
|
|
tmpl := templates.GetParsed()
|
|
|
|
return func(writer http.ResponseWriter, request *http.Request) {
|
|
data := h.addGlobals(map[string]any{}, request)
|
|
|
|
h.renderTemplate(writer, tmpl, "setup.html", data)
|
|
}
|
|
}
|
|
|
|
// setupFormData holds form data for the setup page.
|
|
type setupFormData struct {
|
|
username string
|
|
password string
|
|
passwordConfirm string
|
|
}
|
|
|
|
// validateSetupForm validates the setup form and returns an error message if invalid.
|
|
func validateSetupForm(formData setupFormData) string {
|
|
if formData.username == "" || formData.password == "" {
|
|
return "Username and password are required"
|
|
}
|
|
|
|
if len(formData.password) < minPasswordLength {
|
|
return "Password must be at least 8 characters"
|
|
}
|
|
|
|
if formData.password != formData.passwordConfirm {
|
|
return "Passwords do not match"
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
// renderSetupError renders the setup page with an error message.
|
|
func (h *Handlers) renderSetupError(
|
|
tmpl *templates.TemplateExecutor,
|
|
writer http.ResponseWriter,
|
|
request *http.Request,
|
|
username string,
|
|
errorMsg string,
|
|
) {
|
|
data := h.addGlobals(map[string]any{
|
|
"Username": username,
|
|
dataKeyError: errorMsg,
|
|
}, request)
|
|
h.renderTemplate(writer, tmpl, "setup.html", data)
|
|
}
|
|
|
|
// HandleSetupPOST handles the setup form submission.
|
|
func (h *Handlers) HandleSetupPOST() http.HandlerFunc {
|
|
tmpl := templates.GetParsed()
|
|
|
|
return func(writer http.ResponseWriter, request *http.Request) {
|
|
parseErr := request.ParseForm()
|
|
if parseErr != nil {
|
|
http.Error(writer, "Bad Request", http.StatusBadRequest)
|
|
|
|
return
|
|
}
|
|
|
|
formData := setupFormData{
|
|
username: request.FormValue("username"),
|
|
password: request.FormValue("password"),
|
|
passwordConfirm: request.FormValue("password_confirm"),
|
|
}
|
|
|
|
if validationErr := validateSetupForm(formData); validationErr != "" {
|
|
h.renderSetupError(tmpl, writer, request, formData.username, validationErr)
|
|
|
|
return
|
|
}
|
|
|
|
user, createErr := h.auth.CreateUser(
|
|
request.Context(),
|
|
formData.username,
|
|
formData.password,
|
|
)
|
|
if createErr != nil {
|
|
h.log.Error("failed to create user", "error", createErr)
|
|
h.renderSetupError(tmpl, writer, request, formData.username, "Failed to create user")
|
|
|
|
return
|
|
}
|
|
|
|
sessionErr := h.auth.CreateSession(writer, request, user)
|
|
if sessionErr != nil {
|
|
h.log.Error("failed to create session", "error", sessionErr)
|
|
h.renderSetupError(
|
|
tmpl,
|
|
writer,
|
|
request,
|
|
formData.username,
|
|
"Failed to create session",
|
|
)
|
|
|
|
return
|
|
}
|
|
|
|
http.Redirect(writer, request, "/", http.StatusSeeOther)
|
|
}
|
|
}
|