1
0
mirror of https://github.com/processwire/processwire.git synced 2025-08-12 09:44:38 +02:00

Update to add support for user-view-[role] permissions for cases where people may be implementing a user.php (or related) template file @adrianbj

This commit is contained in:
Ryan Cramer
2021-05-06 10:07:47 -04:00
parent 4ce75aed1a
commit 3485aa8763
2 changed files with 70 additions and 27 deletions

View File

@@ -167,14 +167,18 @@ class Permissions extends PagesType {
'page-edit-images' => $this->_('Use the image editor to manipulate (crop, resize, etc.) images'),
'page-rename' => $this->_('Change the name of published pages they are allowed to edit'),
'user-admin-all' => $this->_('Administer users in any role (except superuser)'),
'user-view-all' => $this->_('User can view users in any role (including superuser)'),
'user-view-self' => $this->_('User can view themself (when not already by other permission)')
);
foreach($this->wire('roles') as $role) {
if($role->name == 'guest' || $role->name == 'superuser') continue;
foreach($this->wire()->roles as $role) {
if($role->name === 'guest') continue;
$a["user-view-$role->name"] = sprintf($this->_('View users in role: %s'), $role->name);
if($role->name === 'superuser') continue;
$a["user-admin-$role->name"] = sprintf($this->_('Administer users in role: %s'), $role->name);
}
$languages = $this->wire('languages');
$languages = $this->wire()->languages;
if($languages) {
$label = $this->_('Edit fields on a page in language: %s');
$alsoLabel = $this->_('(also required to create or delete pages)');

View File

@@ -239,14 +239,13 @@ class PagePermissions extends WireData implements Module {
*/
public function userEditable(Page $page, array $options = array()) {
/** @var User $user */
$user = $this->wire('user');
/** @var Process|ProcessProfile|ProcessPageView|ProcessUser|ProcessPageList|ProcessPageLister $process */
$process = $this->wire('process');
/** @var Config $config */
$config = $this->wire('config');
$user = $this->wire()->user;
$process = $this->wire()->process;
$processName = (string) $process;
$config = $this->wire()->config;
$guestRoleID = $config->guestUserRolePageID;
$defaults = array(
'viewable' => false, // specify true if method is being used to determine viewable state
@@ -255,26 +254,58 @@ class PagePermissions extends WireData implements Module {
$options = count($options) ? array_merge($defaults, $options) : $defaults;
if(!$page->id) return false;
if($page->className() != 'User') $page = $this->wire('users')->get($page->id);
if(!$page || $page instanceof NullPage) return false;
if($user->id === $page->id && !$user->isGuest() && $user->hasPermission('profile-edit')) {
// user is the same as the page being edited or viewed
if($process == 'ProcessProfile') {
// user editing themself in ProcssProfile
return true;
} else if($this->wire('page') && $this->wire('page')->process == 'ProcessProfile') {
// user editing themself in ProcessProfile, when process not yet established
return true;
} else if($process == 'ProcessPageView' && $page->secureFiles() && $options['viewable']) {
// user is viewing a file that is part of their User page when pagefileSecure mode active
return $process->getResponseType() == ProcessPageView::responseTypeFile;
if(!$page instanceof User) {
$template = $this->wire()->templates->get('user');
if($page->className() !== $template->getPageClass(false)) {
$page = $this->wire()->users->get($page->id);
}
}
// if the current process is something other than ProcessUser, they don't have permission
if(!$options['viewable']) {
if($process != 'ProcessUser' && (!$process instanceof ProcessPageList) && (!$process instanceof ProcessPageLister)) {
if(!$page || $page instanceof NullPage) return false;
if($user->id === $page->id && $user->isLoggedin()) {
// user is the same as the page being edited or viewed
$wirePage = $this->wire()->page;
$wireProcessName = $wirePage ? "$wirePage->process" : '';
if(($processName === 'ProcessProfile' || $wireProcessName === 'ProcessProfile') && $user->hasPermission('profile-edit')) {
// user editing themself in ProcessProfile
return true;
}
if($options['viewable'] && $user->hasPermission('user-view-self')) {
// user requests to view themselves
return true;
}
}
if($options['viewable']) {
// perform viewable checks rather than editable checks
if($page->template->useRoles && $user->hasPermission('page-view', $page)) {
// access permission provided by page-view permission configured directly (not inherited) on user template
if($user->isLoggedin()) return true;
}
if($user->hasPermission('user-view-all')) {
// user-view-all permission is similar to page-view on the user template but can also be assigned to guest role
return true;
}
if($page->isSuperuser()) {
// if superuser role is present then view permission cannot be provided by any other user-view-[role]
return $user->isSuperuser() || $user->hasPermission('user-view-superuser');
}
// check for match between user-view-[role] permission and roles of user being requested
$userViewable = false;
foreach($page->roles as $role) {
// check for "user-view-[roleName]" permissions
if($role->id == $guestRoleID) continue;
if($user->hasPermission("user-view-$role->name")) $userViewable = true;
if($userViewable) break;
}
if($userViewable) return true;
} else {
// if the current process is something other than ProcessUser, they don't have permission
if($processName !== 'ProcessUser' && (!$process instanceof ProcessPageList) && (!$process instanceof ProcessPageLister)) {
return false;
}
}
@@ -284,12 +315,12 @@ class PagePermissions extends WireData implements Module {
// if the user page being edited has a superuser role, and the current user doesn't,
// never let them edit regardless of any other permissions
$superuserRole = $this->wire('roles')->get($config->superUserRolePageID);
$superuserRole = $this->wire()->roles->get($config->superUserRolePageID);
if($page->roles->has($superuserRole) && !$user->roles->has($superuserRole)) return false;
// if we reach this point then check if there are more granular user-admin permissions available
// special permissions: user-admin-all, and user-admin-[role]
$userAdminAll = $this->wire('permissions')->get('user-admin-all');
$userAdminAll = $this->wire()->permissions->get('user-admin-all');
// if there are no special permissions, then let them through
if(!$userAdminAll->id) return true;
@@ -299,7 +330,6 @@ class PagePermissions extends WireData implements Module {
// there are role-specific permissions in the system, and user must have appropriate one to edit
$userEditable = false;
$guestRoleID = $config->guestUserRolePageID;
$n = 0;
foreach($page->roles as $role) {
$n++;
@@ -317,6 +347,15 @@ class PagePermissions extends WireData implements Module {
return false;
}
/**
* Returns whether the given user ($page) is viewable by the current user
*
* @param User|Page $page
* @param array $options
* @return bool
* @throws WireException
*
*/
public function userViewable(Page $page, array $options = array()) {
$user = $this->wire()->user;
// user viewing themself
@@ -597,7 +636,7 @@ class PagePermissions extends WireData implements Module {
} else if($page->hasField('process') && $page->get('process')) {
// delegate access to permissions defined with Process module
$viewable = $this->processViewable($page);
} else if($page instanceof User && !$user->isGuest() && ($user->hasPermission('user-admin') || $page->id === $user->id)) {
} else if($page instanceof User) { // && !$user->isGuest() && ($user->hasPermission('user-admin') || $page->id === $user->id)) {
// user administrator or user viewing themself
$viewable = $this->userViewable($page);
} else if(!$user->hasPermission("page-view", $page)) {