diff --git a/.air.toml b/.air.toml deleted file mode 100644 index 2f2e011..0000000 --- a/.air.toml +++ /dev/null @@ -1,52 +0,0 @@ -root = "." -testdata_dir = "testdata" -tmp_dir = "tmp" - -[build] -args_bin = [] -bin = "./tmp/main" -cmd = "go build -o ./tmp/main ." -delay = 1000 -exclude_dir = ["assets", "tmp", "vendor", "testdata", "scripts"] -exclude_file = [] -exclude_regex = ["_test.go"] -exclude_unchanged = false -follow_symlink = false -full_bin = "" -include_dir = [] -include_ext = ["go", "tpl", "tmpl", "html", "css", "js", "svg", "png"] -include_file = [] -kill_delay = "0s" -log = "build-errors.log" -poll = false -poll_interval = 0 -post_cmd = [] -pre_cmd = [] -rerun = false -rerun_delay = 500 -send_interrupt = false -stop_on_error = false - -[color] -app = "" -build = "yellow" -main = "magenta" -runner = "green" -watcher = "cyan" - -[log] -main_only = false -silent = false -time = false - -[misc] -clean_on_exit = false - -[proxy] -app_port = 8169 -enabled = true -proxy_port = 8170 - -[screen] -clear_on_rebuild = false -keep_scroll = true diff --git a/.gitignore b/.gitignore index 3d51441..e44b9f1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ .direnv .env .storage -result -tmp \ No newline at end of file +result \ No newline at end of file diff --git a/README.md b/README.md index be2dabe..e393cc5 100644 --- a/README.md +++ b/README.md @@ -4,45 +4,9 @@ yeah 4 of em.. ## Developing -highly recommended to use nix. its actually optional, but there's caveats. +use `nix shell` or `nix-shell` or maybe just run `go run .` or somethin its ok -**Quickstart** - -```sh -## - Step one, get an environment! -nix develop -# or -nix-shell -# or -direnv allow - -## - Step two, setup .env -cp .env.example .env -# fill out .env (the file has instructions) - -## - Step three, run the thing!! -just -# or .. maybe this.. but it may be unpredictable -go run . - -## - Step four, clean up the code -just precommit -``` - -> _the caveat: using `go` alone is doable. certain things won't happen, like dependency tagging and env var loading, so.. consider `nix`.._ - -### just commands - -- **watch** - (default) runs air livereloader - - open https://localhost:8170 for live reloading, note: the console will output 8169. that works too, but doesn't reload browser on changes -- **run** - runs the app with go run -- **nix-run** - runs the app built via nix (slower) -- **run-container** - builds the app as a docker image, then runs it. (slowest) -- **fmt** - go fmt and prettier -- **tidy** - fix gomods -- **test** - runs normal tests -- **update-vendor-hash** - updates `default.nix` vendorHash field, it won't build without it. -- **precommit** - runs fmt, tidy, update-vendor-hash, and test, in that order. +please run `just precommit` before committing thx, it fixes weird build issues ## Deploying diff --git a/authmiddleware/authmiddleware.go b/authmiddleware/authmiddleware.go index 41405cf..281bf02 100644 --- a/authmiddleware/authmiddleware.go +++ b/authmiddleware/authmiddleware.go @@ -21,16 +21,6 @@ type AuthMiddleware struct { superuserIDs []string } -func New(discordClient discord.IDiscordClient, supportIDs []string, superuserIDs []string) func(fiber.Ctx) error { - am := AuthMiddleware{ - Client: discordClient, - supportIDs: supportIDs, - superuserIDs: superuserIDs, - } - - return am.Handle -} - func (am *AuthMiddleware) Handle(c fiber.Ctx) error { sc := session.FromContext(c) sess := am.Init(sc) @@ -62,6 +52,16 @@ func (am *AuthMiddleware) Commit(sc *session.Middleware, sess *Session) { sc.Set(SessionKey, sess.AsJSON()) } +func SessionFrom(c fiber.Ctx) (s *Session) { + sess := session.FromContext(c) + sessionJSON := sess.Get(SessionKey).([]byte) + s, err := SessionFromJSON(sessionJSON) + if err != nil { + log.Panicln("session failed to parse", err) + } + return s +} + func (am *AuthMiddleware) isSupport(userID string) bool { return slices.Contains(am.supportIDs, userID) } diff --git a/authmiddleware/session.go b/authmiddleware/session.go index 34325bd..c2e9f3d 100644 --- a/authmiddleware/session.go +++ b/authmiddleware/session.go @@ -4,15 +4,10 @@ import ( "log" "time" + "git.sapphic.engineer/roleypoly/v4/discord" "git.sapphic.engineer/roleypoly/v4/types" "github.com/goccy/go-json" "github.com/gofiber/fiber/v3" - "github.com/gofiber/fiber/v3/middleware/session" -) - -var ( - SessionKey uint8 - DefaultSession *Session = &Session{Permissions: PermAnonymous} ) type Session struct { @@ -37,12 +32,16 @@ func SessionFromJSON(input []byte) (*Session, error) { return &s, err } -func SessionFrom(c fiber.Ctx) (s *Session) { - sess := session.FromContext(c) - sessionJSON := sess.Get(SessionKey).([]byte) - s, err := SessionFromJSON(sessionJSON) - if err != nil { - log.Panicln("session failed to parse", err) +var SessionKey uint8 + +func New(discordClient discord.IDiscordClient, supportIDs []string, superuserIDs []string) func(fiber.Ctx) error { + am := AuthMiddleware{ + Client: discordClient, + supportIDs: supportIDs, + superuserIDs: superuserIDs, } - return s + + return am.Handle } + +var DefaultSession *Session = &Session{Permissions: PermAnonymous} diff --git a/authmiddleware/util_test.go b/authmiddleware/util_test.go index b77099b..681407b 100644 --- a/authmiddleware/util_test.go +++ b/authmiddleware/util_test.go @@ -9,7 +9,6 @@ import ( "git.sapphic.engineer/roleypoly/v4/authmiddleware" "git.sapphic.engineer/roleypoly/v4/discord" "git.sapphic.engineer/roleypoly/v4/discord/clientmock" - "git.sapphic.engineer/roleypoly/v4/roleypoly" "git.sapphic.engineer/roleypoly/v4/types" "github.com/goccy/go-json" "github.com/gofiber/fiber/v3" @@ -103,7 +102,7 @@ func ok(c fiber.Ctx) error { } func getApp(dc discord.IDiscordClient) *fiber.App { - app := roleypoly.CreateFiberApp() + app := fiber.New(fiber.Config{}) sessionMiddleware, sessionStore := session.NewWithStore() sessionStore.RegisterType(authmiddleware.Session{}) diff --git a/default.nix b/default.nix index 1ff83fa..36ec488 100644 --- a/default.nix +++ b/default.nix @@ -1,6 +1,6 @@ { pkgs ? import {}, - vendorHash ? "sha256-ilEuRNE61UN22Jm6Yyv80S6VdRa1mB6J/Pde1x/DgEk=", + vendorHash ? "sha256-TvGGu74AWLrWRQvfAesVGJFTp4omPGVmIgyzB3QUKnc=", }: rec { default = roleypoly; diff --git a/interactions/interactions.go b/interactions/interactions.go index 3a5bcd1..0a80b2b 100644 --- a/interactions/interactions.go +++ b/interactions/interactions.go @@ -27,6 +27,7 @@ type Interactions struct { } func NewInteractions(publicKey string, publicBaseURL string, guildsService *discord.GuildService) *Interactions { + return &Interactions{ PublicKey: ed25519.PublicKey(publicKey), PublicBaseURL: publicBaseURL, @@ -40,7 +41,6 @@ func (i *Interactions) Routes(r fiber.Router) { r.Post("/", i.PostHandler) i.Router.Add("hello-world", i.CmdHelloWorld) - i.Router.Add("roleypoly", i.CmdRoleypoly) } func (i *Interactions) PostHandler(c fiber.Ctx) error { diff --git a/interactions/interactions_test.go b/interactions/interactions_test.go index 1abfcb6..1d2f1bf 100644 --- a/interactions/interactions_test.go +++ b/interactions/interactions_test.go @@ -7,13 +7,11 @@ import ( "net/http" "testing" - "git.sapphic.engineer/roleypoly/v4/authmiddleware" "git.sapphic.engineer/roleypoly/v4/discord" "git.sapphic.engineer/roleypoly/v4/interactions" "git.sapphic.engineer/roleypoly/v4/roleypoly" "github.com/goccy/go-json" "github.com/gofiber/fiber/v3" - "github.com/gofiber/fiber/v3/middleware/session" "github.com/stretchr/testify/assert" ) @@ -30,39 +28,7 @@ func TestNewInteractions(t *testing.T) { func TestPostHandler(t *testing.T) { i, _, key := makeInteractions(t) - app := roleypoly.CreateFiberApp() - i.Routes(app) - - body, err := json.Marshal(map[string]any{ - "type": 1, - }) - if err != nil { - t.Error(err) - return - } - - sig, ts := sign(t, key, body) - - req, _ := http.NewRequest("POST", "/", bytes.NewBuffer(body)) - req.Header.Add("X-Signature-Ed25519", sig) - req.Header.Add("X-Signature-Timestamp", ts) - - res, err := app.Test(req, fiber.TestConfig{}) - - assert.Nil(t, err) - assert.Equal(t, http.StatusOK, res.StatusCode) -} - -func TestPostHandlerIntegration(t *testing.T) { - i, dsm, key := makeInteractions(t) - app := roleypoly.CreateFiberApp() - - // Tests that everything works including auth middleware - sessionMiddleware, sessionStore := session.NewWithStore() - sessionStore.RegisterType(authmiddleware.Session{}) - app.Use(sessionMiddleware) - app.Use(authmiddleware.New(dsm, []string{}, []string{})) - + app := fiber.New() i.Routes(app) body, err := json.Marshal(map[string]any{ @@ -88,7 +54,6 @@ func TestPostHandlerIntegration(t *testing.T) { func TestPostHandlerSigFail(t *testing.T) { i, _, _ := makeInteractions(t) app := roleypoly.CreateFiberApp() - i.Routes(app) body, err := json.Marshal(map[string]any{ diff --git a/justfile b/justfile index 6e7217e..1bea0d0 100644 --- a/justfile +++ b/justfile @@ -1,6 +1,3 @@ -watch: - air - run: go run . @@ -18,13 +15,11 @@ fmt: go fmt ./... tidy: + go clean -modcache go mod tidy update-vendor-hash: scripts/update-vendor-hash.sh test: - go test ./... - -clean-repo: - rm -rf tmp result \ No newline at end of file + go test ./... \ No newline at end of file diff --git a/main.go b/main.go index a1ac032..a467e20 100644 --- a/main.go +++ b/main.go @@ -17,16 +17,11 @@ func main() { utils.DiscordBotToken, ) - roleypoly.SetupStatic(app) roleypoly.SetupControllers( app, - roleypoly.ControllerConfig{ - DiscordClient: dc, - PublicKey: utils.DiscordPublicKey, - PublicBaseURL: utils.PublicBaseURL, - SupportIDs: utils.SupportIDs, - SuperuserIDs: utils.SupueruserIDs, - }, + dc, + utils.DiscordPublicKey, + utils.PublicBaseURL, ) log.Fatal(app.Listen(utils.ListenAddr)) diff --git a/roleypoly/fiber.go b/roleypoly/fiber.go index d546d41..33a5706 100644 --- a/roleypoly/fiber.go +++ b/roleypoly/fiber.go @@ -19,7 +19,6 @@ import ( staticfs "git.sapphic.engineer/roleypoly/v4/static" "git.sapphic.engineer/roleypoly/v4/templates" "git.sapphic.engineer/roleypoly/v4/testing" - "git.sapphic.engineer/roleypoly/v4/types" ) func CreateFiberApp() *fiber.App { @@ -32,6 +31,24 @@ func CreateFiberApp() *fiber.App { ViewsLayout: "layouts/main", }) + sessionMiddleware, sessionStore := session.NewWithStore() + sessionStore.RegisterType(authmiddleware.Session{}) + + app.Use(sessionMiddleware) + app.Use(csrf.New(csrf.Config{ + Session: sessionStore, + })) + + app.Get("/static*", static.New("", static.Config{ + FS: staticfs.FS, + Compress: true, + CacheDuration: 24 * 8 * time.Hour, + })) + app.Get("/favicon.ico", oneStatic) + app.Get("/manifest.json", oneStatic) + app.Get("/robots.txt", oneStatic) + app.Get("/humans.txt", oneStatic) + return app } @@ -46,49 +63,16 @@ func oneStatic(c fiber.Ctx) error { return c.SendStream(f) } -func SetupStatic(app *fiber.App) { - app.Get("/static*", static.New("", static.Config{ - FS: staticfs.FS, - Compress: true, - CacheDuration: 24 * 8 * time.Hour, - })) - app.Get("/favicon.ico", oneStatic) - app.Get("/manifest.json", oneStatic) - app.Get("/robots.txt", oneStatic) - app.Get("/humans.txt", oneStatic) -} +func SetupControllers(app *fiber.App, dc *discord.DiscordClient, publicKey string, publicBaseURL string) { + gs := discord.NewGuildService(dc) -type ControllerConfig struct { - DiscordClient discord.IDiscordClient - PublicKey string - PublicBaseURL string - SupportIDs []string - SuperuserIDs []string -} + (&testing.TestingController{ + Guilds: gs, + }).Routes(app.Group("/testing")) -func SetupControllers(app *fiber.App, cfg ControllerConfig) { - app.Use(func(c fiber.Ctx) error { - c.Locals(types.ConfigKey, cfg) - return c.Next() - }) - - sessionMiddleware, sessionStore := session.NewWithStore() - sessionStore.RegisterType(authmiddleware.Session{}) - - app.Use(sessionMiddleware) - app.Use(csrf.New(csrf.Config{ - Session: sessionStore, - })) - app.Use(authmiddleware.New(cfg.DiscordClient, cfg.SupportIDs, cfg.SuperuserIDs)) - - gs := discord.NewGuildService(cfg.DiscordClient) - - (&testing.TestingController{Guilds: gs}). - Routes(app.Group("/testing")) - - interactions.NewInteractions(cfg.PublicKey, cfg.PublicBaseURL, gs). - Routes(app.Group("/interactions")) + interactions.NewInteractions(publicKey, publicBaseURL, gs).Routes(app.Group("/interactions")) + app.Use(authmiddleware.New(dc, []string{}, []string{})) } // func getStorageDirectory() string { diff --git a/roleypoly/fiber_test.go b/roleypoly/fiber_test.go deleted file mode 100644 index ea85bcf..0000000 --- a/roleypoly/fiber_test.go +++ /dev/null @@ -1,40 +0,0 @@ -package roleypoly_test - -import ( - "bytes" - "net/http" - "testing" - - "git.sapphic.engineer/roleypoly/v4/roleypoly" - "github.com/stretchr/testify/assert" -) - -func TestStaticRoot(t *testing.T) { - app := roleypoly.CreateFiberApp() - roleypoly.SetupStatic(app) - - req, err := http.NewRequest("GET", "/humans.txt", nil) - assert.Nil(t, err) - - resp, err := app.Test(req) - assert.Nil(t, err) - - buf := bytes.Buffer{} - buf.ReadFrom(resp.Body) - assert.Equal(t, "you're on thin ice, soup head.", buf.String()) -} - -func TestStaticPath(t *testing.T) { - app := roleypoly.CreateFiberApp() - roleypoly.SetupStatic(app) - - req, err := http.NewRequest("GET", "/static/humans.txt", nil) - assert.Nil(t, err) - - resp, err := app.Test(req) - assert.Nil(t, err) - - buf := bytes.Buffer{} - buf.ReadFrom(resp.Body) - assert.Equal(t, "you're on thin ice, soup head.", buf.String()) -} diff --git a/shell.nix b/shell.nix index 944bef8..d55a473 100644 --- a/shell.nix +++ b/shell.nix @@ -3,6 +3,6 @@ go just nil - air + just ]; } diff --git a/static/humans.txt b/static/humans.txt deleted file mode 100644 index 4c416a0..0000000 --- a/static/humans.txt +++ /dev/null @@ -1 +0,0 @@ -you're on thin ice, soup head. \ No newline at end of file diff --git a/templates/tests/landing.html b/templates/tests/landing.html deleted file mode 100644 index e69de29..0000000 diff --git a/types/keys.go b/types/keys.go deleted file mode 100644 index 7c38735..0000000 --- a/types/keys.go +++ /dev/null @@ -1,3 +0,0 @@ -package types - -var ConfigKey int diff --git a/utils/env.go b/utils/env.go index 2007562..7a3294c 100644 --- a/utils/env.go +++ b/utils/env.go @@ -1,9 +1,6 @@ package utils -import ( - "os" - "strings" -) +import "os" var ( DiscordBotToken = os.Getenv("DISCORD_BOT_TOKEN") @@ -12,6 +9,4 @@ var ( DiscordPublicKey = os.Getenv("DISCORD_PUBLIC_KEY") ListenAddr = Or(os.Getenv("LISTEN_ADDR"), ":8169") PublicBaseURL = os.Getenv("PUBLIC_BASE_URL") - SupportIDs = strings.Split(os.Getenv("SUPPORT_IDS"), ",") - SupueruserIDs = strings.Split(os.Getenv("SUPERUSER_IDS"), ",") )