feat: User Groups admin screen with the users count and privileged codes protected
- controller golem15.user.usergroups behind golem15.users.access_groups - list with users_count from the list's own query; form with the checkbox permission editor stored in user_groups.permissions - creating a group with a privileged code, changing a code to or from one and deleting a privileged group need golem15.users.manage_privileged_groups - a group delete removes its users_groups rows in the same transaction - UserGroup gains Fillable, Rules and the read-only UsersCount; PermissionSet.Text - TestAdminGroups and the D-06 matrix in TestAdminPrivilegedGroups
This commit is contained in:
@@ -92,6 +92,18 @@ func permissionInt(value any) (int, bool) {
|
||||
return n, true
|
||||
}
|
||||
|
||||
// Text returns the set as the text of a permission column that is a plain
|
||||
// nullable string on its model (user_groups.permissions): the JSON object
|
||||
// Value writes, or nil for a set without a non-zero value.
|
||||
func (p PermissionSet) Text() *string {
|
||||
value, err := p.Value()
|
||||
text, ok := value.(string)
|
||||
if err != nil || !ok {
|
||||
return nil
|
||||
}
|
||||
return &text
|
||||
}
|
||||
|
||||
// Value implements driver.Valuer: NULL for a set without a non-zero value,
|
||||
// else a JSON object of integers with the zero values left out.
|
||||
func (p PermissionSet) Value() (driver.Value, error) {
|
||||
|
||||
@@ -4,7 +4,8 @@ import "time"
|
||||
|
||||
// UserGroup is a row of user_groups, the PHP UserGroup model. Membership
|
||||
// lives in the users_groups pivot (User.Groups). Permissions is the raw
|
||||
// jsonable text column.
|
||||
// jsonable text column; ParsePermissionSet reads it and PermissionSet.Text
|
||||
// writes it.
|
||||
type UserGroup struct {
|
||||
ID uint `gorm:"column:id;primaryKey"`
|
||||
Name string `gorm:"column:name"`
|
||||
@@ -13,6 +14,11 @@ type UserGroup struct {
|
||||
Permissions *string `gorm:"column:permissions"`
|
||||
CreatedAt *time.Time `gorm:"column:created_at"`
|
||||
UpdatedAt *time.Time `gorm:"column:updated_at"`
|
||||
// UsersCount is the number of members, the PHP users_count relation. It
|
||||
// is not a column of user_groups: only a query that selects an expression
|
||||
// named users_count fills it (the admin list does), it is never written,
|
||||
// and it is zero everywhere else.
|
||||
UsersCount int64 `gorm:"column:users_count;->" json:"-"`
|
||||
}
|
||||
|
||||
func (UserGroup) TableName() string { return "user_groups" }
|
||||
@@ -24,6 +30,21 @@ const (
|
||||
GroupRegistered = "registered"
|
||||
)
|
||||
|
||||
// Fillable is the field list an admin save may set. Permissions is written
|
||||
// through the permission editor, not by a fill.
|
||||
func (UserGroup) Fillable() []string {
|
||||
return []string{"name", "code", "description"}
|
||||
}
|
||||
|
||||
// Rules is the PHP UserGroup rule set without its regex on code, which the
|
||||
// rule engine does not know: the admin controller checks the code's format.
|
||||
func (UserGroup) Rules() map[string]string {
|
||||
return map[string]string{
|
||||
"name": "required|between:3,64",
|
||||
"code": "required|unique:user_groups",
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
Register(UserGroup{})
|
||||
}
|
||||
|
||||
15
models/usergroup/columns.yaml
Normal file
15
models/usergroup/columns.yaml
Normal file
@@ -0,0 +1,15 @@
|
||||
columns:
|
||||
id:
|
||||
label: golem15.user::lang.group.id
|
||||
invisible: true
|
||||
name:
|
||||
label: golem15.user::lang.group.name
|
||||
searchable: true
|
||||
code:
|
||||
label: golem15.user::lang.group.code
|
||||
created_at:
|
||||
label: golem15.user::lang.group.created_at
|
||||
type: datetime
|
||||
users_count:
|
||||
label: golem15.user::lang.group.users_count
|
||||
sortable: false
|
||||
21
models/usergroup/fields.yaml
Normal file
21
models/usergroup/fields.yaml
Normal file
@@ -0,0 +1,21 @@
|
||||
fields:
|
||||
name:
|
||||
label: golem15.user::lang.group.name
|
||||
type: text
|
||||
span: left
|
||||
required: true
|
||||
code:
|
||||
label: golem15.user::lang.group.code
|
||||
comment: golem15.user::lang.group.code_comment
|
||||
type: text
|
||||
span: right
|
||||
preset: name
|
||||
description:
|
||||
label: golem15.user::lang.group.description_field
|
||||
type: textarea
|
||||
size: tiny
|
||||
permissions:
|
||||
type: permissioneditor
|
||||
mode: checkbox
|
||||
span: full
|
||||
tab: golem15.user::lang.user.permissions_tab
|
||||
Reference in New Issue
Block a user