Signup handles POST /auth/signup (public, when signup enabled).
(w http.ResponseWriter, r *http.Request)
| 1370 | |
| 1371 | // Signup handles POST /auth/signup (public, when signup enabled). |
| 1372 | func (h *AuthHandler) Signup(w http.ResponseWriter, r *http.Request) { |
| 1373 | if h.log != nil { |
| 1374 | h.log.Debug("auth request", "method", r.Method, "path", r.URL.Path) |
| 1375 | } |
| 1376 | s, err := h.settings.GetFirst(r.Context()) |
| 1377 | if err != nil || s == nil || !s.SignupEnabled { |
| 1378 | Error(w, http.StatusForbidden, "User signup is currently disabled") |
| 1379 | return |
| 1380 | } |
| 1381 | |
| 1382 | var req struct { |
| 1383 | FirstName string `json:"firstName"` |
| 1384 | LastName string `json:"lastName"` |
| 1385 | Username string `json:"username"` |
| 1386 | Email string `json:"email"` |
| 1387 | Password string `json:"password"` |
| 1388 | } |
| 1389 | if err := decodeJSON(r, &req); err != nil { |
| 1390 | Error(w, http.StatusBadRequest, "Invalid request body") |
| 1391 | return |
| 1392 | } |
| 1393 | if req.FirstName == "" || req.LastName == "" || req.Username == "" || req.Email == "" || req.Password == "" { |
| 1394 | Error(w, http.StatusBadRequest, "All fields are required") |
| 1395 | return |
| 1396 | } |
| 1397 | if len(req.Username) < 3 { |
| 1398 | Error(w, http.StatusBadRequest, "Username must be at least 3 characters") |
| 1399 | return |
| 1400 | } |
| 1401 | if err := ValidatePasswordPolicy(h.resolved, req.Password); err != nil { |
| 1402 | Error(w, http.StatusBadRequest, err.Error()) |
| 1403 | return |
| 1404 | } |
| 1405 | |
| 1406 | exists, _ := h.users.ExistsByUsernameOrEmail(r.Context(), req.Username, req.Email, "") |
| 1407 | if exists { |
| 1408 | Error(w, http.StatusConflict, "Username or email already exists") |
| 1409 | return |
| 1410 | } |
| 1411 | |
| 1412 | role := s.DefaultUserRole |
| 1413 | if role == "" && h.resolved != nil { |
| 1414 | role = h.resolved.DefaultUserRole |
| 1415 | } |
| 1416 | if role == "" { |
| 1417 | role = "user" |
| 1418 | } |
| 1419 | |
| 1420 | hash, err := bcrypt.GenerateFromPassword([]byte(req.Password), 12) |
| 1421 | if err != nil { |
| 1422 | Error(w, http.StatusInternalServerError, "Failed to create account") |
| 1423 | return |
| 1424 | } |
| 1425 | hashStr := string(hash) |
| 1426 | |
| 1427 | u := &models.User{ |
| 1428 | Username: req.Username, |
| 1429 | Email: req.Email, |
nothing calls this directly
no test coverage detected