SQLite replaces Postgres, and two fixes from using the thing. - The database is a file under ./storage instead of a second container. Ten members never needed a database server, and the driver is pure Go, so the build stays CGO_ENABLED=0 and the dependency count is unchanged. One bind mount is now the whole backup: no pgdata, no healthcheck-gated depends_on, no startup retry loop. Timestamps are UTC text, idle_ttl is seconds, the divisive/unified boards carry their own stddev, and foreign keys are on by pragma. Tests get a database file each and run without any setup - Invites are copied, not clicked. An invite is something to send, and the anchor opened the join form in the admin's own browser - Feedback asks for more than faults: the footer reads "Ongelmia? Ideoita? Palautetta?" and the page behind it invites ideas rather than only bugs - Kuuntele YouTubessa opens in a new tab, so a half-typed review survives it
59 lines
1.5 KiB
Go
59 lines
1.5 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
)
|
|
|
|
func TestRequireAdmin(t *testing.T) {
|
|
a := &app{cfg: config{adminUser: "admin", adminPass: "s3cret"}}
|
|
h := a.requireAdmin(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusTeapot)
|
|
}))
|
|
|
|
for _, tc := range []struct {
|
|
name, user, pass string
|
|
auth bool
|
|
want int
|
|
}{
|
|
{name: "no credentials", want: http.StatusUnauthorized},
|
|
{name: "wrong password", user: "admin", pass: "hunter2", auth: true, want: http.StatusUnauthorized},
|
|
{name: "wrong user", user: "root", pass: "s3cret", auth: true, want: http.StatusUnauthorized},
|
|
{name: "correct", user: "admin", pass: "s3cret", auth: true, want: http.StatusTeapot},
|
|
} {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
r := httptest.NewRequest("GET", "/admin", nil)
|
|
if tc.auth {
|
|
r.SetBasicAuth(tc.user, tc.pass)
|
|
}
|
|
w := httptest.NewRecorder()
|
|
h.ServeHTTP(w, r)
|
|
if w.Code != tc.want {
|
|
t.Fatalf("status = %d, want %d", w.Code, tc.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestMigrateIsIdempotent(t *testing.T) {
|
|
ctx := context.Background()
|
|
a := testApp(t) // already migrated once
|
|
|
|
if err := migrate(ctx, a.db); err != nil {
|
|
t.Fatalf("second migrate: %v", err)
|
|
}
|
|
if err := sweep(ctx, a.db); err != nil {
|
|
t.Fatalf("sweep: %v", err)
|
|
}
|
|
|
|
var n int
|
|
if err := a.db.QueryRowContext(ctx, `select count(*) from schema_migrations`).Scan(&n); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if n != 1 {
|
|
t.Fatalf("applied migrations = %d, want 1", n)
|
|
}
|
|
}
|