- Settings -> System -> Roles (summercms.cabana.roles, backend.manage_roles, order 110): name, code slugged from the name, description, checkbox permission editor with the editor's ceiling - system roles (is_system or code-declared grants) keep their code and cannot be deleted; a role any admin holds (deleted ones included) cannot be deleted, the refusal names the role and the count - role codes unique among roles
140 lines
5.0 KiB
Go
140 lines
5.0 KiB
Go
package cabana
|
|
|
|
import (
|
|
"embed"
|
|
"io/fs"
|
|
|
|
"git.golem15.com/golem15/summercms/modules/backpack"
|
|
"git.golem15.com/golem15/summercms/modules/pact"
|
|
"git.golem15.com/golem15/summercms/modules/party"
|
|
)
|
|
|
|
// The admin's own screens for backend administrators and roles (Settings →
|
|
// System), registered by cabana itself through an internal pseudo-plugin.
|
|
const (
|
|
// PermissionManageUsers opens the Administrators screen. No role is
|
|
// granted it in code: until an administrator grants it, only superusers
|
|
// reach the screen.
|
|
PermissionManageUsers = "backend.manage_users"
|
|
// PermissionManageRoles opens the Roles screen. No role is granted it in
|
|
// code either.
|
|
PermissionManageRoles = "backend.manage_roles"
|
|
// AdministratorsControllerID is the admin controller ID of the
|
|
// Administrators screen, the target other plugins name to add record
|
|
// actions to it (pact.HasAdminActionExtensions).
|
|
AdministratorsControllerID = "summercms.cabana.users"
|
|
// RolesControllerID is the admin controller ID of the Roles screen.
|
|
RolesControllerID = "summercms.cabana.roles"
|
|
)
|
|
|
|
// backendScreensPluginID is the pseudo-plugin's ID. It is also the
|
|
// migration history ID of the backend tables (lagoon), which is untouched:
|
|
// the pseudo-plugin declares no migrations.
|
|
const backendScreensPluginID = "summercms.cabana"
|
|
|
|
// backendScreensFS holds the screens' admin YAML and partials. all: keeps
|
|
// the partials, whose names start with an underscore.
|
|
//
|
|
//go:embed all:backendscreens
|
|
var backendScreensFS embed.FS
|
|
|
|
// backendScreens is the internal pseudo-plugin that registers the
|
|
// Administrators and Roles screens, their two permissions and their settings
|
|
// entries. Activate appends it to the plugins only when some plugin
|
|
// registers admin controllers, so an application without an admin still
|
|
// boots without one. app is the activating application and reg the compiled
|
|
// registry, set once compilation is done; the controllers read both per
|
|
// request.
|
|
type backendScreens struct {
|
|
app *backpack.App
|
|
reg *Registry
|
|
}
|
|
|
|
var (
|
|
_ party.Plugin = (*backendScreens)(nil)
|
|
_ pact.AdminAssets = (*backendScreens)(nil)
|
|
_ pact.HasAdminControllers = (*backendScreens)(nil)
|
|
_ pact.HasPermissions = (*backendScreens)(nil)
|
|
_ pact.HasSettings = (*backendScreens)(nil)
|
|
)
|
|
|
|
func (*backendScreens) ID() string { return backendScreensPluginID }
|
|
func (*backendScreens) Requires() []string { return nil }
|
|
func (*backendScreens) Register(*backpack.App) error { return nil }
|
|
func (*backendScreens) Boot(*backpack.App) error { return nil }
|
|
|
|
// AdminFS serves the embedded tree rooted at backendscreens/, so its paths
|
|
// start at controllers/ and models/.
|
|
func (*backendScreens) AdminFS() fs.FS {
|
|
sub, err := fs.Sub(backendScreensFS, "backendscreens")
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
return sub
|
|
}
|
|
|
|
func (s *backendScreens) AdminControllers() []pact.AdminController {
|
|
return []pact.AdminController{usersAdmin{screens: s}, rolesAdmin{screens: s}}
|
|
}
|
|
|
|
// Permissions declares the two screen permissions with no role grants
|
|
// (D-04): an upgrade gives no existing role access to the screens.
|
|
func (*backendScreens) Permissions() []pact.Permission {
|
|
return []pact.Permission{
|
|
{Code: PermissionManageUsers, Tab: "backend::lang.permissions.tab_system", Label: "backend::lang.permissions.manage_users"},
|
|
{Code: PermissionManageRoles, Tab: "backend::lang.permissions.tab_system", Label: "backend::lang.permissions.manage_roles"},
|
|
}
|
|
}
|
|
|
|
// Settings links the screens from Settings → System; there is no navigation
|
|
// entry.
|
|
func (*backendScreens) Settings() []pact.SettingsItem {
|
|
return []pact.SettingsItem{
|
|
{
|
|
Code: "administrators",
|
|
Label: "backend::lang.user.menu_label",
|
|
Description: "backend::lang.user.menu_description",
|
|
Category: "backend::lang.settings.category_system",
|
|
Icon: "users",
|
|
Order: 100,
|
|
Permissions: []string{PermissionManageUsers},
|
|
Controller: AdministratorsControllerID,
|
|
},
|
|
{
|
|
Code: "roles",
|
|
Label: "backend::lang.user.role.menu_label",
|
|
Description: "backend::lang.user.role.menu_description",
|
|
Category: "backend::lang.settings.category_system",
|
|
Icon: "shield-check",
|
|
Order: 110,
|
|
Permissions: []string{PermissionManageRoles},
|
|
Controller: RolesControllerID,
|
|
},
|
|
}
|
|
}
|
|
|
|
// application is the activating app, or nil.
|
|
func (s *backendScreens) application() *backpack.App {
|
|
if s == nil {
|
|
return nil
|
|
}
|
|
return s.app
|
|
}
|
|
|
|
// registry is the compiled registry, or nil before compilation finished.
|
|
func (s *backendScreens) registry() *Registry {
|
|
if s == nil {
|
|
return nil
|
|
}
|
|
return s.reg
|
|
}
|
|
|
|
// withBackendScreens returns a new plugin slice with the pseudo-plugin
|
|
// appended, and the pseudo-plugin. plugins itself is never modified.
|
|
func withBackendScreens(app *backpack.App, plugins []party.Plugin) ([]party.Plugin, *backendScreens) {
|
|
screens := &backendScreens{app: app}
|
|
out := make([]party.Plugin, 0, len(plugins)+1)
|
|
out = append(out, plugins...)
|
|
return append(out, screens), screens
|
|
}
|