Create creates a new user.
(w http.ResponseWriter, r *http.Request)
| 149 | |
| 150 | // Create creates a new user. |
| 151 | func (h *UsersHandler) Create(w http.ResponseWriter, r *http.Request) { |
| 152 | var req struct { |
| 153 | Username string `json:"username"` |
| 154 | Email string `json:"email"` |
| 155 | Password string `json:"password"` |
| 156 | FirstName *string `json:"first_name"` |
| 157 | LastName *string `json:"last_name"` |
| 158 | Role string `json:"role"` |
| 159 | } |
| 160 | if err := decodeJSON(r, &req); err != nil { |
| 161 | Error(w, http.StatusBadRequest, "Invalid request body") |
| 162 | return |
| 163 | } |
| 164 | if len(req.Username) < 3 { |
| 165 | Error(w, http.StatusBadRequest, "Username must be at least 3 characters") |
| 166 | return |
| 167 | } |
| 168 | if req.Email == "" { |
| 169 | Error(w, http.StatusBadRequest, "Valid email is required") |
| 170 | return |
| 171 | } |
| 172 | if req.Password == "" { |
| 173 | Error(w, http.StatusBadRequest, "Password is required") |
| 174 | return |
| 175 | } |
| 176 | if err := ValidatePasswordPolicy(h.resolved, req.Password); err != nil { |
| 177 | Error(w, http.StatusBadRequest, err.Error()) |
| 178 | return |
| 179 | } |
| 180 | |
| 181 | role := req.Role |
| 182 | if role == "" { |
| 183 | s, _ := h.settings.GetFirst(r.Context()) |
| 184 | if s != nil && s.DefaultUserRole != "" { |
| 185 | role = s.DefaultUserRole |
| 186 | } |
| 187 | if role == "" && h.resolved != nil { |
| 188 | role = h.resolved.DefaultUserRole |
| 189 | } |
| 190 | if role == "" && os.Getenv("DEFAULT_USER_ROLE") != "" { |
| 191 | role = strings.TrimSpace(os.Getenv("DEFAULT_USER_ROLE")) |
| 192 | } |
| 193 | if role == "" { |
| 194 | role = "user" |
| 195 | } |
| 196 | } |
| 197 | |
| 198 | // Enforce role escalation protection. |
| 199 | callerRole, _ := r.Context().Value(middleware.UserRoleKey).(string) |
| 200 | if !h.canAssignRole(r, callerRole, role) { |
| 201 | Error(w, http.StatusForbidden, "You do not have permission to assign the role: "+role) |
| 202 | return |
| 203 | } |
| 204 | |
| 205 | exists, err := h.users.ExistsByUsernameOrEmail(r.Context(), req.Username, req.Email, "") |
| 206 | if err != nil || exists { |
| 207 | Error(w, http.StatusConflict, "Username or email already exists") |
| 208 | return |
no test coverage detected