Parent directory

settings_test.go

3542 bytes
  1package cmd
  2
  3import (
  4	"bytes"
  5	"context"
  6	"strings"
  7	"testing"
  8
  9	"github.com/charmbracelet/soft-serve/pkg/access"
 10	"github.com/charmbracelet/soft-serve/pkg/backend"
 11	"github.com/charmbracelet/soft-serve/pkg/config"
 12	"github.com/charmbracelet/soft-serve/pkg/db"
 13	"github.com/charmbracelet/soft-serve/pkg/db/migrate"
 14	"github.com/charmbracelet/soft-serve/pkg/proto"
 15	"github.com/charmbracelet/soft-serve/pkg/store"
 16	"github.com/charmbracelet/soft-serve/pkg/store/database"
 17	"github.com/matryer/is"
 18	_ "modernc.org/sqlite"
 19)
 20
 21// newSettingsTestContext returns a context wired with a config, a real
 22// migrated SQLite-backed backend, and an authenticated admin user, ready to
 23// execute SettingsCommand() against. Returns the config too, so tests can
 24// mutate AnonAccess/AllowKeyless to simulate a config override.
 25func newSettingsTestContext(t *testing.T) (context.Context, *config.Config) {
 26	t.Helper()
 27	is := is.New(t)
 28	ctx := context.Background()
 29
 30	dp := t.TempDir()
 31	cfg := config.DefaultConfig()
 32	cfg.DataPath = dp
 33	cfg.DB.Driver = "sqlite"
 34	cfg.DB.DataSource = dp + "/test.db"
 35
 36	ctx = config.WithContext(ctx, cfg)
 37	dbx, err := db.Open(ctx, cfg.DB.Driver, cfg.DB.DataSource)
 38	is.NoErr(err)
 39	t.Cleanup(func() { dbx.Close() }) //nolint:errcheck
 40
 41	is.NoErr(migrate.Migrate(ctx, dbx))
 42	dbstore := database.New(ctx, dbx)
 43	ctx = store.WithContext(ctx, dbstore)
 44	be := backend.New(ctx, cfg, dbx, dbstore)
 45	ctx = backend.WithContext(ctx, be)
 46
 47	// "admin" is already taken by the default user the migration seeds, so
 48	// use a distinct username for the test's admin.
 49	admin, err := be.CreateUser(ctx, "testadmin", proto.UserOptions{Admin: true})
 50	is.NoErr(err)
 51	ctx = proto.WithUserContext(ctx, admin)
 52
 53	return ctx, cfg
 54}
 55
 56func runSettings(t *testing.T, ctx context.Context, args ...string) (stdout, stderr string, err error) {
 57	t.Helper()
 58	c := SettingsCommand()
 59	var outBuf, errBuf bytes.Buffer
 60	c.SetOut(&outBuf)
 61	c.SetErr(&errBuf)
 62	c.SetArgs(args)
 63	err = c.ExecuteContext(ctx)
 64	return outBuf.String(), errBuf.String(), err
 65}
 66
 67func TestSettingsAnonAccessWarnsOnConfigOverride(t *testing.T) {
 68	is := is.New(t)
 69	ctx, cfg := newSettingsTestContext(t)
 70
 71	// No override active: setting anon-access should succeed silently.
 72	_, stderr, err := runSettings(t, ctx, "anon-access", "read-write")
 73	is.NoErr(err)
 74	is.Equal(stderr, "")
 75
 76	// With a config override active, the write still succeeds (so it takes
 77	// effect if the override is later removed), but must warn loudly that
 78	// it currently has no effect.
 79	adminAccess := access.AdminAccess
 80	cfg.AnonAccess = &adminAccess
 81	_, stderr, err = runSettings(t, ctx, "anon-access", "no-access")
 82	is.NoErr(err)
 83	if !strings.Contains(stderr, "override") {
 84		t.Fatalf("expected override warning on stderr, got: %q", stderr)
 85	}
 86}
 87
 88func TestSettingsAllowKeylessWarnsOnConfigOverride(t *testing.T) {
 89	is := is.New(t)
 90	ctx, cfg := newSettingsTestContext(t)
 91
 92	// No override active: setting allow-keyless should succeed silently.
 93	_, stderr, err := runSettings(t, ctx, "allow-keyless", "false")
 94	is.NoErr(err)
 95	is.Equal(stderr, "")
 96
 97	// With a config override active, the write still succeeds, but must
 98	// warn that it currently has no effect. This is the dangerous
 99	// direction: an admin trying to lock things down (false) while a
100	// config override forces it open (true).
101	allow := true
102	cfg.AllowKeyless = &allow
103	_, stderr, err = runSettings(t, ctx, "allow-keyless", "false")
104	is.NoErr(err)
105	if !strings.Contains(stderr, "override") {
106		t.Fatalf("expected override warning on stderr, got: %q", stderr)
107	}
108}