list

web

Repo with a simple http server with auth to serve my email.

curl -O https://dovel.email/web.tar.gz tar.gz

a2f4f0d

Author: blmayer (bleemayer@gmail.com)

Date: Wed Nov 15 10:10:36 2023 -0300

Parent: e0ebb54

Fixed auth

Diff

Makefile

diff --git a/Makefile b/Makefile
index e8310ec..97bfad2 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 
 deploy: $(wildcard cmd/web/*.go)
 	GOARCH=arm GOARM=6 go build $^
-	scp main zero:dovel-web
+	scp -O main zero:dovel-web
 	ssh zero "mv dovel-web .local/bin"
 
 deploy-certs: fullchain.pem privkey.pem

cmd/web/main.go

diff --git a/cmd/web/main.go b/cmd/web/main.go
index 91bb1c8..819a891 100644
--- a/cmd/web/main.go
+++ b/cmd/web/main.go
@@ -2,12 +2,10 @@ package main
 
 import (
 	"encoding/json"
+	"log/slog"
 	"net/http"
 	"os"
 	"path"
-	"log/slog"
-
-	"git.derelict.garden/bryon/vault"
 )
 
 type Config struct {
@@ -29,13 +27,20 @@ func (u user) Pass() string {
 }
 
 var (
-	v   vault.Vault[user]
+	v   *vault
 	cfg Config
 )
 
 func private(w http.ResponseWriter, r *http.Request) {
-	name, pass, ok := r.BasicAuth()
-	if !ok || name == "" || pass == "" {
+	name, pass, _ := r.BasicAuth()
+	if name == "" || pass == "" {
+		w.Header().Add("WWW-Authenticate", "Basic")
+		w.WriteHeader(http.StatusUnauthorized)
+		return
+	}
+	slog.Debug("authenticating request", "user", name, "pass", pass)
+	if !v.Validate(name, pass) {
+		slog.Debug("authentication failed")
 		w.Header().Add("WWW-Authenticate", "Basic")
 		w.WriteHeader(http.StatusUnauthorized)
 		return
@@ -49,6 +54,14 @@ func private(w http.ResponseWriter, r *http.Request) {
 }
 
 func main() {
+	if os.Getenv("DEBUG") != "" {
+		slog.SetDefault(
+			slog.New(slog.NewTextHandler(
+				os.Stdout, &slog.HandlerOptions{
+					Level: slog.LevelDebug,
+				})),
+		)
+	}
 	configPath, err := os.UserConfigDir()
 	if err != nil {
 		println(err, "using ~/.config/dovel/web.json")
@@ -61,9 +74,9 @@ func main() {
 		panic("open config: " + err.Error())
 	}
 	json.NewDecoder(configFile).Decode(&cfg)
-	slog.Info("loaded config", cfg)
+	slog.Info("loaded", "config", cfg)
 
-	v, err = vault.NewJSONPlainTextVault[user](path.Join(configPath, "users.json"))
+	v, err = NewVault(path.Join(configPath, "users.json"))
 	if err != nil {
 		panic("new vault: " + err.Error())
 	}

cmd/web/vault.go

diff --git a/cmd/web/vault.go b/cmd/web/vault.go
new file mode 100644
index 0000000..5e89c9a
--- /dev/null
+++ b/cmd/web/vault.go
@@ -0,0 +1,56 @@
+package main
+
+import (
+	"crypto/sha256"
+	"encoding/json"
+	"fmt"
+	"log/slog"
+	"os"
+	"sync"
+)
+
+type vault struct {
+	mu    sync.Mutex
+	path  string
+	Users []user
+}
+
+func NewVault(path string) (*vault, error) {
+	s := &vault{Users: []user{}, path: path, mu: sync.Mutex{}}
+
+	file, err := os.Open(path)
+	if err != nil {
+		return s, err
+	}
+	defer file.Close()
+
+	err = json.NewDecoder(file).Decode(&s.Users)
+	if err != nil {
+		return s, err
+	}
+	slog.Debug("vault", "users", s.Users)
+
+	return s, nil
+}
+
+func (v *vault) GetUser(login string) user {
+	for _, u := range v.Users {
+		if u.Name == login {
+			return u
+		}
+	}
+	return user{}
+}
+
+func (v *vault) Validate(login, pass string) bool {
+	user := v.GetUser(login)
+	if user.Name != "" {
+		shapass := fmt.Sprintf("%x", sha256.Sum256([]byte(pass)))
+		slog.Debug("vault", "sha256", shapass)
+		if user.Pass() == shapass {
+			return true
+		}
+	}
+	return false
+}
+