Add access control and support for personal layouts

This commit is contained in:
Tomaž Jerman
2023-04-07 12:39:26 +02:00
committed by Jože Fortun
parent 3a329511a4
commit b9e102313d
18 changed files with 549 additions and 70 deletions
-1
View File
@@ -10,7 +10,6 @@ package automation
import (
"context"
atypes "github.com/cortezaproject/corteza/server/automation/types"
"github.com/cortezaproject/corteza/server/pkg/expr"
"github.com/cortezaproject/corteza/server/pkg/wfexec"
+8
View File
@@ -632,6 +632,14 @@ var Page = &dal.Model{
Store: &dal.CodecAlias{Ident: "rel_namespace"},
},
&dal.Attribute{
Ident: "Meta",
Type: &dal.TypeJSON{
DefaultValue: "{}",
},
Store: &dal.CodecAlias{Ident: "meta"},
},
&dal.Attribute{
Ident: "Config",
Type: &dal.TypeJSON{
+7
View File
@@ -58,6 +58,10 @@ page: {
}
}
meta: {
goType: "types.PageMeta"
dal: { type: "JSON", defaultEmptyObject: true }
}
config: {
goType: "types.PageConfig"
dal: { type: "JSON", defaultEmptyObject: true }
@@ -160,6 +164,9 @@ page: {
"read": {}
"update": {}
"delete": {}
"page-layout.create": description: "Create page layout on namespace"
"page-layouts.search": description: "List, search or filter page layouts on namespace"
}
}
+8
View File
@@ -97,6 +97,14 @@ pageLayout: {
}
}
rbac: {
operations: {
"read": {}
"update": {}
"delete": {}
}
}
locale: {
extended: true
+10
View File
@@ -345,6 +345,11 @@ endpoints:
name: config
required: false
title: Config JSON
- type: "*types.PageMeta"
name: meta
required: false
title: Meta
parser: types.ParsePageMeta
- name: read
path: "/{pageID}"
method: GET
@@ -411,6 +416,11 @@ endpoints:
name: config
required: false
title: Config JSON
- type: "*types.PageMeta"
name: meta
required: false
title: Meta
parser: types.ParsePageMeta
- name: reorder
method: POST
title: Reorder pages
+2
View File
@@ -118,6 +118,7 @@ func (ctrl *Page) Create(ctx context.Context, r *request.PageCreate) (interface{
Visible: r.Visible,
Weight: r.Weight,
Labels: r.Labels,
Meta: r.Meta,
}
)
@@ -168,6 +169,7 @@ func (ctrl *Page) Update(ctx context.Context, r *request.PageUpdate) (interface{
Visible: r.Visible,
Weight: r.Weight,
Labels: r.Labels,
Meta: r.Meta,
}
)
+70
View File
@@ -140,6 +140,11 @@ type (
//
// Config JSON
Config sqlxTypes.JSONText
// Meta POST parameter
//
// Meta
Meta *types.PageMeta
}
PageRead struct {
@@ -221,6 +226,11 @@ type (
//
// Config JSON
Config sqlxTypes.JSONText
// Meta POST parameter
//
// Meta
Meta *types.PageMeta
}
PageReorder struct {
@@ -514,6 +524,7 @@ func (r PageCreate) Auditable() map[string]interface{} {
"visible": r.Visible,
"blocks": r.Blocks,
"config": r.Config,
"meta": r.Meta,
}
}
@@ -572,6 +583,11 @@ func (r PageCreate) GetConfig() sqlxTypes.JSONText {
return r.Config
}
// Auditable returns all auditable/loggable parameters
func (r PageCreate) GetMeta() *types.PageMeta {
return r.Meta
}
// Fill processes request and fills internal variables
func (r *PageCreate) Fill(req *http.Request) (err error) {
@@ -667,6 +683,18 @@ func (r *PageCreate) Fill(req *http.Request) (err error) {
return err
}
}
if val, ok := req.MultipartForm.Value["meta[]"]; ok {
r.Meta, err = types.ParsePageMeta(val)
if err != nil {
return err
}
} else if val, ok := req.MultipartForm.Value["meta"]; ok {
r.Meta, err = types.ParsePageMeta(val)
if err != nil {
return err
}
}
}
}
@@ -751,6 +779,18 @@ func (r *PageCreate) Fill(req *http.Request) (err error) {
return err
}
}
if val, ok := req.Form["meta[]"]; ok {
r.Meta, err = types.ParsePageMeta(val)
if err != nil {
return err
}
} else if val, ok := req.Form["meta"]; ok {
r.Meta, err = types.ParsePageMeta(val)
if err != nil {
return err
}
}
}
{
@@ -870,6 +910,7 @@ func (r PageUpdate) Auditable() map[string]interface{} {
"visible": r.Visible,
"blocks": r.Blocks,
"config": r.Config,
"meta": r.Meta,
}
}
@@ -933,6 +974,11 @@ func (r PageUpdate) GetConfig() sqlxTypes.JSONText {
return r.Config
}
// Auditable returns all auditable/loggable parameters
func (r PageUpdate) GetMeta() *types.PageMeta {
return r.Meta
}
// Fill processes request and fills internal variables
func (r *PageUpdate) Fill(req *http.Request) (err error) {
@@ -1028,6 +1074,18 @@ func (r *PageUpdate) Fill(req *http.Request) (err error) {
return err
}
}
if val, ok := req.MultipartForm.Value["meta[]"]; ok {
r.Meta, err = types.ParsePageMeta(val)
if err != nil {
return err
}
} else if val, ok := req.MultipartForm.Value["meta"]; ok {
r.Meta, err = types.ParsePageMeta(val)
if err != nil {
return err
}
}
}
}
@@ -1112,6 +1170,18 @@ func (r *PageUpdate) Fill(req *http.Request) (err error) {
return err
}
}
if val, ok := req.Form["meta[]"]; ok {
r.Meta, err = types.ParsePageMeta(val)
if err != nil {
return err
}
} else if val, ok := req.Form["meta"]; ok {
r.Meta, err = types.ParsePageMeta(val)
if err != nil {
return err
}
}
}
{
+68 -2
View File
@@ -272,6 +272,31 @@ func (svc accessControl) List() (out []map[string]string) {
"any": types.PageRbacResource(0, 0),
"op": "delete",
},
{
"type": types.PageResourceType,
"any": types.PageRbacResource(0, 0),
"op": "page-layout.create",
},
{
"type": types.PageResourceType,
"any": types.PageRbacResource(0, 0),
"op": "page-layouts.search",
},
{
"type": types.PageLayoutResourceType,
"any": types.PageLayoutRbacResource(0, 0, 0),
"op": "read",
},
{
"type": types.PageLayoutResourceType,
"any": types.PageLayoutRbacResource(0, 0, 0),
"op": "update",
},
{
"type": types.PageLayoutResourceType,
"any": types.PageLayoutRbacResource(0, 0, 0),
"op": "delete",
},
{
"type": types.RecordResourceType,
"any": types.RecordRbacResource(0, 0, 0),
@@ -592,6 +617,41 @@ func (svc accessControl) CanDeletePage(ctx context.Context, r *types.Page) bool
return svc.can(ctx, "delete", r)
}
// CanCreatePageLayoutOnPage checks if current user can create page layout on namespace
//
// This function is auto-generated
func (svc accessControl) CanCreatePageLayoutOnPage(ctx context.Context, r *types.Page) bool {
return svc.can(ctx, "page-layout.create", r)
}
// CanSearchPageLayoutsOnPage checks if current user can list, search or filter page layouts on namespace
//
// This function is auto-generated
func (svc accessControl) CanSearchPageLayoutsOnPage(ctx context.Context, r *types.Page) bool {
return svc.can(ctx, "page-layouts.search", r)
}
// CanReadPageLayout checks if current user can read
//
// This function is auto-generated
func (svc accessControl) CanReadPageLayout(ctx context.Context, r *types.PageLayout) bool {
return svc.can(ctx, "read", r)
}
// CanUpdatePageLayout checks if current user can update
//
// This function is auto-generated
func (svc accessControl) CanUpdatePageLayout(ctx context.Context, r *types.PageLayout) bool {
return svc.can(ctx, "update", r)
}
// CanDeletePageLayout checks if current user can delete
//
// This function is auto-generated
func (svc accessControl) CanDeletePageLayout(ctx context.Context, r *types.PageLayout) bool {
return svc.can(ctx, "delete", r)
}
// CanReadRecord checks if current user can read
//
// This function is auto-generated
@@ -817,13 +877,19 @@ func rbacResourceOperations(r string) map[string]bool {
"pages.search": true,
}
case types.PageResourceType:
return map[string]bool{
"read": true,
"update": true,
"delete": true,
"page-layout.create": true,
"page-layouts.search": true,
}
case types.PageLayoutResourceType:
return map[string]bool{
"read": true,
"update": true,
"delete": true,
}
case types.PageLayoutResourceType:
return map[string]bool{}
case types.RecordResourceType:
return map[string]bool{
"read": true,
+10
View File
@@ -622,6 +622,16 @@ func (svc page) handleUpdate(ctx context.Context, upd *types.Page) pageUpdateHan
}
}
if upd.Meta != nil {
if res.Meta.AllowPersonalLayouts != upd.Meta.AllowPersonalLayouts {
if res.Meta == nil {
res.Meta = &types.PageMeta{}
res.Meta.AllowPersonalLayouts = upd.Meta.AllowPersonalLayouts
changes |= pageChanged
}
}
}
if res.Title != upd.Title {
res.Title = upd.Title
changes |= pageChanged
+63 -42
View File
@@ -37,12 +37,16 @@ type (
}
pageLayoutAccessController interface {
CanManageResourceTranslations(ctx context.Context) bool
CanManageResourceTranslations(context.Context) bool
// @todo...
CanCreatePageLayoutOnPage(context.Context, *types.Page) bool
CanSearchPageLayoutsOnPage(context.Context, *types.Page) bool
CanReadPageLayout(context.Context, *types.PageLayout) bool
CanUpdatePageLayout(context.Context, *types.PageLayout) bool
CanDeletePageLayout(context.Context, *types.PageLayout) bool
}
pageLayoutUpdateHandler func(ctx context.Context, ns *types.Namespace, c *types.PageLayout) (pageLayoutChanges, error)
pageLayoutUpdateHandler func(ctx context.Context, ns *types.Namespace, pg *types.Page, c *types.PageLayout) (pageLayoutChanges, error)
pageLayoutChanges uint8
)
@@ -98,9 +102,9 @@ func (svc pageLayout) FindByPageLayoutID(ctx context.Context, namespaceID, pageL
func checkPageLayout(ctx context.Context, ac pageLayoutAccessController) func(res *types.PageLayout) (bool, error) {
return func(res *types.PageLayout) (bool, error) {
// if !ac.CanReadPageLayout(ctx, res) {
// return false, nil
// }
if !ac.CanReadPageLayout(ctx, res) {
return false, nil
}
return true, nil
}
@@ -111,21 +115,22 @@ func (svc pageLayout) search(ctx context.Context, filter types.PageLayoutFilter)
var (
aProps = &pageLayoutActionProps{filter: &filter}
ns *types.Namespace
pg *types.Page
)
// For each fetched item, store backend will check if it is valid or not
filter.Check = checkPageLayout(ctx, svc.ac)
err = func() error {
ns, err = loadNamespace(ctx, svc.store, filter.NamespaceID)
ns, pg, err = loadPageCombo(ctx, svc.store, ns.ID, filter.PageID)
if err != nil {
return err
}
aProps.setNamespace(ns)
// if !svc.ac.CanSearchPageLayoutsOnNamespace(ctx, ns) {
// return PageLayoutErrNotAllowedToSearch()
// }
if !svc.ac.CanSearchPageLayoutsOnPage(ctx, pg) {
return PageLayoutErrNotAllowedToSearch()
}
if len(filter.Labels) > 0 {
filter.LabeledIDs, err = label.Search(
@@ -172,8 +177,9 @@ func (svc pageLayout) Find(ctx context.Context, filter types.PageLayoutFilter) (
func (svc pageLayout) Create(ctx context.Context, new *types.PageLayout) (*types.PageLayout, error) {
var (
ns *types.Namespace
aProps = &pageLayoutActionProps{pageLayout: new}
ns *types.Namespace
pg *types.Page
)
new.ID = 0
@@ -183,13 +189,16 @@ func (svc pageLayout) Create(ctx context.Context, new *types.PageLayout) (*types
return PageLayoutErrInvalidID()
}
if ns, err = loadNamespace(ctx, s, new.NamespaceID); err != nil {
if ns, pg, err = loadPageCombo(ctx, s, new.NamespaceID, new.PageID); err != nil {
return err
}
// if !svc.ac.CanCreatePageLayoutOnNamespace(ctx, ns) {
// return PageLayoutErrNotAllowedToCreate()
// }
// Allow users to manage their personal layouts regardless of RBAC (when enabled)
if !svc.ac.CanCreatePageLayoutOnPage(ctx, pg) {
if new.OwnedBy == 0 || !pg.Meta.AllowPersonalLayouts {
return PageLayoutErrNotAllowedToCreate()
}
}
aProps.setNamespace(ns)
@@ -247,9 +256,11 @@ func (svc pageLayout) Reorder(ctx context.Context, namespaceID, pageID uint64, p
}
_ = p
// if !svc.ac.CanUpdatePageLayout(ctx, p) {
// return PageLayoutErrNotAllowedToUpdate()
// }
// @note following the pattern of pages; should probably change this
// on both resources since it doesn't sound right.
if !svc.ac.CanCreatePageLayoutOnPage(ctx, p) {
return PageLayoutErrNotAllowedToUpdate()
}
return store.ReorderComposePageLayouts(ctx, s, namespaceID, pageID, pageLayoutIDs)
})
@@ -260,12 +271,12 @@ func (svc pageLayout) Reorder(ctx context.Context, namespaceID, pageID uint64, p
func (svc pageLayout) Update(ctx context.Context, upd *types.PageLayout) (c *types.PageLayout, err error) {
err = store.Tx(ctx, svc.store, func(ctx context.Context, s store.Storer) (err error) {
ns, res, err := loadPageLayoutCombo(ctx, s, upd.NamespaceID, upd.PageID, upd.ID)
ns, pg, res, err := loadPageLayoutCombo(ctx, s, upd.NamespaceID, upd.PageID, upd.ID)
if err != nil {
return
}
c, err = svc.updater(ctx, svc.store, ns, res, PageLayoutActionUpdate, svc.handleUpdate(ctx, upd))
c, err = svc.updater(ctx, svc.store, ns, pg, res, PageLayoutActionUpdate, svc.handleUpdate(ctx, upd))
return
})
@@ -275,34 +286,35 @@ func (svc pageLayout) Update(ctx context.Context, upd *types.PageLayout) (c *typ
func (svc pageLayout) DeleteByID(ctx context.Context, namespaceID, pageID, pageLayoutID uint64) error {
var (
ns *types.Namespace
pg *types.Page
res *types.PageLayout
)
return store.Tx(ctx, svc.store, func(ctx context.Context, s store.Storer) (err error) {
// simply delete the pageLayout and ignore the subpageLayouts
ns, res, err = loadPageLayoutCombo(ctx, s, namespaceID, pageID, pageLayoutID)
ns, pg, res, err = loadPageLayoutCombo(ctx, s, namespaceID, pageID, pageLayoutID)
if err != nil {
return
}
_, err = svc.updater(ctx, svc.store, ns, res, PageLayoutActionDelete, svc.handleDelete)
_, err = svc.updater(ctx, svc.store, ns, pg, res, PageLayoutActionDelete, svc.handleDelete)
return
})
}
func (svc pageLayout) UndeleteByID(ctx context.Context, namespaceID, pageID, pageLayoutID uint64) error {
return store.Tx(ctx, svc.store, func(ctx context.Context, s store.Storer) (err error) {
ns, res, err := loadPageLayoutCombo(ctx, s, namespaceID, pageID, pageLayoutID)
ns, pg, res, err := loadPageLayoutCombo(ctx, s, namespaceID, pageID, pageLayoutID)
if err != nil {
return
}
_, err = svc.updater(ctx, svc.store, ns, res, PageLayoutActionUpdate, svc.handleUndelete)
_, err = svc.updater(ctx, svc.store, ns, pg, res, PageLayoutActionUpdate, svc.handleUndelete)
return
})
}
func (svc pageLayout) updater(ctx context.Context, s store.Storer, ns *types.Namespace, res *types.PageLayout, action func(...*pageLayoutActionProps) *pageLayoutAction, fn pageLayoutUpdateHandler) (*types.PageLayout, error) {
func (svc pageLayout) updater(ctx context.Context, s store.Storer, ns *types.Namespace, pg *types.Page, res *types.PageLayout, action func(...*pageLayoutActionProps) *pageLayoutAction, fn pageLayoutUpdateHandler) (*types.PageLayout, error) {
var (
changes pageLayoutChanges
old *types.PageLayout
@@ -338,7 +350,7 @@ func (svc pageLayout) updater(ctx context.Context, s store.Storer, ns *types.Nam
return
}
if changes, err = fn(ctx, ns, res); err != nil {
if changes, err = fn(ctx, ns, pg, res); err != nil {
return err
}
@@ -391,9 +403,9 @@ func (svc pageLayout) lookup(ctx context.Context, namespaceID uint64, lookup fun
aProps.setPageLayout(p)
// if !svc.ac.CanReadPageLayout(ctx, p) {
// return PageLayoutErrNotAllowedToRead()
// }
if !svc.ac.CanReadPageLayout(ctx, p) {
return PageLayoutErrNotAllowedToRead()
}
if err = label.Load(ctx, svc.store, p); err != nil {
return err
@@ -416,7 +428,7 @@ func (svc pageLayout) uniqueCheck(ctx context.Context, p *types.PageLayout) (err
}
func (svc pageLayout) handleUpdate(ctx context.Context, upd *types.PageLayout) pageLayoutUpdateHandler {
return func(ctx context.Context, ns *types.Namespace, res *types.PageLayout) (changes pageLayoutChanges, err error) {
return func(ctx context.Context, ns *types.Namespace, pg *types.Page, res *types.PageLayout) (changes pageLayoutChanges, err error) {
if isStale(upd.UpdatedAt, res.UpdatedAt, res.CreatedAt) {
return pageLayoutUnchanged, PageLayoutErrStaleData()
}
@@ -429,9 +441,12 @@ func (svc pageLayout) handleUpdate(ctx context.Context, upd *types.PageLayout) p
return pageLayoutUnchanged, err
}
// if !svc.ac.CanUpdatePageLayout(ctx, res) {
// return pageLayoutUnchanged, PageLayoutErrNotAllowedToUpdate()
// }
// Allow users to manage their personal layouts regardless of RBAC (when enabled)
if !svc.ac.CanUpdatePageLayout(ctx, res) {
if res.OwnedBy == 0 || !pg.Meta.AllowPersonalLayouts {
return pageLayoutUnchanged, PageLayoutErrNotAllowedToUpdate()
}
}
// Get max blockID for later use
blockID := uint64(0)
@@ -517,10 +532,13 @@ func (svc pageLayout) handleUpdate(ctx context.Context, upd *types.PageLayout) p
}
}
func (svc pageLayout) handleDelete(ctx context.Context, ns *types.Namespace, m *types.PageLayout) (pageLayoutChanges, error) {
// if !svc.ac.CanDeletePageLayout(ctx, m) {
// return pageLayoutUnchanged, PageLayoutErrNotAllowedToDelete()
// }
func (svc pageLayout) handleDelete(ctx context.Context, ns *types.Namespace, pg *types.Page, m *types.PageLayout) (pageLayoutChanges, error) {
// Allow users to manage their personal layouts regardless of RBAC (when enabled)
if !svc.ac.CanDeletePageLayout(ctx, m) {
if m.OwnedBy == 0 || !pg.Meta.AllowPersonalLayouts {
return pageLayoutUnchanged, PageLayoutErrNotAllowedToDelete()
}
}
if m.DeletedAt != nil {
// pageLayout already deleted
@@ -531,10 +549,13 @@ func (svc pageLayout) handleDelete(ctx context.Context, ns *types.Namespace, m *
return pageLayoutChanged, nil
}
func (svc pageLayout) handleUndelete(ctx context.Context, ns *types.Namespace, m *types.PageLayout) (pageLayoutChanges, error) {
// if !svc.ac.CanDeletePageLayout(ctx, m) {
// return pageLayoutUnchanged, PageLayoutErrNotAllowedToUndelete()
// }
func (svc pageLayout) handleUndelete(ctx context.Context, ns *types.Namespace, pg *types.Page, m *types.PageLayout) (pageLayoutChanges, error) {
// Allow users to manage their personal layouts regardless of RBAC (when enabled)
if !svc.ac.CanDeletePageLayout(ctx, m) {
if m.OwnedBy == 0 || !pg.Meta.AllowPersonalLayouts {
return pageLayoutUnchanged, PageLayoutErrNotAllowedToUndelete()
}
}
if m.DeletedAt == nil {
// pageLayout not deleted
@@ -561,7 +582,7 @@ func (svc *pageLayout) UpdateConfig(ss *systemTypes.AppSettings) {
func loadPageLayoutCombo(ctx context.Context, s interface {
store.ComposePageLayouts
store.ComposeNamespaces
}, namespaceID, pageID, pageLayoutID uint64) (ns *types.Namespace, c *types.PageLayout, err error) {
}, namespaceID, pageID, pageLayoutID uint64) (ns *types.Namespace, pg *types.Page, c *types.PageLayout, err error) {
ns, err = loadNamespace(ctx, s, namespaceID)
if err != nil {
return
+252
View File
@@ -707,6 +707,258 @@ func PageLayoutErrInvalidNamespaceID(mm ...*pageLayoutActionProps) *errors.Error
return e
}
// PageLayoutErrNotAllowedToRead returns "compose:page-layout.notAllowedToRead" as *errors.Error
//
//
// This function is auto-generated.
//
func PageLayoutErrNotAllowedToRead(mm ...*pageLayoutActionProps) *errors.Error {
var p = &pageLayoutActionProps{}
if len(mm) > 0 {
p = mm[0]
}
var e = errors.New(
errors.KindInternal,
p.Format("not allowed to read this pageLayout", nil),
errors.Meta("type", "notAllowedToRead"),
errors.Meta("resource", "compose:page-layout"),
// action log entry; no formatting, it will be applied inside recordAction fn.
errors.Meta(pageLayoutLogMetaKey{}, "could not read {{pageLayout}}; insufficient permissions"),
errors.Meta(pageLayoutPropsMetaKey{}, p),
// translation namespace & key
errors.Meta(locale.ErrorMetaNamespace{}, "compose"),
errors.Meta(locale.ErrorMetaKey{}, "page-layout.errors.notAllowedToRead"),
errors.StackSkip(1),
)
if len(mm) > 0 {
}
return e
}
// PageLayoutErrNotAllowedToSearch returns "compose:page-layout.notAllowedToSearch" as *errors.Error
//
//
// This function is auto-generated.
//
func PageLayoutErrNotAllowedToSearch(mm ...*pageLayoutActionProps) *errors.Error {
var p = &pageLayoutActionProps{}
if len(mm) > 0 {
p = mm[0]
}
var e = errors.New(
errors.KindInternal,
p.Format("not allowed to search or list pageLayouts", nil),
errors.Meta("type", "notAllowedToSearch"),
errors.Meta("resource", "compose:page-layout"),
// action log entry; no formatting, it will be applied inside recordAction fn.
errors.Meta(pageLayoutLogMetaKey{}, "could not search pageLayouts; insufficient permissions"),
errors.Meta(pageLayoutPropsMetaKey{}, p),
// translation namespace & key
errors.Meta(locale.ErrorMetaNamespace{}, "compose"),
errors.Meta(locale.ErrorMetaKey{}, "page-layout.errors.notAllowedToSearch"),
errors.StackSkip(1),
)
if len(mm) > 0 {
}
return e
}
// PageLayoutErrNotAllowedToListPageLayouts returns "compose:page-layout.notAllowedToListPageLayouts" as *errors.Error
//
//
// This function is auto-generated.
//
func PageLayoutErrNotAllowedToListPageLayouts(mm ...*pageLayoutActionProps) *errors.Error {
var p = &pageLayoutActionProps{}
if len(mm) > 0 {
p = mm[0]
}
var e = errors.New(
errors.KindInternal,
p.Format("not allowed to list pageLayouts", nil),
errors.Meta("type", "notAllowedToListPageLayouts"),
errors.Meta("resource", "compose:page-layout"),
// action log entry; no formatting, it will be applied inside recordAction fn.
errors.Meta(pageLayoutLogMetaKey{}, "could not list pageLayouts; insufficient permissions"),
errors.Meta(pageLayoutPropsMetaKey{}, p),
// translation namespace & key
errors.Meta(locale.ErrorMetaNamespace{}, "compose"),
errors.Meta(locale.ErrorMetaKey{}, "page-layout.errors.notAllowedToListPageLayouts"),
errors.StackSkip(1),
)
if len(mm) > 0 {
}
return e
}
// PageLayoutErrNotAllowedToCreate returns "compose:page-layout.notAllowedToCreate" as *errors.Error
//
//
// This function is auto-generated.
//
func PageLayoutErrNotAllowedToCreate(mm ...*pageLayoutActionProps) *errors.Error {
var p = &pageLayoutActionProps{}
if len(mm) > 0 {
p = mm[0]
}
var e = errors.New(
errors.KindInternal,
p.Format("not allowed to create pageLayouts", nil),
errors.Meta("type", "notAllowedToCreate"),
errors.Meta("resource", "compose:page-layout"),
// action log entry; no formatting, it will be applied inside recordAction fn.
errors.Meta(pageLayoutLogMetaKey{}, "could not create pageLayouts; insufficient permissions"),
errors.Meta(pageLayoutPropsMetaKey{}, p),
// translation namespace & key
errors.Meta(locale.ErrorMetaNamespace{}, "compose"),
errors.Meta(locale.ErrorMetaKey{}, "page-layout.errors.notAllowedToCreate"),
errors.StackSkip(1),
)
if len(mm) > 0 {
}
return e
}
// PageLayoutErrNotAllowedToUpdate returns "compose:page-layout.notAllowedToUpdate" as *errors.Error
//
//
// This function is auto-generated.
//
func PageLayoutErrNotAllowedToUpdate(mm ...*pageLayoutActionProps) *errors.Error {
var p = &pageLayoutActionProps{}
if len(mm) > 0 {
p = mm[0]
}
var e = errors.New(
errors.KindInternal,
p.Format("not allowed to update this pageLayout", nil),
errors.Meta("type", "notAllowedToUpdate"),
errors.Meta("resource", "compose:page-layout"),
// action log entry; no formatting, it will be applied inside recordAction fn.
errors.Meta(pageLayoutLogMetaKey{}, "could not update {{pageLayout}}; insufficient permissions"),
errors.Meta(pageLayoutPropsMetaKey{}, p),
// translation namespace & key
errors.Meta(locale.ErrorMetaNamespace{}, "compose"),
errors.Meta(locale.ErrorMetaKey{}, "page-layout.errors.notAllowedToUpdate"),
errors.StackSkip(1),
)
if len(mm) > 0 {
}
return e
}
// PageLayoutErrNotAllowedToDelete returns "compose:page-layout.notAllowedToDelete" as *errors.Error
//
//
// This function is auto-generated.
//
func PageLayoutErrNotAllowedToDelete(mm ...*pageLayoutActionProps) *errors.Error {
var p = &pageLayoutActionProps{}
if len(mm) > 0 {
p = mm[0]
}
var e = errors.New(
errors.KindInternal,
p.Format("not allowed to delete this pageLayout", nil),
errors.Meta("type", "notAllowedToDelete"),
errors.Meta("resource", "compose:page-layout"),
// action log entry; no formatting, it will be applied inside recordAction fn.
errors.Meta(pageLayoutLogMetaKey{}, "could not delete {{pageLayout}}; insufficient permissions"),
errors.Meta(pageLayoutPropsMetaKey{}, p),
// translation namespace & key
errors.Meta(locale.ErrorMetaNamespace{}, "compose"),
errors.Meta(locale.ErrorMetaKey{}, "page-layout.errors.notAllowedToDelete"),
errors.StackSkip(1),
)
if len(mm) > 0 {
}
return e
}
// PageLayoutErrNotAllowedToUndelete returns "compose:page-layout.notAllowedToUndelete" as *errors.Error
//
//
// This function is auto-generated.
//
func PageLayoutErrNotAllowedToUndelete(mm ...*pageLayoutActionProps) *errors.Error {
var p = &pageLayoutActionProps{}
if len(mm) > 0 {
p = mm[0]
}
var e = errors.New(
errors.KindInternal,
p.Format("not allowed to undelete this pageLayout", nil),
errors.Meta("type", "notAllowedToUndelete"),
errors.Meta("resource", "compose:page-layout"),
// action log entry; no formatting, it will be applied inside recordAction fn.
errors.Meta(pageLayoutLogMetaKey{}, "could not undelete {{pageLayout}}; insufficient permissions"),
errors.Meta(pageLayoutPropsMetaKey{}, p),
// translation namespace & key
errors.Meta(locale.ErrorMetaNamespace{}, "compose"),
errors.Meta(locale.ErrorMetaKey{}, "page-layout.errors.notAllowedToUndelete"),
errors.StackSkip(1),
)
if len(mm) > 0 {
}
return e
}
// *********************************************************************************************************************
// *********************************************************************************************************************
+21 -25
View File
@@ -84,34 +84,30 @@ errors:
message: "invalid or missing namespace ID"
severity: warning
# - error: notAllowedToRead
# message: "not allowed to read this pageLayout"
# log: "could not read {{pageLayout}}; insufficient permissions"
- error: notAllowedToRead
message: "not allowed to read this pageLayout"
log: "could not read {{pageLayout}}; insufficient permissions"
# - error: notAllowedToSearch
# message: "not allowed to search or list pageLayouts"
# log: "could not search pageLayouts; insufficient permissions"
- error: notAllowedToSearch
message: "not allowed to search or list pageLayouts"
log: "could not search pageLayouts; insufficient permissions"
# - error: notAllowedToReadNamespace
# message: "not allowed to read this namespace"
# log: "could not read namespace {{namespace}}; insufficient permissions"
- error: notAllowedToListPageLayouts
message: "not allowed to list pageLayouts"
log: "could not list pageLayouts; insufficient permissions"
# - error: notAllowedToListPageLayouts
# message: "not allowed to list pageLayouts"
# log: "could not list pageLayouts; insufficient permissions"
- error: notAllowedToCreate
message: "not allowed to create pageLayouts"
log: "could not create pageLayouts; insufficient permissions"
# - error: notAllowedToCreate
# message: "not allowed to create pageLayouts"
# log: "could not create pageLayouts; insufficient permissions"
- error: notAllowedToUpdate
message: "not allowed to update this pageLayout"
log: "could not update {{pageLayout}}; insufficient permissions"
# - error: notAllowedToUpdate
# message: "not allowed to update this pageLayout"
# log: "could not update {{pageLayout}}; insufficient permissions"
- error: notAllowedToDelete
message: "not allowed to delete this pageLayout"
log: "could not delete {{pageLayout}}; insufficient permissions"
# - error: notAllowedToDelete
# message: "not allowed to delete this pageLayout"
# log: "could not delete {{pageLayout}}; insufficient permissions"
# - error: notAllowedToUndelete
# message: "not allowed to undelete this pageLayout"
# log: "could not undelete {{pageLayout}}; insufficient permissions"
- error: notAllowedToUndelete
message: "not allowed to undelete this pageLayout"
log: "could not undelete {{pageLayout}}; insufficient permissions"
+6
View File
@@ -29,6 +29,8 @@ type (
Config PageConfig `json:"config"`
Blocks PageBlocks `json:"blocks"`
Meta *PageMeta `json:"meta"`
Children PageSet `json:"children,omitempty"`
Labels map[string]string `json:"labels,omitempty"`
@@ -73,6 +75,10 @@ type (
Description string `json:"description,omitempty"`
}
PageMeta struct {
AllowPersonalLayouts bool `json:"allowPersonalLayouts"`
}
PageBlockStyle struct {
Variants map[string]string `json:"variants,omitempty"`
Wrap map[string]string `json:"wrap,omitempty"`
+5
View File
@@ -7,6 +7,11 @@ func ParsePageLayoutMeta(ss []string) (p *PageLayoutMeta, err error) {
return p, parseStringsInput(ss, &p)
}
func ParsePageMeta(ss []string) (p *PageMeta, err error) {
p = &PageMeta{}
return p, parseStringsInput(ss, &p)
}
func parseStringsInput(ss []string, p interface{}) (err error) {
if len(ss) == 0 {
return
+4
View File
@@ -293,6 +293,7 @@ type (
SelfID uint64 `db:"self_id"`
ModuleID uint64 `db:"module_id"`
NamespaceID uint64 `db:"namespace_id"`
Meta composeType.PageMeta `db:"meta"`
Config composeType.PageConfig `db:"config"`
Blocks composeType.PageBlocks `db:"blocks"`
Visible bool `db:"visible"`
@@ -1619,6 +1620,7 @@ func (aux *auxComposePage) encode(res *composeType.Page) (_ error) {
aux.SelfID = res.SelfID
aux.ModuleID = res.ModuleID
aux.NamespaceID = res.NamespaceID
aux.Meta = res.Meta
aux.Config = res.Config
aux.Blocks = res.Blocks
aux.Visible = res.Visible
@@ -1641,6 +1643,7 @@ func (aux auxComposePage) decode() (res *composeType.Page, _ error) {
res.SelfID = aux.SelfID
res.ModuleID = aux.ModuleID
res.NamespaceID = aux.NamespaceID
res.Meta = aux.Meta
res.Config = aux.Config
res.Blocks = aux.Blocks
res.Visible = aux.Visible
@@ -1663,6 +1666,7 @@ func (aux *auxComposePage) scan(row scanner) error {
&aux.SelfID,
&aux.ModuleID,
&aux.NamespaceID,
&aux.Meta,
&aux.Config,
&aux.Blocks,
&aux.Visible,
+4
View File
@@ -1971,6 +1971,7 @@ var (
"self_id",
"rel_module",
"rel_namespace",
"meta",
"config",
"blocks",
"visible",
@@ -1994,6 +1995,7 @@ var (
"self_id": res.SelfID,
"rel_module": res.ModuleID,
"rel_namespace": res.NamespaceID,
"meta": res.Meta,
"config": res.Config,
"blocks": res.Blocks,
"visible": res.Visible,
@@ -2020,6 +2022,7 @@ var (
"self_id": res.SelfID,
"rel_module": res.ModuleID,
"rel_namespace": res.NamespaceID,
"meta": res.Meta,
"config": res.Config,
"blocks": res.Blocks,
"visible": res.Visible,
@@ -2044,6 +2047,7 @@ var (
"self_id": res.SelfID,
"rel_module": res.ModuleID,
"rel_namespace": res.NamespaceID,
"meta": res.Meta,
"config": res.Config,
"blocks": res.Blocks,
"visible": res.Visible,
+6
View File
@@ -642,7 +642,9 @@ func AttachmentErrFailedToProcessImage(mm ...*attachmentActionProps) *errors.Err
// AttachmentErrInvalidAvatarFileType returns "system:attachment.invalidAvatarFileType" as *errors.Error
//
//
// This function is auto-generated.
//
func AttachmentErrInvalidAvatarFileType(mm ...*attachmentActionProps) *errors.Error {
var p = &attachmentActionProps{}
if len(mm) > 0 {
@@ -674,7 +676,9 @@ func AttachmentErrInvalidAvatarFileType(mm ...*attachmentActionProps) *errors.Er
// AttachmentErrInvalidAvatarFileSize returns "system:attachment.invalidAvatarFileSize" as *errors.Error
//
//
// This function is auto-generated.
//
func AttachmentErrInvalidAvatarFileSize(mm ...*attachmentActionProps) *errors.Error {
var p = &attachmentActionProps{}
if len(mm) > 0 {
@@ -706,7 +710,9 @@ func AttachmentErrInvalidAvatarFileSize(mm ...*attachmentActionProps) *errors.Er
// AttachmentErrInvalidInitialsLength returns "system:attachment.invalidInitialsLength" as *errors.Error
//
//
// This function is auto-generated.
//
func AttachmentErrInvalidInitialsLength(mm ...*attachmentActionProps) *errors.Error {
var p = &attachmentActionProps{}
if len(mm) > 0 {
+5
View File
@@ -560,6 +560,7 @@ func UserActionDeleteAuthSessions(props ...*userActionProps) *userAction {
// UserActionUploadAvatar returns "system:user.uploadAvatar" action
//
// This function is auto-generated.
//
func UserActionUploadAvatar(props ...*userActionProps) *userAction {
a := &userAction{
timestamp: time.Now(),
@@ -579,6 +580,7 @@ func UserActionUploadAvatar(props ...*userActionProps) *userAction {
// UserActionGenerateAvatar returns "system:user.generateAvatar" action
//
// This function is auto-generated.
//
func UserActionGenerateAvatar(props ...*userActionProps) *userAction {
a := &userAction{
timestamp: time.Now(),
@@ -598,6 +600,7 @@ func UserActionGenerateAvatar(props ...*userActionProps) *userAction {
// UserActionDeleteAvatar returns "system:user.deleteAvatar" action
//
// This function is auto-generated.
//
func UserActionDeleteAvatar(props ...*userActionProps) *userAction {
a := &userAction{
timestamp: time.Now(),
@@ -1364,7 +1367,9 @@ func UserErrMaxUserLimitReached(mm ...*userActionProps) *errors.Error {
// UserErrNotAllowedToDeleteAvatar returns "system:user.notAllowedToDeleteAvatar" as *errors.Error
//
//
// This function is auto-generated.
//
func UserErrNotAllowedToDeleteAvatar(mm ...*userActionProps) *errors.Error {
var p = &userActionProps{}
if len(mm) > 0 {