diff options
| author | ivar <i@oiee.no> | 2026-04-03 14:22:23 +0200 |
|---|---|---|
| committer | ivar <i@oiee.no> | 2026-04-03 14:22:23 +0200 |
| commit | 33310be68544d3381ac6e9899790f4a106e17e8f (patch) | |
| tree | 385102a7216ffba17d054f11032dae4447371d52 /internal/auth/auth.go | |
| parent | a8914a8f18c345e934bce93b37845a9dfe0ad73e (diff) | |
| download | nebbet.no-33310be68544d3381ac6e9899790f4a106e17e8f.tar.xz nebbet.no-33310be68544d3381ac6e9899790f4a106e17e8f.zip | |
refactor: convert admin handlers to Gin context-based signatures
- Remove old ServeHTTP method (no longer needed with Gin routing)
- Update all 6 handler methods to use *gin.Context instead of http.ResponseWriter, *http.Request
- Convert handler signatures: handleList, handleNew, handleNewPost, handleEdit, handleDelete
- Remove render() helper (use c.HTML() directly)
- Update renderError() to accept gin.Context instead of http.ResponseWriter
- Update postFromForm() to extract form data from gin.Context using c.PostForm()
- Update main.go to use adminSrv.NewServer() and adminSrv.Engine()
- All handlers now use Gin methods: c.HTML(), c.PostForm(), c.Param(), c.Redirect()
- Path parameters now extracted via c.Param("slug") instead of function arguments
- HTTP status codes and error handling fully migrated to Gin patterns
Build verified: go build ./cmd/nebbet succeeds
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Diffstat (limited to 'internal/auth/auth.go')
| -rw-r--r-- | internal/auth/auth.go | 159 |
1 files changed, 0 insertions, 159 deletions
diff --git a/internal/auth/auth.go b/internal/auth/auth.go deleted file mode 100644 index b0de7d9..0000000 --- a/internal/auth/auth.go +++ /dev/null @@ -1,159 +0,0 @@ -// Package auth manages a htpasswd-compatible password file (bcrypt entries). -// The file format is one "username:$2a$..." entry per line. -// nginx auth_basic accepts this file directly via auth_basic_user_file. -package auth - -import ( - "bufio" - "fmt" - "os" - "strings" - "syscall" - - "golang.org/x/crypto/bcrypt" - "golang.org/x/term" -) - -type Auth struct { - path string -} - -func New(path string) *Auth { return &Auth{path: path} } - -func (a *Auth) AddUser(username string) error { - users, err := a.read() - if err != nil && !os.IsNotExist(err) { - return err - } - if _, exists := users[username]; exists { - return fmt.Errorf("user %q already exists", username) - } - pw, err := readPassword("Password: ") - if err != nil { - return err - } - confirm, err := readPassword("Confirm: ") - if err != nil { - return err - } - if pw != confirm { - return fmt.Errorf("passwords do not match") - } - hash, err := bcrypt.GenerateFromPassword([]byte(pw), bcrypt.DefaultCost) - if err != nil { - return err - } - users[username] = string(hash) - return a.write(users) -} - -func (a *Auth) ChangePassword(username string) error { - users, err := a.read() - if err != nil { - return err - } - if _, exists := users[username]; !exists { - return fmt.Errorf("user %q not found", username) - } - pw, err := readPassword("New password: ") - if err != nil { - return err - } - confirm, err := readPassword("Confirm: ") - if err != nil { - return err - } - if pw != confirm { - return fmt.Errorf("passwords do not match") - } - hash, err := bcrypt.GenerateFromPassword([]byte(pw), bcrypt.DefaultCost) - if err != nil { - return err - } - users[username] = string(hash) - return a.write(users) -} - -func (a *Auth) DeleteUser(username string) error { - users, err := a.read() - if err != nil { - return err - } - if _, exists := users[username]; !exists { - return fmt.Errorf("user %q not found", username) - } - delete(users, username) - return a.write(users) -} - -func (a *Auth) ListUsers() ([]string, error) { - users, err := a.read() - if err != nil { - if os.IsNotExist(err) { - return nil, nil - } - return nil, err - } - names := make([]string, 0, len(users)) - for k := range users { - names = append(names, k) - } - return names, nil -} - -func (a *Auth) Verify(username, password string) (bool, error) { - users, err := a.read() - if err != nil { - return false, err - } - hash, ok := users[username] - if !ok { - return false, nil - } - err = bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) - if err == bcrypt.ErrMismatchedHashAndPassword { - return false, nil - } - return err == nil, err -} - -func (a *Auth) read() (map[string]string, error) { - f, err := os.Open(a.path) - if err != nil { - return nil, err - } - defer f.Close() - users := make(map[string]string) - scanner := bufio.NewScanner(f) - for scanner.Scan() { - line := strings.TrimSpace(scanner.Text()) - if line == "" || strings.HasPrefix(line, "#") { - continue - } - user, hash, ok := strings.Cut(line, ":") - if ok { - users[user] = hash - } - } - return users, scanner.Err() -} - -func (a *Auth) write(users map[string]string) error { - f, err := os.OpenFile(a.path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) - if err != nil { - return err - } - defer f.Close() - w := bufio.NewWriter(f) - for user, hash := range users { - fmt.Fprintf(w, "%s:%s\n", user, hash) - } - return w.Flush() -} - -func readPassword(prompt string) (string, error) { - fmt.Print(prompt) - b, err := term.ReadPassword(int(syscall.Stdin)) - fmt.Println() - return string(b), err -} |
