fix(09): WR-09 scaffold admin controllers with a required permission and a record source placeholder

This commit is contained in:
Jakub Zych
2026-10-01 21:13:40 +02:00
parent 8b48eea4e1
commit 20a79c5df4
5 changed files with 29 additions and 2 deletions

View File

@@ -34,6 +34,7 @@ type artifactData struct {
DownSQL string
CommandName string
Description string
Permission string
}
var migrationNow = func() time.Time { return time.Now().UTC() }
@@ -265,6 +266,7 @@ func MakeAdminController(ctx context.Context, startDir, pluginID, name string) (
ConfigDir: configDir,
PluginPath: strings.ReplaceAll(plugin.ID, ".", "/"),
Snake: snake,
Permission: plugin.ID + ".access_" + snake,
}
src, err := renderStub("admin_controller.go", data)
if err != nil {

View File

@@ -769,6 +769,12 @@ func TestScaffoldAllArtifacts(t *testing.T) {
`ID() string { return "golem15.demo.albums" }`,
`ModelName() string { return "Albums" }`,
`ConfigDir() string { return "controllers/albums" }`,
// WR-09: the scaffold is never open to every administrator and names
// its record source, so completing it cannot silently expose the data.
`pact.AdminPermissioned = albumsAdmin{}`,
`RequiredPermissions() []string`,
`return []string{"golem15.demo.access_albums"}`,
`NewRecord() any { return nil }`,
} {
if !bytes.Contains(adminSrc, []byte(want)) {
t.Fatalf("albums.go missing %s:\n%s", want, adminSrc)

View File

@@ -90,12 +90,31 @@ package controllers
import "git.golem15.com/golem15/summercms/modules/pact"
var (
_ pact.AdminController = {{.Worker}}{}
_ pact.AdminRecordSource = {{.Worker}}{}
_ pact.AdminPermissioned = {{.Worker}}{}
)
type {{.Worker}} struct{}
func ({{.Worker}}) ID() string { return {{printf "%q" .Kind}} }
func ({{.Worker}}) ModelName() string { return {{printf "%q" .Ident}} }
func ({{.Worker}}) ConfigDir() string { return {{printf "%q" .ConfigDir}} }
// NewRecord returns the model the generic admin handlers query and fill.
// TODO: return a pointer to the plugin's model, such as &models.{{.Ident}}{}.
// Until then the list and every write answer 500, so nothing is exposed.
func ({{.Worker}}) NewRecord() any { return nil }
// RequiredPermissions is checked before any schema or record is served. Keep
// it: a controller without one is open to every administrator. Declare the
// code in the plugin's Permissions() (pact.HasPermissions), or the admin API
// refuses to start with an unknown-permission error that names this controller.
func ({{.Worker}}) RequiredPermissions() []string {
return []string{ {{printf "%q" .Permission}} }
}
// {{.Func}} returns the {{.Kind}} admin controller.
func {{.Func}}() pact.AdminController { return {{.Worker}}{} }
{{end}}