From 840935d22d221d20c3e97d2ddc05da67f67d03b9 Mon Sep 17 00:00:00 2001 From: Jakub Zych Date: Sun, 4 Oct 2026 23:15:01 +0200 Subject: [PATCH] refactor: drop the quiz import and the golem15.quizzes dependency golem15.quizzes now serves its own import at /api/v1/quizzes/import behind the same shared API token. --- controllers/api/manage.go | 36 ------------------------------------ go.mod | 3 --- plugin.go | 5 ++--- plugin_test.go | 9 +++------ routes.go | 3 +-- static_test.go | 3 +-- 6 files changed, 7 insertions(+), 52 deletions(-) diff --git a/controllers/api/manage.go b/controllers/api/manage.go index d9a6c1e..e91454e 100644 --- a/controllers/api/manage.go +++ b/controllers/api/manage.go @@ -12,7 +12,6 @@ import ( "time" "unicode" - quizzes "git.golem15.com/golem15/sm-quizzes-plugin/classes" usermodels "git.golem15.com/golem15/sm-user-plugin/models" "git.golem15.com/golem15/summercms/modules/bouncer" "git.golem15.com/golem15/summercms/modules/lagoon" @@ -134,41 +133,6 @@ func (h *Handlers) ApplySeed(w http.ResponseWriter, r *http.Request) { }) } -// ImportQuiz answers POST /quizzes?replace=: quizzes:import over HTTP. The -// body is the quiz document of golem15.quizzes. An existing slug is a 409 -// unless replace is on. -func (h *Handlers) ImportQuiz(w http.ResponseWriter, r *http.Request) { - raw, ok := body(w, r) - if !ok { - return - } - doc, err := quizzes.ParseImport(raw) - if err != nil { - writeInvalid(w, err.Error()) - return - } - db, ok := h.db(w, r) - if !ok { - return - } - res, err := quizzes.Import(r.Context(), db, doc, flag(r, "replace")) - if errors.Is(err, quizzes.ErrQuizExists) { - wire.WriteJSON(w, http.StatusConflict, map[string]any{"error": true, "message": "A quiz with the slug " + doc.Slug + " already exists; pass replace=1 to replace its questions."}) - return - } - if err != nil { - writeOpaque500(w) - return - } - writeData(w, map[string]any{ - "id": res.Quiz.ID, - "slug": res.Quiz.Slug, - "created": res.Created, - "questions": res.Questions, - "answers": res.Answers, - }) -} - // managedMaterialJSON is a material as the management API shows it: drafts // too, so published_at may be null. type managedMaterialJSON struct { diff --git a/go.mod b/go.mod index 630008b..369a1c5 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,6 @@ module git.golem15.com/jakub/sm-bm-plugin go 1.27.0 require ( - git.golem15.com/golem15/sm-quizzes-plugin v0.0.0 git.golem15.com/golem15/sm-user-plugin v0.0.0 git.golem15.com/golem15/summercms v0.0.0 github.com/go-gormigrate/gormigrate/v2 v2.1.7 @@ -122,5 +121,3 @@ require ( replace git.golem15.com/golem15/summercms => ../../../../summercms.go replace git.golem15.com/golem15/sm-user-plugin => ../../golem15/user - -replace git.golem15.com/golem15/sm-quizzes-plugin => ../../golem15/quizzes diff --git a/plugin.go b/plugin.go index 1fbf6a1..bd779f3 100644 --- a/plugin.go +++ b/plugin.go @@ -54,9 +54,8 @@ type Plugin struct { func (p *Plugin) ID() string { return "jz.bm" } // Requires golem15.user: its users table holds the students, and its -// jwt.auth middleware guards the API. golem15.quizzes holds the quizzes the -// management API imports. -func (p *Plugin) Requires() []string { return []string{"golem15.user", "golem15.quizzes"} } +// jwt.auth and user.api_token middleware guard the APIs. +func (p *Plugin) Requires() []string { return []string{"golem15.user"} } func (p *Plugin) Register(app *backpack.App) error { p.app = app diff --git a/plugin_test.go b/plugin_test.go index 002deee..e187844 100644 --- a/plugin_test.go +++ b/plugin_test.go @@ -7,7 +7,6 @@ import ( "strings" "testing" - _ "git.golem15.com/golem15/sm-quizzes-plugin" _ "git.golem15.com/golem15/sm-user-plugin" "git.golem15.com/golem15/summercms/modules/backpack" "git.golem15.com/golem15/summercms/modules/bonfire" @@ -48,11 +47,10 @@ func testConfig(t *testing.T) *compass.Config { return cfg } -// activate boots the plugin and both declared dependencies the way the -// generated main does. +// activate boots golem15.user and jz.bm the way the generated main does. func activate(t *testing.T, app *backpack.App) []party.Plugin { t.Helper() - plugins, err := party.Activate(app, []string{"golem15.user", "golem15.quizzes", "jz.bm"}) + plugins, err := party.Activate(app, []string{"golem15.user", "jz.bm"}) if err != nil { t.Fatalf("Activate: %v", err) } @@ -73,7 +71,7 @@ func bmPlugin(t *testing.T, plugins []party.Plugin) *bm.Plugin { func TestPluginActivates(t *testing.T) { app := backpack.New(testConfig(t)) p := bmPlugin(t, activate(t, app)) - if p.ID() != "jz.bm" || !slices.Equal(p.Requires(), []string{"golem15.user", "golem15.quizzes"}) { + if p.ID() != "jz.bm" || !slices.Equal(p.Requires(), []string{"golem15.user"}) { t.Errorf("ID %q Requires %v", p.ID(), p.Requires()) } if n := len(p.Models()); n != 10 { @@ -125,7 +123,6 @@ func TestRoutes(t *testing.T) { "POST /api/v1/bm/materials", "DELETE /api/v1/bm/materials/{id}", "POST /api/v1/bm/seed", - "POST /api/v1/bm/quizzes", } var got []string sawFeed := false diff --git a/routes.go b/routes.go index 2c80d7b..1ac5e54 100644 --- a/routes.go +++ b/routes.go @@ -91,7 +91,7 @@ func (p *Plugin) Routes(r pact.Router) error { g.Post("/calendar-feed/rotate", h.RotateCalendarFeed, "throttle:10,1") g.Delete("/calendar-feed", h.DeleteCalendarFeed) }) - // The management API: what bm:seed and quizzes:import do, plus materials, + // The management API: what bm:seed does, plus materials, // behind the application-wide user API token. Scope limits delegation; // user.permission checks the owner's current group permissions. r.Group(ManagePrefix, surf.Use(bucketManage, "user.api_token"), func(g pact.Router) { @@ -105,7 +105,6 @@ func (p *Plugin) Routes(r pact.Router) error { "user.permission:"+controllers.PermCourses, "user.permission:"+controllers.PermSchedule, "user.permission:"+controllers.PermMaterials) - g.Post("/quizzes", h.ImportQuiz, "user.scope:write", "user.permission:golem15.quizzes.access_quizzes") }) // The calendar feed: public, because calendar clients fetch it without // credentials; the token in the path is the credential. ServeMux cannot diff --git a/static_test.go b/static_test.go index 6924355..1c2484e 100644 --- a/static_test.go +++ b/static_test.go @@ -10,7 +10,6 @@ import ( "testing" "testing/fstest" - _ "git.golem15.com/golem15/sm-quizzes-plugin" _ "git.golem15.com/golem15/sm-user-plugin" "git.golem15.com/golem15/summercms/modules/backpack" "git.golem15.com/golem15/summercms/modules/compass" @@ -220,7 +219,7 @@ func TestStaticThroughRouter(t *testing.T) { t.Fatal(err) } app := backpack.New(cfg) - plugins, err := party.Activate(app, []string{"golem15.user", "golem15.quizzes", "jz.bm"}) + plugins, err := party.Activate(app, []string{"golem15.user", "jz.bm"}) if err != nil { t.Fatal(err) }