Return different "Not permitted" error message depending on what is required #2548

This commit is contained in:
Kijin Sung 2025-05-22 13:20:48 +09:00
parent 7cba835065
commit bb4cd62e31
5 changed files with 91 additions and 35 deletions

View file

@ -249,7 +249,7 @@ class ModuleObject extends BaseObject
*/
public function setPrivileges()
{
if(!$this->user->isAdmin())
if (!$this->user->isAdmin())
{
// Get privileges(granted) information for target module by <permission check> of module.xml
if(($permission = $this->xml_info->action->{$this->act}->permission) && $permission->check_var)
@ -278,34 +278,29 @@ class ModuleObject extends BaseObject
foreach($check_module_srl as $target_srl)
{
// Get privileges(granted) information of current user for target module
if(($grant = ModuleModel::getInstance()->getPrivilegesBySrl($target_srl, $permission->check_type)) === false)
$check_grant = ModuleModel::getPrivilegesBySrl($target_srl, $permission->check_type);
if ($check_grant === false)
{
return false;
}
// Check permission
if(!$this->checkPermission($grant, $this->user))
if(!$this->checkPermission($check_grant, $this->user, $failed_requirement))
{
$this->stop($this->user->isMember() ? 'msg_not_permitted_act' : 'msg_not_logged');
$this->stop($this->_generatePermissionError($failed_requirement));
return false;
}
}
}
}
// If no privileges(granted) information, check permission by privileges(granted) information for current module
if(!isset($grant))
{
// Get privileges(granted) information of current user for current module
// Check permission based on the grant information for the current module.
$grant = ModuleModel::getInstance()->getGrant($this->module_info, $this->user, $this->xml_info);
// Check permission
if(!$this->checkPermission($grant, $this->user))
if(!$this->checkPermission($grant, $this->user, $failed_requirement))
{
$this->stop($this->user->isMember() ? 'msg_not_permitted_act' : 'msg_not_logged');
$this->stop($this->_generatePermissionError($failed_requirement));
return false;
}
}
// If member action, grant access for log-in, sign-up, member pages
if(preg_match('/^(disp|proc)(Member|Communication)[A-Z][a-zA-Z]+$/', $this->act))
@ -313,7 +308,7 @@ class ModuleObject extends BaseObject
$grant->access = true;
}
// Set privileges(granted) variables
// Set aliases to grant object
$this->grant = $grant;
Context::set('grant', $grant);
@ -325,9 +320,10 @@ class ModuleObject extends BaseObject
*
* @param object $grant privileges(granted) information of user
* @param object $member_info member information
* @param string|array &$failed_requirement
* @return bool
*/
public function checkPermission($grant = null, $member_info = null)
public function checkPermission($grant = null, $member_info = null, &$failed_requirement = '')
{
// Get logged-in member information
if(!$member_info)
@ -361,24 +357,45 @@ class ModuleObject extends BaseObject
{
return true;
}
// If permission is 'member', the user must be logged in
elseif ($permission === 'member')
if ($permission === 'member')
{
if($member_info->member_srl)
if ($member_info->member_srl)
{
return true;
}
else
{
$failed_requirement = 'member';
return false;
}
}
// If permission is 'not_member', the user must be logged out
elseif ($permission === 'not_member' || $permission === 'not-member')
if ($permission === 'not_member' || $permission === 'not-member')
{
if(!$member_info->member_srl)
if (!$member_info->member_srl || $grant->manager)
{
return true;
}
else
{
$failed_requirement = 'not_member';
return false;
}
}
// If permission is 'root', false
// Because an administrator who have root privilege(granted) was passed already
if ($permission == 'root')
{
$failed_requirement = 'root';
return false;
}
// If permission is 'manager', check 'is user have manager privilege(granted)'
elseif (preg_match('/^(manager(?::(.+))?|([a-z0-9\_]+)-managers)$/', $permission, $type))
if (preg_match('/^(manager(?::(.+))?|([a-z0-9\_]+)-managers)$/', $permission, $type))
{
// If permission is manager(:scope), check manager privilege and scope
if ($grant->manager)
@ -412,32 +429,63 @@ class ModuleObject extends BaseObject
return true;
}
}
$failed_requirement = 'manager';
return false;
}
// If permission is 'root', false
// Because an administrator who have root privilege(granted) was passed already
elseif ($permission == 'root')
// Check grant name
// If multiple names are given, all of them must pass.
elseif ($grant_names = array_map('trim', explode(',', $permission)))
{
foreach ($grant_names as $name)
{
if (!isset($grant->{$name}))
{
return false;
}
// If grant name, check the privilege(granted) of the user
elseif ($grant_names = explode(',', $permission))
{
$privilege_list = array_keys((array) $this->xml_info->grant);
foreach($grant_names as $name)
{
if(!in_array($name, $privilege_list) || !$grant->$name)
if (!$grant->{$name})
{
$failed_requirement = $grant->whocan($name);
return false;
}
}
return true;
}
return false;
}
/**
* Generate an error message for a failed permission.
*
* @param mixed $failed_requirement
* @return string
*/
protected function _generatePermissionError($failed_requirement)
{
if ($failed_requirement === 'member' || !$this->user->isMember())
{
return 'msg_not_logged';
}
elseif ($failed_requirement === 'not_member')
{
return 'msg_required_not_logged';
}
elseif ($failed_requirement === 'manager' || $failed_requirement === 'root')
{
return 'msg_administrator_only';
}
elseif (is_array($failed_requirement))
{
return 'msg_required_specific_group';
}
else
{
return 'msg_not_permitted_act';
}
}
/**
* Stop processing this module instance.
*

View file

@ -251,7 +251,8 @@ $lang->msg_not_founded = 'Cannot find the target.';
$lang->msg_no_result = 'No results found.';
$lang->msg_fail_to_request_open = 'Failed to open your request.';
$lang->msg_invalid_format = 'Invalid Format';
$lang->msg_not_permitted_act = 'You do not have permission to execute requested action.';
$lang->msg_administrator_only = 'Only administrators can access this page.';
$lang->msg_not_permitted_act = 'You do not have permission to access this page.';
$lang->msg_module_is_not_exists = 'Cannot find the page you requested. Ask your Site Admin to check the page.';
$lang->msg_module_is_not_standalone = 'Requested page cannot be executed independently.';
$lang->msg_module_class_not_found = 'Cannot find class to handle the requested action.';

View file

@ -251,6 +251,7 @@ $lang->msg_not_founded = '대상을 찾을 수 없습니다.';
$lang->msg_no_result = '검색 결과가 없습니다.';
$lang->msg_fail_to_request_open = '요청한 연결에 실패했습니다.';
$lang->msg_invalid_format = '잘못된 형식입니다.';
$lang->msg_administrator_only = '관리자만 사용할 수 있는 기능입니다.';
$lang->msg_not_permitted_act = '요청한 기능을 실행할 수 있는 권한이 없습니다.';
$lang->msg_module_is_not_exists = '요청한 페이지를 찾을 수 없습니다. 사이트 관리자에게 문의해 주세요.';
$lang->msg_module_is_not_standalone = '요청한 페이지는 독립적으로 동작할 수 없습니다.';

View file

@ -201,6 +201,9 @@ $lang->msg_email_address_not_changeable = 'You cannot change your email address
$lang->msg_signup_disabled = 'You are not able to sign up';
$lang->msg_already_logged = 'You have already signed up.';
$lang->msg_not_logged = 'Please log in.';
$lang->msg_required_not_logged = 'This page is only available to users who are not logged in.';
$lang->msg_required_specific_group = 'You need to belong to a certain group in order to access this page.';
$lang->msg_required_minimum_level = 'YOu need to be level %d or higher in order to access this page.';
$lang->msg_insert_group_name = 'Please enter the name of group.';
$lang->msg_check_group = 'Please select the group.';
$lang->msg_not_uploaded_profile_image = 'Profile image could not be registered.';

View file

@ -203,6 +203,9 @@ $lang->msg_email_address_not_changeable = '이메일 주소는 이 화면에서
$lang->msg_signup_disabled = '회원 가입할 수 없습니다.';
$lang->msg_already_logged = '이미 로그인되어 있습니다.';
$lang->msg_not_logged = '로그인이 필요합니다.';
$lang->msg_required_not_logged = '로그인하지 않은 상태에서만 사용할 수 있는 기능입니다.';
$lang->msg_required_specific_group = '이 기능을 사용할 수 있는 그룹이 제한되어 있습니다.';
$lang->msg_required_minimum_level = '이 기능을 사용하려면 레벨 %d 이상이어야 합니다.';
$lang->msg_insert_group_name = '그룹명을 입력해 주세요.';
$lang->msg_check_group = '그룹을 선택해 주세요.';
$lang->msg_not_uploaded_profile_image = '프로필 이미지를 등록할 수 없습니다.';