3
0

Implement ownership access-control on record creation

Besides "owner.manage" on record resoure we now also have
"owned-record.create" on module.
This commit is contained in:
Denis Arh
2022-06-28 15:58:57 +02:00
parent 42f94b6395
commit 9ce63f1210
4 changed files with 38 additions and 27 deletions

View File

@@ -45,6 +45,7 @@ module: schema.#Resource & {
"update": {}
"delete": {}
"record.create": description: "Create record"
"owned-record.create": description: "Create record with custom owner"
"records.search": description: "List, search or filter records"
}
}

View File

@@ -23,10 +23,11 @@ type (
Fields []*moduleFieldPayload `json:"fields"`
CanGrant bool `json:"canGrant"`
CanUpdateModule bool `json:"canUpdateModule"`
CanDeleteModule bool `json:"canDeleteModule"`
CanCreateRecord bool `json:"canCreateRecord"`
CanGrant bool `json:"canGrant"`
CanUpdateModule bool `json:"canUpdateModule"`
CanDeleteModule bool `json:"canDeleteModule"`
CanCreateRecord bool `json:"canCreateRecord"`
CanCreateOwnedRecord bool `json:"canCreateOwnedRecord"`
}
moduleFieldPayload struct {
@@ -49,6 +50,7 @@ type (
CanUpdateModule(context.Context, *types.Module) bool
CanDeleteModule(context.Context, *types.Module) bool
CanCreateRecordOnModule(context.Context, *types.Module) bool
CanCreateOwnedRecordOnModule(context.Context, *types.Module) bool
CanReadRecord(context.Context, *types.Record) bool
CanReadRecordValueOnModuleField(context.Context, *types.ModuleField) bool
@@ -189,7 +191,9 @@ func (ctrl Module) makePayload(ctx context.Context, m *types.Module, err error)
CanUpdateModule: ctrl.ac.CanUpdateModule(ctx, m),
CanDeleteModule: ctrl.ac.CanDeleteModule(ctx, m),
CanCreateRecord: ctrl.ac.CanCreateRecordOnModule(ctx, m),
CanCreateRecord: ctrl.ac.CanCreateRecordOnModule(ctx, m),
CanCreateOwnedRecord: ctrl.ac.CanCreateOwnedRecordOnModule(ctx, m),
}, nil
}

View File

@@ -174,6 +174,11 @@ func (svc accessControl) List() (out []map[string]string) {
"any": types.ModuleRbacResource(0, 0),
"op": "record.create",
},
{
"type": types.ModuleResourceType,
"any": types.ModuleRbacResource(0, 0),
"op": "owned-record.create",
},
{
"type": types.ModuleResourceType,
"any": types.ModuleRbacResource(0, 0),
@@ -426,6 +431,13 @@ func (svc accessControl) CanCreateRecordOnModule(ctx context.Context, r *types.M
return svc.can(ctx, "record.create", r)
}
// CanCreateOwnedRecordOnModule checks if current user can create record with custom owner
//
// This function is auto-generated
func (svc accessControl) CanCreateOwnedRecordOnModule(ctx context.Context, r *types.Module) bool {
return svc.can(ctx, "owned-record.create", r)
}
// CanSearchRecordsOnModule checks if current user can list, search or filter records
//
// This function is auto-generated
@@ -651,11 +663,12 @@ func rbacResourceOperations(r string) map[string]bool {
}
case types.ModuleResourceType:
return map[string]bool{
"read": true,
"update": true,
"delete": true,
"record.create": true,
"records.search": true,
"read": true,
"update": true,
"delete": true,
"record.create": true,
"owned-record.create": true,
"records.search": true,
}
case types.ModuleFieldResourceType:
return map[string]bool{

View File

@@ -72,6 +72,7 @@ type (
recordManageOwnerAccessController interface {
CanManageOwnerOnRecord(context.Context, *types.Record) bool
CanCreateOwnedRecordOnModule(context.Context, *types.Module) bool
}
recordAccessController interface {
@@ -661,10 +662,15 @@ func SetRecordOwner(ctx context.Context, ac recordManageOwnerAccessController, s
}
)
if (old != nil && curOwner != updOwner) || (old == nil && updOwner != invoker) {
// check if ownership can be changed when:
// a) updating (old != nil) and ownership changed
// b) creating (old == nil) and ownership id not set to the invoking user
if old == nil && updOwner != invoker {
// Can be set on new records
if !ac.CanCreateOwnedRecordOnModule(ctx, upd.GetModule()) {
return mkError("accessDenied", "record.errors.ownershipChangeDenied")
}
}
if old != nil && curOwner != updOwner {
// Can ownership be changed on existing record?
if !ac.CanManageOwnerOnRecord(ctx, upd) {
return mkError("accessDenied", "record.errors.ownershipChangeDenied")
}
@@ -929,19 +935,6 @@ func (svc record) procCreate(ctx context.Context, invokerID uint64, m *types.Mod
new.DeletedAt = nil
new.DeletedBy = 0
if new.OwnedBy == 0 {
new.OwnedBy = invokerID
}
if new.OwnedBy != invokerID {
// we're creating record here and this check goes against current
// RBAC implementation logic on record creation
if !svc.ac.CanManageOwnerOnRecord(ctx, new) {
// not permitted to change the owner
}
}
if err := SetRecordOwner(ctx, svc.ac, svc.store, nil, new, invokerID); err != nil {
return err
}