- pact.HasAdminActionExtensions / AdminActionExtension: plugins add record actions to any admin controller by ID, merged at boot before permission validation (unknown target, no preview, duplicate name stop the boot) - internal summercms.cabana pseudo-plugin, appended only when some plugin registers admin controllers: Administrators list and preview, settings link under System, backend.manage_users and backend.manage_roles with no role grants - backend::lang user, user.role and permissions copy (en, pl) - smoke tests: compile-time seam and settings, Postgres list/preview/action
62 lines
2.2 KiB
Go
62 lines
2.2 KiB
Go
package cabana_test
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
|
|
"git.golem15.com/golem15/summercms/modules/cabana"
|
|
"git.golem15.com/golem15/summercms/modules/pact"
|
|
)
|
|
|
|
// ProfileLink is a row of the acme.profiles plugin that links a frontend
|
|
// profile to a backend administrator.
|
|
type ProfileLink struct {
|
|
ID uint `gorm:"column:id;primaryKey"`
|
|
BackendUserID uint `gorm:"column:backend_user_id"`
|
|
}
|
|
|
|
func (ProfileLink) TableName() string { return "acme_profiles_links" }
|
|
|
|
// ProfilesPlugin adds a record action to the admin's Administrators screen,
|
|
// a controller it does not own.
|
|
type ProfilesPlugin struct{}
|
|
|
|
var _ pact.HasAdminActionExtensions = ProfilesPlugin{}
|
|
|
|
// AdminActionExtensions adds an action to the Administrators screen.
|
|
func (ProfilesPlugin) AdminActionExtensions() []pact.AdminActionExtension {
|
|
return []pact.AdminActionExtension{{
|
|
Controller: cabana.AdministratorsControllerID,
|
|
RecordActions: []pact.AdminRecordAction{{
|
|
Name: "acme_unlink_profile",
|
|
Label: "acme.profiles::lang.unlink",
|
|
Confirm: "acme.profiles::lang.unlink_confirm",
|
|
Permissions: []string{"acme.profiles.manage_links"},
|
|
Run: func(ctx context.Context, in pact.AdminRecordActionInput) (pact.AdminRecordActionResult, error) {
|
|
tx, ok := cabana.TxFromContext(ctx) // the action's row-locked transaction
|
|
if !ok {
|
|
return pact.AdminRecordActionResult{}, errors.New("acme.profiles: no transaction")
|
|
}
|
|
err := tx.Where("backend_user_id = ?", in.RecordID).Delete(&ProfileLink{}).Error
|
|
return pact.AdminRecordActionResult{Message: "acme.profiles::lang.unlinked"}, err
|
|
},
|
|
}},
|
|
}}
|
|
}
|
|
|
|
func TestExampleActionExtension(t *testing.T) {
|
|
extensions := ProfilesPlugin{}.AdminActionExtensions()
|
|
if len(extensions) != 1 || extensions[0].Controller != "summercms.cabana.users" || len(extensions[0].RecordActions) != 1 {
|
|
t.Fatalf("extensions = %+v", extensions)
|
|
}
|
|
action := extensions[0].RecordActions[0]
|
|
if action.Name != "acme_unlink_profile" || action.Run == nil {
|
|
t.Fatalf("action = %+v", action)
|
|
}
|
|
// Outside the record action route there is no transaction.
|
|
if _, err := action.Run(context.Background(), pact.AdminRecordActionInput{RecordID: 1}); err == nil {
|
|
t.Fatal("Run without a transaction succeeded")
|
|
}
|
|
}
|