From c110103899fef6cccc2ace2088b3a8c4ec3d18e1 Mon Sep 17 00:00:00 2001 From: Seongmin Lee Date: Tue, 21 Jul 2026 16:00:57 +0900 Subject: [PATCH] spindle: add admin subcommand Signed-off-by: Seongmin Lee --- cmd/spindle/main.go | 26 ++++++++++++++++++++++++-- spindle/acl.go | 39 +++++++++++++++++++++++++++++++++++++++ spindle/config/config.go | 1 + spindle/db/acl.go | 39 +++++++++++++++++++++++++++++++++++++++ spindle/db/db.go | 16 ++++++++++++++++ 5 files changed, 119 insertions(+), 2 deletions(-) create mode 100644 spindle/acl.go create mode 100644 spindle/db/acl.go diff --git a/cmd/spindle/main.go b/cmd/spindle/main.go index c377a7ca..6ea8d622 100644 --- a/cmd/spindle/main.go +++ b/cmd/spindle/main.go @@ -15,7 +15,8 @@ func main() { Name: "spindle", Usage: "spindle continuous integration runner", Commands: []*cli.Command{ - Command(), + Run(), + adminCmd, }, DefaultCommand: "run", } @@ -32,7 +33,7 @@ func main() { } } -func Command() *cli.Command { +func Run() *cli.Command { return &cli.Command{ Name: "run", Usage: "run the spindle server", @@ -41,3 +42,24 @@ func Command() *cli.Command { }, } } + +var adminCmd = &cli.Command{ + Name: "admin", + Commands: []*cli.Command{ + { + Name: "allow", + Usage: "allow user to use spindle", + Action: func(ctx context.Context, c *cli.Command) error { + return spindle.AllowMember(ctx) + }, + }, + { + Name: "block", + Usage: "block user to use spindle", + Action: func(ctx context.Context, c *cli.Command) error { + return spindle.BlockMember(ctx) + }, + }, + }, +} + diff --git a/spindle/acl.go b/spindle/acl.go new file mode 100644 index 00000000..90fabafe --- /dev/null +++ b/spindle/acl.go @@ -0,0 +1,39 @@ +package spindle + +import ( + "context" + "fmt" + + "github.com/bluesky-social/indigo/atproto/syntax" + "tangled.org/core/spindle/config" +) + +func AllowMember(ctx context.Context) error { + var user syntax.DID + + cfg, err := config.Load(ctx) + if err != nil { + return fmt.Errorf("failed to load config: %w", err) + } + + // TODO: upsert user policy to "allowed" + + _, _ = user, cfg + + panic("unimplemented") +} + +func BlockMember(ctx context.Context) error { + var user syntax.DID + + cfg, err := config.Load(ctx) + if err != nil { + return fmt.Errorf("failed to load config: %w", err) + } + + // TODO: upsert user policy to "blocked" + + _, _ = user, cfg + + panic("unimplemented") +} diff --git a/spindle/config/config.go b/spindle/config/config.go index 661e35f7..7cdfb8af 100644 --- a/spindle/config/config.go +++ b/spindle/config/config.go @@ -25,6 +25,7 @@ type Server struct { QueueSize int `env:"QUEUE_SIZE, default=100"` MaxJobCount int `env:"MAX_JOB_COUNT, default=2"` // max number of pipelines that run at a time DockerSocket string `env:"DOCKER_SOCKET"` // path to a docker socket to expose to workflow containers + InviteOnly bool `env:"INVITE_ONLY, default=true"` } type Tap struct { diff --git a/spindle/db/acl.go b/spindle/db/acl.go new file mode 100644 index 00000000..ba7af9b5 --- /dev/null +++ b/spindle/db/acl.go @@ -0,0 +1,39 @@ +package db + +import ( + "context" + + "github.com/bluesky-social/indigo/atproto/syntax" +) + +func (d *DB) AddAllowedUser(ctx context.Context, user syntax.DID) error { + _, err := d.ExecContext(ctx, + `insert or ignore into spindle_allowlist (did) values (?)`, + user, + ) + return err +} + +func (d *DB) RemoveAllowedUser(ctx context.Context, user syntax.DID) error { + _, err := d.ExecContext(ctx, + `delete from spindle_allowlist where did = ?`, + user, + ) + return err +} + +func (d *DB) AddBlockedUser(ctx context.Context, user syntax.DID) error { + _, err := d.ExecContext(ctx, + `insert or ignore into spindle_blocklist (did) values (?)`, + user, + ) + return err +} + +func (d *DB) RemoveBlockedUser(ctx context.Context, user syntax.DID) error { + _, err := d.ExecContext(ctx, + `delete from spindle_blocklist where did = ?`, + user, + ) + return err +} diff --git a/spindle/db/db.go b/spindle/db/db.go index 8a74d6d2..c8396905 100644 --- a/spindle/db/db.go +++ b/spindle/db/db.go @@ -261,6 +261,22 @@ func runMigrations(_ context.Context, conn *sql.Conn, logger *slog.Logger) error return err } + if err := orm.RunMigration(conn, logger, "spindle-local-memberlist", func(tx *sql.Tx) error { + _, err := tx.Exec(` + create table spindle_members_new ( + did text not null primary key, + blocked integer not null default 0 + ); + + insert into spindle_members_new (did) + select distinct did + from spindle_members; + `) + return err + }); err != nil { + return err + } + return nil } -- 2.51.2