Skip to content

Commit cfa7939

Browse files
committed
Initial commit
0 parents  commit cfa7939

File tree

5 files changed

+207
-0
lines changed

5 files changed

+207
-0
lines changed

.editorconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
root = true
2+
3+
[*]
4+
indent_style = space
5+
indent_size = 4
6+
end_of_line = lf
7+
charset = utf-8
8+
trim_trailing_whitespace = true
9+
insert_final_newline = true

README.md

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# Kirby – Bouncer
2+
3+
Restrict access of a user role to a specific page (and its children) in the panel.
4+
5+
![bouncer-screenshot](https://user-images.githubusercontent.com/14079751/76368370-4c6ccc00-6330-11ea-92d3-9ac560cf037e.jpg)
6+
7+
<br/>
8+
9+
## Overview
10+
11+
> This plugin is completely free and published under the MIT license. However, if you are using it in a commercial project and want to help me keep up with maintenance, please consider [making a donation of your choice](https://www.paypal.me/sylvainjule) or purchasing your license(s) through [my affiliate link](https://a.paddle.com/v2/click/1129/36369?link=1170).
12+
13+
- [1. Installation](#1-installation)
14+
- [2. Setup](#2-setup)
15+
- [3. Disclaimer](#3-disclaimer)
16+
- [4. License](#4-disclaimer)
17+
18+
<br/>
19+
20+
## 1. Installation
21+
22+
Download and copy this repository to ```/site/plugins/bouncer```
23+
24+
Alternatively, you can install it with composer: ```composer require sylvainjule/bouncer```
25+
26+
<br/>
27+
28+
## 2. Setup
29+
30+
The intent of this plugin is to limit a user's ability to edit only their Account page + a page (and its children) selected in a *Pages field*.
31+
32+
- First, create a new user role (for example, `/site/blueprints/users/test.yml`)
33+
- Set their permissions, and add a `pages` field:
34+
35+
```yaml
36+
title: Test
37+
38+
permissions:
39+
access:
40+
panel: true
41+
site: true
42+
settings: false
43+
users: false
44+
# ...
45+
user:
46+
changeRole: false
47+
delete: false
48+
update: false # else a user will be able to edit the page they have access to on their profile
49+
50+
fields:
51+
canaccess:
52+
label: 'The user will only be able to access:'
53+
type: pages
54+
multiple: false
55+
options: query
56+
query: site.pages # or any query that suits your needs
57+
```
58+
59+
- In your `site/config/config.php`, tell the plugin which `role => fieldname` associations to use:
60+
61+
```php
62+
return [
63+
'sylvainjule.bouncer.list' => [
64+
'test' => 'canaccess'
65+
]
66+
];
67+
```
68+
69+
<br/>
70+
71+
## 3. Disclaimer
72+
73+
- I needed this functionnality for a website and turned it into a plugin. I hope it can prove helpful, but do not intend to extend it or support more refined restriction scenarios with this plugin.
74+
- The plugin uses Vue router's `beforeResolve` guard, currently not used by the panel (Kirby 3.3.5). This may change in the future, please look for any change in that direction before updating your websites, and please let me know if you spot an interfering update.
75+
76+
<br/>
77+
78+
## 4. License
79+
80+
MIT

composer.json

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"name": "sylvainjule/bouncer",
3+
"description": "Restrict access of a user role to a specific page (and its children) in the panel.",
4+
"type": "kirby-plugin",
5+
"license": "MIT",
6+
"authors": [
7+
{
8+
"name": "Sylvain Julé",
9+
"email": "[email protected]"
10+
}
11+
],
12+
"require": {
13+
"getkirby/composer-installer": "^1.1"
14+
},
15+
"extra": {
16+
"installer-name": "bouncer"
17+
},
18+
"minimum-stability": "beta"
19+
}

index.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
panel.plugin('sylvainjule/bouncer', {
2+
created(Vue) {
3+
Vue.$router.onReady(function() {
4+
getCurrentUser(true, function() {
5+
checkRedirect(Vue.$router.currentRoute, undefined);
6+
});
7+
});
8+
9+
Vue.$router.beforeResolve((to, from, next) => {
10+
if(from.path == '/login') Vue.$data.user = undefined;
11+
12+
if(!Vue.$data.user) {
13+
getCurrentUser(false, function() {
14+
checkRedirect(to, next);
15+
});
16+
}
17+
else {
18+
checkRedirect(to, next);
19+
}
20+
});
21+
22+
23+
function checkRedirect(to, next, firstLoad = false) {
24+
var user = Vue.$data.user;
25+
26+
if(user && user.restriction) {
27+
if(!isAllowed(to, user)) {
28+
if(next) { next(user.restriction.path); }
29+
else { Vue.$router.push(user.restriction.path); }
30+
}
31+
else {
32+
if(next) {
33+
if(to.path == '/logout' || to.path == '/login') Vue.$data.user = undefined;
34+
next();
35+
}
36+
}
37+
}
38+
else {
39+
if(next) { next(); }
40+
}
41+
}
42+
function getCurrentUser(safety = false, callback = false) {
43+
if(safety && (Vue.$router.currentRoute.path == '/login' || Vue.$router.currentRoute.path == '/')) return false;
44+
45+
Vue.$api
46+
.get('current-user')
47+
.then(user => {
48+
Vue.$data.user = user;
49+
if(callback) callback();
50+
});
51+
}
52+
function isAllowed(to, user) {
53+
return to.name == 'Account' ||
54+
to.path == '/logout' ||
55+
to.path == '/login' ||
56+
to.path.slice(0, user.restriction.path.length) == user.restriction.path;
57+
}
58+
},
59+
});

index.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
Kirby::plugin('sylvainjule/bouncer', [
4+
'options' => array(
5+
'list' => []
6+
),
7+
'api' => [
8+
'routes' => function ($kirby) {
9+
return [
10+
[
11+
'pattern' => 'current-user',
12+
'action' => function() use ($kirby) {
13+
$currentUser = $kirby->user();
14+
$currentRole = $currentUser->role()->name();
15+
$restriction = false;
16+
17+
foreach(option('sylvainjule.bouncer.list') as $role => $fieldname) {
18+
if($currentRole == $role) {
19+
if($p = $currentUser->$fieldname()->toPage()) {
20+
$restriction = array(
21+
'path' => $p->panelUrl(true),
22+
);
23+
}
24+
else {
25+
$restriction = array(
26+
'path' => '/users/'. $currentUser->id(),
27+
);
28+
}
29+
}
30+
}
31+
32+
return array(
33+
'restriction' => $restriction,
34+
);
35+
}
36+
]
37+
];
38+
}
39+
]
40+
]);

0 commit comments

Comments
 (0)