summaryrefslogtreecommitdiffstats
path: root/internal/auth/auth.go
diff options
context:
space:
mode:
authorivar <i@oiee.no>2026-04-03 14:22:23 +0200
committerivar <i@oiee.no>2026-04-03 14:22:23 +0200
commit33310be68544d3381ac6e9899790f4a106e17e8f (patch)
tree385102a7216ffba17d054f11032dae4447371d52 /internal/auth/auth.go
parenta8914a8f18c345e934bce93b37845a9dfe0ad73e (diff)
downloadnebbet.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.go159
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
-}