diff --git a/blueprints/fields/permission-access.yml b/blueprints/fields/permission-access.yml new file mode 100644 index 0000000..4f7d0e4 --- /dev/null +++ b/blueprints/fields/permission-access.yml @@ -0,0 +1,8 @@ +type: fields + +fields: + permissionAccess: + label: Access Permission + type: tags + options: query + query: site.getPermissionTags diff --git a/blueprints/fields/permission-user.yml b/blueprints/fields/permission-user.yml new file mode 100644 index 0000000..55b02cd --- /dev/null +++ b/blueprints/fields/permission-user.yml @@ -0,0 +1,8 @@ +type: fields + +fields: + permissionUser: + label: User Permissions + type: tags + options: query + query: site.getPermissionTags diff --git a/index.php b/index.php index 1d5aab6..49ac720 100644 --- a/index.php +++ b/index.php @@ -14,6 +14,62 @@ Kirby::plugin( name: "hobbyhome/permissions", extends: [ + "options" => [ + "excludeAdmin" => true, + "inherit" => true, + ], + "blueprints" => [ + "fields/permission-user" => __DIR__ . "/blueprints/fields/permission-user.yml", + "fields/permission-access" => __DIR__ . "/blueprints/fields/permission-access.yml", + ], + "hooks" => [ + "page.render:before" => function ($contentType, $data, $page) { + if (!$page->hasPerm()) { + go(site()->errorPage(), 403); + } + + return $data; + }, + "permissions.page:check" => function ($permission, $page, $field = "permissionAccess", $inherit = null) { + $permission = hasPerm($page, $field); + + if ($permission) { + if (is_null($inherit)) { + $inherit = option("hobbyhome.permissions.inherit"); + } + + if ($inherit) { + // We're inheriting permissions. + // Ensure user has access to parent pages. + foreach ($page->parents() as $parent) { + if (!hasPerm($parent, $field)) { + $permission = false; + break; + } + } + } + } + + return $permission; + } + ], + "pageMethods" => [ + "hasPerm" => function ($field = "permissionAccess", $inherit = null) { + $permission = false; + + return kirby()->apply("permissions.page:check", ["permission" => $permission, "page" => $this, "field" => $field, "inherit" => $inherit], "permission"); + }, + ], + "siteMethods" => [ + "getPermissionTags" => function() { + $userPermissions = kirby()->users()->pluck("permissionUser", ",", true); + $accessPermissions = $this->index(true)->pluck("permissionAccess", ",", true); + + $availablePermissions = A::merge($userPermissions, $accessPermissions); + + return $availablePermissions; + }, + ], ], info: [ "authors" => [[ @@ -25,3 +81,36 @@ Kirby::plugin( "version" => "0.0.0", ], ); + +/** + * Check if a user has the permission set on $object->$field(). + */ +function hasPerm($object, $field = "permissionAccess") { + $hasPerm = false; + + if ($object->$field()->isEmpty()) { + // Permission is not restricted. + $hasPerm = true; + } elseif ($user = kirby()->user()) { + if (option("hobbyhome.permissions.excludeAdmin") and $user->role()->isAdmin()) { + // User is an admin and excluded from permission checks. + $hasPerm = true; + } else { + // Get user permissions. + $userPermissions = $user->permissionUser()->split(); + + // Get object permissions. + $objectPermissions = $object->$field()->split(); + + // Check if at least one object permission is in the list of user permissions. + foreach ($objectPermissions as $permission) { + if (A::has($userPermissions, $permission, true)) { + $hasPerm = true; + break; + } + } + } + } + + return $hasPerm; +}