first commit
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/security/authorization/internal/ApiAuthorizationMiddleware.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class ApiAuthorizationMiddleware
|
||||
*
|
||||
* @ingroup security_authorization
|
||||
*
|
||||
* @brief Slim middleware which enforces authorization policies
|
||||
*/
|
||||
|
||||
namespace PKP\security\authorization\internal;
|
||||
|
||||
use PKP\core\APIResponse;
|
||||
use PKP\core\JSONMessage;
|
||||
use PKP\handler\APIHandler;
|
||||
use Slim\Http\Request as SlimRequest;
|
||||
|
||||
class ApiAuthorizationMiddleware
|
||||
{
|
||||
/** @var APIHandler $handler Reference to api handler */
|
||||
protected $_handler = null;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
*/
|
||||
public function __construct(APIHandler $handler)
|
||||
{
|
||||
$this->_handler = $handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles authorization
|
||||
*
|
||||
* @param SlimRequest $slimRequest
|
||||
*
|
||||
* @return bool|string
|
||||
*/
|
||||
protected function _authorize($slimRequest)
|
||||
{
|
||||
// share SlimRequest with Handler
|
||||
$this->_handler->setSlimRequest($slimRequest);
|
||||
$request = $this->_handler->getRequest();
|
||||
$args = [$slimRequest];
|
||||
if (!$slimRequest->getAttribute('route')) {
|
||||
return $request->getRouter()->handleAuthorizationFailure($request, 'api.404.endpointNotFound');
|
||||
} elseif ($this->_handler->authorize($request, $args, $this->_handler->getRoleAssignments())) {
|
||||
$this->_handler->validate(null, $request);
|
||||
$this->_handler->initialize($request);
|
||||
return true;
|
||||
} else {
|
||||
$authorizationMessage = $this->_handler->getLastAuthorizationMessage();
|
||||
if ($authorizationMessage == '') {
|
||||
$authorizationMessage = 'api.403.unauthorized';
|
||||
}
|
||||
$router = $request->getRouter();
|
||||
$result = $router->handleAuthorizationFailure($request, $authorizationMessage);
|
||||
switch (1) {
|
||||
case is_string($result): return $result;
|
||||
case $result instanceof JSONMessage: return $result->getString();
|
||||
default:
|
||||
assert(false);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Middleware invokable function
|
||||
*
|
||||
* @param SlimRequest $request request
|
||||
* @param APIResponse $response response
|
||||
* @param callable $next Next middleware
|
||||
*
|
||||
* @return bool|string|APIResponse
|
||||
*/
|
||||
public function __invoke($request, $response, $next)
|
||||
{
|
||||
$result = $this->_authorize($request);
|
||||
if ($result !== true) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
$response = $next($request, $response);
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\security\authorization\internal\ApiAuthorizationMiddleware', '\ApiAuthorizationMiddleware');
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/security/authorization/internal/ApiCsrfMiddleware.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class ApiCsrfMiddleware
|
||||
*
|
||||
* @ingroup security_authorization
|
||||
*
|
||||
* @brief Slim middleware which requires a CSRF token for POST, PUT and DELETE
|
||||
* operations whenever an API Token is not in use.
|
||||
*/
|
||||
|
||||
namespace PKP\security\authorization\internal;
|
||||
|
||||
use APP\core\Application;
|
||||
use PKP\core\APIResponse;
|
||||
use PKP\handler\APIHandler;
|
||||
use Slim\Http\Request as SlimRequest;
|
||||
|
||||
class ApiCsrfMiddleware
|
||||
{
|
||||
/** @var APIHandler $handler Reference to api handler */
|
||||
protected $_handler = null;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
*/
|
||||
public function __construct(APIHandler $handler)
|
||||
{
|
||||
$this->_handler = $handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Middleware invokable function
|
||||
*
|
||||
* @param SlimRequest $slimRequest request
|
||||
* @param APIResponse $response response
|
||||
* @param callable $next Next middleware
|
||||
*
|
||||
* @return APIResponse
|
||||
*/
|
||||
public function __invoke($slimRequest, $response, $next)
|
||||
{
|
||||
if ($this->_isCSRFRequired($slimRequest) && !$this->_isCSRFValid($slimRequest)) {
|
||||
return $response->withJson([
|
||||
'error' => 'form.csrfInvalid',
|
||||
'errorMessage' => __('form.csrfInvalid'),
|
||||
], 403);
|
||||
}
|
||||
$response = $next($slimRequest, $response);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a CSRF token is required
|
||||
*
|
||||
* @param SlimRequest $slimRequest
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function _isCSRFRequired($slimRequest)
|
||||
{
|
||||
if ($this->_handler->getApiToken()) {
|
||||
return false;
|
||||
}
|
||||
$server = $slimRequest->getServerParams();
|
||||
return !empty($server['REQUEST_METHOD']) && in_array($server['REQUEST_METHOD'], ['POST', 'PUT', 'DELETE']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the CSRF token is present and valid
|
||||
*
|
||||
* @param SlimRequest $slimRequest
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function _isCSRFValid($slimRequest)
|
||||
{
|
||||
$server = $slimRequest->getServerParams();
|
||||
if (empty($server['HTTP_X_CSRF_TOKEN'])) {
|
||||
return false;
|
||||
}
|
||||
$session = Application::get()->getRequest()->getSession();
|
||||
return $session && $session->getCSRFToken() === $server['HTTP_X_CSRF_TOKEN'];
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\security\authorization\internal\ApiCsrfMiddleware', '\ApiCsrfMiddleware');
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/security/authorization/internal/ApiTokenDecodingMiddleware.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class ApiTokenDecodingMiddleware
|
||||
*
|
||||
* @ingroup security_authorization
|
||||
*
|
||||
* @brief Slim middleware which decodes and validates JSON Web Tokens
|
||||
*/
|
||||
|
||||
namespace PKP\security\authorization\internal;
|
||||
|
||||
use Exception;
|
||||
use Firebase\JWT\JWT;
|
||||
use Firebase\JWT\SignatureInvalidException;
|
||||
use PKP\config\Config;
|
||||
use PKP\core\APIResponse;
|
||||
use PKP\handler\APIHandler;
|
||||
use Slim\Http\Request as SlimRequest;
|
||||
|
||||
class ApiTokenDecodingMiddleware
|
||||
{
|
||||
/** @var APIHandler $handler Reference to api handler */
|
||||
protected $_handler = null;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
*/
|
||||
public function __construct(APIHandler $handler)
|
||||
{
|
||||
$this->_handler = $handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes the request's JSON Web Token
|
||||
*
|
||||
* @param SlimRequest $slimRequest
|
||||
*
|
||||
* @return bool|string
|
||||
*/
|
||||
protected function _decode($slimRequest)
|
||||
{
|
||||
try {
|
||||
$jwt = $this->getJWT($slimRequest);
|
||||
} catch (Exception $e) {
|
||||
$request = $this->_handler->getRequest();
|
||||
return $request->getRouter()
|
||||
->handleAuthorizationFailure(
|
||||
$request,
|
||||
$e->getMessage()
|
||||
);
|
||||
}
|
||||
if (!$jwt) {
|
||||
/**
|
||||
* If we don't have a token, it's for the authentication logic to handle if it's a problem.
|
||||
*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
$secret = Config::getVar('security', 'api_key_secret', '');
|
||||
if (!$secret) {
|
||||
$request = $this->_handler->getRequest();
|
||||
return $request->getRouter()
|
||||
->handleAuthorizationFailure(
|
||||
$request,
|
||||
'api.500.apiSecretKeyMissing'
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
$apiToken = JWT::decode($jwt, $secret, ['HS256']);
|
||||
/**
|
||||
* Compatibility with old API keys
|
||||
*
|
||||
* @link https://github.com/pkp/pkp-lib/issues/6462
|
||||
*/
|
||||
if (substr($apiToken, 0, 2) === '""') {
|
||||
$apiToken = json_decode($apiToken);
|
||||
}
|
||||
$this->_handler->setApiToken($apiToken);
|
||||
} catch (Exception $e) {
|
||||
/**
|
||||
* If JWT decoding fails, it throws an 'UnexpectedValueException'.
|
||||
* If JSON decoding fails (of the JWT payload), it throws a 'DomainException'.
|
||||
* If token couldn't verified, it throws a 'SignatureInvalidException'.
|
||||
*/
|
||||
if ($e instanceof SignatureInvalidException) {
|
||||
$request = $this->_handler->getRequest();
|
||||
return $request->getRouter()
|
||||
->handleAuthorizationFailure(
|
||||
$request,
|
||||
'api.400.invalidApiToken'
|
||||
);
|
||||
}
|
||||
|
||||
if ($e instanceof \UnexpectedValueException ||
|
||||
$e instanceof \DomainException
|
||||
) {
|
||||
$request = $this->_handler->getRequest();
|
||||
return $request->getRouter()
|
||||
->handleAuthorizationFailure(
|
||||
$request,
|
||||
'api.400.tokenCouldNotBeDecoded',
|
||||
[
|
||||
'error' => $e->getMessage()
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Middleware invokable function
|
||||
*
|
||||
* @param SlimRequest $request request
|
||||
* @param APIResponse $response response
|
||||
* @param callable $next Next middleware
|
||||
*
|
||||
* @return bool|string|APIResponse
|
||||
*/
|
||||
public function __invoke($request, $response, $next)
|
||||
{
|
||||
$result = $this->_decode($request);
|
||||
if ($result !== true) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
$response = $next($request, $response);
|
||||
return $response;
|
||||
}
|
||||
|
||||
protected function getJWT(SlimRequest $slimRequest)
|
||||
{
|
||||
$authHeader = $slimRequest->getHeader('Authorization');
|
||||
|
||||
if (!count($authHeader) || empty($authHeader[0])) {
|
||||
// DEPRECATED as of 3.4.0. Use the Authorization header.
|
||||
return $slimRequest->getQueryParam('apiToken');
|
||||
}
|
||||
|
||||
// Several authorization methods may be supplied with commas between them.
|
||||
// For example: Basic basic_auth_string_here, Bearer api_key_here
|
||||
// JWT uses the Bearer scheme with an API key. Ignore the others.
|
||||
$clauses = explode(',', $authHeader[0]);
|
||||
foreach ($clauses as $clause) {
|
||||
// Split the authorization scheme and parameters and look for the Bearer scheme.
|
||||
$parts = explode(' ', trim($clause));
|
||||
if (count($parts) == 2 && $parts[0] == 'Bearer') {
|
||||
// Found bearer authorization; return the token.
|
||||
return $parts[1];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\security\authorization\internal\ApiTokenDecodingMiddleware', '\ApiTokenDecodingMiddleware');
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/**
|
||||
* @file classes/security/authorization/internal/ContextPolicy.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class ContextPolicy
|
||||
*
|
||||
* @ingroup security_authorization_internal
|
||||
*
|
||||
* @brief Basic policy that ensures availability of a context in
|
||||
* the request context and a valid user group. All context based policies
|
||||
* extend this policy.
|
||||
*/
|
||||
|
||||
namespace PKP\security\authorization\internal;
|
||||
|
||||
use PKP\security\authorization\ContextRequiredPolicy;
|
||||
use PKP\security\authorization\PolicySet;
|
||||
|
||||
class ContextPolicy extends PolicySet
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param \PKP\core\PKPRequest $request
|
||||
*/
|
||||
public function __construct($request)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
// Ensure we're in a context
|
||||
$this->addPolicy(new ContextRequiredPolicy($request, 'user.authorization.noContext'));
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\security\authorization\internal\ContextPolicy', '\ContextPolicy');
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
/**
|
||||
* @file classes/security/authorization/internal/DecisionAllowedPolicy.php
|
||||
*
|
||||
* Copyright (c) 2014-2022 Simon Fraser University
|
||||
* Copyright (c) 2000-2022 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class DecisionAllowedPolicy
|
||||
*
|
||||
* @ingroup security_authorization_internal
|
||||
*
|
||||
* @brief Checks whether a user is allowed to take the authorized decision
|
||||
* on the authorized submission. Also relies on authorized roles.
|
||||
*/
|
||||
|
||||
namespace PKP\security\authorization\internal;
|
||||
|
||||
use APP\core\Application;
|
||||
use APP\facades\Repo;
|
||||
use PKP\db\DAORegistry;
|
||||
use PKP\security\authorization\AuthorizationPolicy;
|
||||
use PKP\security\Role;
|
||||
use PKP\stageAssignment\StageAssignmentDAO;
|
||||
use PKP\user\User;
|
||||
|
||||
class DecisionAllowedPolicy extends AuthorizationPolicy
|
||||
{
|
||||
protected ?User $user;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
*/
|
||||
public function __construct(?User $user)
|
||||
{
|
||||
parent::__construct('editor.submission.workflowDecision.disallowedDecision');
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see AuthorizationPolicy::effect()
|
||||
*/
|
||||
public function effect()
|
||||
{
|
||||
if (!$this->user) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
$submission = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION);
|
||||
$decisionType = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_DECISION_TYPE);
|
||||
|
||||
$stageAssignmentDao = DAORegistry::getDAO('StageAssignmentDAO'); /** @var StageAssignmentDAO $stageAssignmentDao */
|
||||
$result = $stageAssignmentDao->getBySubmissionAndUserIdAndStageId($submission->getId(), $this->user->getId(), $submission->getData('stageId'));
|
||||
$stageAssignments = $result->toArray();
|
||||
if (empty($stageAssignments)) {
|
||||
$userRoles = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_USER_ROLES);
|
||||
$canAccessUnassignedSubmission = !empty(array_intersect([Role::ROLE_ID_SITE_ADMIN, Role::ROLE_ID_MANAGER], $userRoles));
|
||||
if ($canAccessUnassignedSubmission) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_PERMIT;
|
||||
} else {
|
||||
$this->setAdvice(self::AUTHORIZATION_ADVICE_DENY_MESSAGE, 'editor.submission.workflowDecision.noUnassignedDecisions');
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
} else {
|
||||
$isAllowed = false;
|
||||
foreach ($stageAssignments as $stageAssignment) {
|
||||
$userGroup = Repo::userGroup()->get($stageAssignment->getUserGroupId());
|
||||
if (!in_array($userGroup->getRoleId(), [Role::ROLE_ID_MANAGER, Role::ROLE_ID_SUB_EDITOR])) {
|
||||
continue;
|
||||
}
|
||||
if (Repo::decision()->isRecommendation($decisionType->getDecision()) && $stageAssignment->getRecommendOnly()) {
|
||||
$isAllowed = true;
|
||||
} elseif (!$stageAssignment->getRecommendOnly()) {
|
||||
$isAllowed = true;
|
||||
}
|
||||
|
||||
// Check whether there is a decision that a recommending role can make on the stage the submission is in.
|
||||
$recommendatorsAvailableDecisions = Repo::decision()
|
||||
->getDecisionTypesMadeByRecommendingUsers($submission->getData('stageId'));
|
||||
|
||||
// if there is any decision that the recommending role is allowed to make, check if the current decision is within the allowed ones
|
||||
if (!empty($recommendatorsAvailableDecisions)) {
|
||||
$matches = array_filter($recommendatorsAvailableDecisions, function ($decisionInArray) use ($decisionType) {
|
||||
return $decisionInArray->getDecision() === $decisionType->getDecision();
|
||||
});
|
||||
|
||||
if (!empty($matches)) {
|
||||
$isAllowed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($isAllowed) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_PERMIT;
|
||||
}
|
||||
}
|
||||
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\security\authorization\internal\DecisionAllowedPolicy', '\DecisionAllowedPolicy');
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
/**
|
||||
* @file classes/security/authorization/internal/DecisionStageValidPolicy.php
|
||||
*
|
||||
* Copyright (c) 2014-2022 Simon Fraser University
|
||||
* Copyright (c) 2000-2022 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class DecisionStageValidPolicy
|
||||
*
|
||||
* @ingroup security_authorization_internal
|
||||
*
|
||||
* @brief Checks whether the authorized submission is in the correct stage
|
||||
* to take the authorized decision
|
||||
*/
|
||||
|
||||
namespace PKP\security\authorization\internal;
|
||||
|
||||
use APP\core\Application;
|
||||
use PKP\security\authorization\AuthorizationPolicy;
|
||||
|
||||
class DecisionStageValidPolicy extends AuthorizationPolicy
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct('editor.submission.workflowDecision.invalidStage');
|
||||
}
|
||||
|
||||
/**
|
||||
* @see AuthorizationPolicy::effect()
|
||||
*/
|
||||
public function effect()
|
||||
{
|
||||
$submission = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION);
|
||||
$decisionType = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_DECISION_TYPE);
|
||||
|
||||
if ($submission->getData('stageId') === $decisionType->getStageId()) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_PERMIT;
|
||||
}
|
||||
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\security\authorization\internal\DecisionStageValidPolicy', '\DecisionStageValidPolicy');
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
/**
|
||||
* @file classes/security/authorization/internal/DecisionTypeRequiredPolicy.php
|
||||
*
|
||||
* Copyright (c) 2014-2022 Simon Fraser University
|
||||
* Copyright (c) 2000-2022 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class DecisionTypeRequiredPolicy
|
||||
*
|
||||
* @ingroup security_authorization_internal
|
||||
*
|
||||
* @brief Policy that ensures that the requested decision type is valid
|
||||
*/
|
||||
|
||||
namespace PKP\security\authorization\internal;
|
||||
|
||||
use APP\core\Application;
|
||||
use APP\facades\Repo;
|
||||
use PKP\core\PKPRequest;
|
||||
use PKP\decision\DecisionType;
|
||||
use PKP\security\authorization\AuthorizationPolicy;
|
||||
use PKP\security\authorization\DataObjectRequiredPolicy;
|
||||
|
||||
class DecisionTypeRequiredPolicy extends DataObjectRequiredPolicy
|
||||
{
|
||||
protected int $decision;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param PKPRequest $request
|
||||
* @param array $args request parameters
|
||||
* @param int $decision The decision constant to check
|
||||
*/
|
||||
public function __construct($request, &$args, int $decision)
|
||||
{
|
||||
parent::__construct($request, $args, '', 'editor.submission.workflowDecision.typeInvalid');
|
||||
$this->decision = $decision;
|
||||
}
|
||||
|
||||
//
|
||||
// Implement template methods from AuthorizationPolicy
|
||||
//
|
||||
/**
|
||||
* @see DataObjectRequiredPolicy::dataObjectEffect()
|
||||
*/
|
||||
public function dataObjectEffect()
|
||||
{
|
||||
/** @var ?DecisionType $decisionType */
|
||||
$decisionType = Repo::decision()->getDecisionType($this->decision);
|
||||
|
||||
if (!$decisionType) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
$this->addAuthorizedContextObject(Application::ASSOC_TYPE_DECISION_TYPE, $decisionType);
|
||||
|
||||
return AuthorizationPolicy::AUTHORIZATION_PERMIT;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\security\authorization\internal\DecisionTypeRequiredPolicy', '\DecisionTypeRequiredPolicy');
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
/**
|
||||
* @file classes/security/authorization/internal/PluginLevelRequiredPolicy.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class PluginLevelRequiredPolicy
|
||||
*
|
||||
* @ingroup security_authorization_internal
|
||||
*
|
||||
* @brief Class to test the plugin level.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace PKP\security\authorization\internal;
|
||||
|
||||
use APP\core\Application;
|
||||
use PKP\core\PKPRequest;
|
||||
use PKP\security\authorization\AuthorizationPolicy;
|
||||
|
||||
class PluginLevelRequiredPolicy extends AuthorizationPolicy
|
||||
{
|
||||
/** @var bool */
|
||||
public $_contextPresent;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param PKPRequest $request
|
||||
* @param bool $contextPresent
|
||||
*/
|
||||
public function __construct($request, $contextPresent)
|
||||
{
|
||||
parent::__construct('user.authorization.pluginLevel');
|
||||
$this->_contextPresent = $contextPresent;
|
||||
}
|
||||
|
||||
//
|
||||
// Implement template methods from AuthorizationPolicy
|
||||
//
|
||||
/**
|
||||
* @see AuthorizationPolicy::effect()
|
||||
*/
|
||||
public function effect()
|
||||
{
|
||||
// Get the plugin.
|
||||
$plugin = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_PLUGIN);
|
||||
if (!$plugin instanceof \PKP\plugins\Plugin) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
if (!$this->_contextPresent) { // Site context
|
||||
return $plugin->isSitePlugin() ? AuthorizationPolicy::AUTHORIZATION_PERMIT : AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
return $plugin->isSitePlugin() ? AuthorizationPolicy::AUTHORIZATION_DENY : AuthorizationPolicy::AUTHORIZATION_PERMIT;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\security\authorization\internal\PluginLevelRequiredPolicy', '\PluginLevelRequiredPolicy');
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
/**
|
||||
* @file classes/security/authorization/internal/PluginRequiredPolicy.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class PluginRequiredPolicy
|
||||
*
|
||||
* @ingroup security_authorization_internal
|
||||
*
|
||||
* @brief Class to make sure we have a valid plugin in request.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace PKP\security\authorization\internal;
|
||||
|
||||
use APP\core\Application;
|
||||
use APP\core\Request;
|
||||
use PKP\core\PKPRequest;
|
||||
use PKP\plugins\Plugin;
|
||||
use PKP\plugins\PluginRegistry;
|
||||
use PKP\security\authorization\AuthorizationPolicy;
|
||||
|
||||
class PluginRequiredPolicy extends AuthorizationPolicy
|
||||
{
|
||||
/** @var Request */
|
||||
public $_request;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param PKPRequest $request
|
||||
*/
|
||||
public function __construct($request)
|
||||
{
|
||||
parent::__construct('user.authorization.pluginRequired');
|
||||
$this->_request = $request;
|
||||
}
|
||||
|
||||
//
|
||||
// Implement template methods from AuthorizationPolicy
|
||||
//
|
||||
/**
|
||||
* @see AuthorizationPolicy::effect()
|
||||
*/
|
||||
public function effect()
|
||||
{
|
||||
// Get the plugin request data.
|
||||
$category = $this->_request->getUserVar('category');
|
||||
$pluginName = $this->_request->getUserVar('plugin');
|
||||
|
||||
// Load the plugin.
|
||||
$plugins = PluginRegistry::loadCategory($category);
|
||||
$foundPlugin = null;
|
||||
foreach ($plugins as $plugin) { /** @var Plugin $plugin */
|
||||
if ($plugin->getName() == $pluginName) {
|
||||
$foundPlugin = $plugin;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$foundPlugin instanceof Plugin) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// Add the plugin to the authorized context.
|
||||
$this->addAuthorizedContextObject(Application::ASSOC_TYPE_PLUGIN, $foundPlugin);
|
||||
return AuthorizationPolicy::AUTHORIZATION_PERMIT;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\security\authorization\internal\PluginRequiredPolicy', '\PluginRequiredPolicy');
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
/**
|
||||
* @file classes/security/authorization/internal/PublicationCanBeEditedPolicy.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class PublicationCanBeEditedPolicy
|
||||
*
|
||||
* @ingroup security_authorization_internal
|
||||
*
|
||||
* @brief Policy to ensure the authorized publication is editable by the given user
|
||||
*
|
||||
*/
|
||||
|
||||
namespace PKP\security\authorization\internal;
|
||||
|
||||
use APP\core\Application;
|
||||
use APP\core\Request;
|
||||
use APP\facades\Repo;
|
||||
use APP\submission\Submission;
|
||||
use PKP\security\authorization\AuthorizationPolicy;
|
||||
use PKP\security\Role;
|
||||
|
||||
class PublicationCanBeEditedPolicy extends AuthorizationPolicy
|
||||
{
|
||||
/** @var \User */
|
||||
private $_currentUser;
|
||||
|
||||
public function __construct(Request $request, string $message)
|
||||
{
|
||||
parent::__construct($message);
|
||||
|
||||
$currentUser = $request->getUser();
|
||||
$this->_currentUser = $currentUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see AuthorizationPolicy::effect()
|
||||
*/
|
||||
public function effect()
|
||||
{
|
||||
$submission = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION); /** @var Submission $submission */
|
||||
|
||||
// Prevent users from editing publications if they do not have permission. Except for admins.
|
||||
$userRoles = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_USER_ROLES);
|
||||
if (in_array(Role::ROLE_ID_SITE_ADMIN, $userRoles) || Repo::submission()->canEditPublication($submission->getId(), $this->_currentUser->getId())) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_PERMIT;
|
||||
}
|
||||
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/**
|
||||
* @file classes/security/authorization/internal/PublicationIsSubmissionPolicy.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class PublicationIsSubmissionPolicy
|
||||
*
|
||||
* @ingroup security_authorization_internal
|
||||
*
|
||||
* @brief Policy to ensure the authorized publication is related to the authorized submission.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace PKP\security\authorization\internal;
|
||||
|
||||
use APP\core\Application;
|
||||
use PKP\security\authorization\AuthorizationPolicy;
|
||||
|
||||
class PublicationIsSubmissionPolicy extends AuthorizationPolicy
|
||||
{
|
||||
/**
|
||||
* @see AuthorizationPolicy::effect()
|
||||
*/
|
||||
public function effect()
|
||||
{
|
||||
$submission = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION);
|
||||
$publication = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_PUBLICATION);
|
||||
|
||||
if ($submission && $publication && $submission->getId() === $publication->getData('submissionId')) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_PERMIT;
|
||||
}
|
||||
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\security\authorization\internal\PublicationIsSubmissionPolicy', '\PublicationIsSubmissionPolicy');
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
/**
|
||||
* @file classes/security/authorization/internal/PublicationRequiredPolicy.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class PublicationRequiredPolicy
|
||||
*
|
||||
* @ingroup security_authorization_internal
|
||||
*
|
||||
* @brief Policy that ensures that the request contains a valid publication id.
|
||||
*/
|
||||
|
||||
namespace PKP\security\authorization\internal;
|
||||
|
||||
use APP\core\Application;
|
||||
use APP\facades\Repo;
|
||||
use PKP\core\PKPRequest;
|
||||
use PKP\security\authorization\AuthorizationPolicy;
|
||||
use PKP\security\authorization\DataObjectRequiredPolicy;
|
||||
|
||||
class PublicationRequiredPolicy extends DataObjectRequiredPolicy
|
||||
{
|
||||
protected ?string $publicationParameterName;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param PKPRequest $request
|
||||
* @param array $args request parameters
|
||||
* @param ?string $publicationParameterName the request parameter we expect
|
||||
* the submission id in. Pass null to look for the current publication in an authorized
|
||||
* submission object instead.
|
||||
* @param null|mixed $operations
|
||||
*/
|
||||
public function __construct($request, &$args, $publicationParameterName = null, $operations = null)
|
||||
{
|
||||
parent::__construct($request, $args, $publicationParameterName, 'user.authorization.invalidPublication', $operations);
|
||||
$this->publicationParameterName = $publicationParameterName;
|
||||
|
||||
$callOnDeny = [$request->getDispatcher(), 'handle404', []];
|
||||
$this->setAdvice(
|
||||
AuthorizationPolicy::AUTHORIZATION_ADVICE_CALL_ON_DENY,
|
||||
$callOnDeny
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// Implement template methods from AuthorizationPolicy
|
||||
//
|
||||
/**
|
||||
* @see DataObjectRequiredPolicy::dataObjectEffect()
|
||||
*/
|
||||
public function dataObjectEffect()
|
||||
{
|
||||
// Get the publication id from the policy or, if
|
||||
// no parameter name is passed, look for the current
|
||||
// publication in an authorized submission object
|
||||
if ($this->publicationParameterName) {
|
||||
$publication = Repo::publication()->get((int) $this->getDataObjectId());
|
||||
} else {
|
||||
$submission = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION);
|
||||
if ($submission) {
|
||||
$publication = $submission->getCurrentPublication();
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($publication)) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// Save the publication to the authorization context.
|
||||
$this->addAuthorizedContextObject(Application::ASSOC_TYPE_PUBLICATION, $publication);
|
||||
return AuthorizationPolicy::AUTHORIZATION_PERMIT;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\security\authorization\internal\PublicationRequiredPolicy', '\PublicationRequiredPolicy');
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
/**
|
||||
* @file classes/security/authorization/internal/QueryAssignedToUserAccessPolicy.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class QueryAssignedToUserAccessPolicy
|
||||
*
|
||||
* @ingroup security_authorization_internal
|
||||
*
|
||||
* @brief Class to control access to a query that is assigned to the current user
|
||||
*
|
||||
*/
|
||||
|
||||
namespace PKP\security\authorization\internal;
|
||||
|
||||
use APP\core\Application;
|
||||
use PKP\core\PKPRequest;
|
||||
use PKP\db\DAORegistry;
|
||||
use PKP\query\QueryDAO;
|
||||
use PKP\security\authorization\AuthorizationPolicy;
|
||||
use PKP\security\Role;
|
||||
|
||||
class QueryAssignedToUserAccessPolicy extends AuthorizationPolicy
|
||||
{
|
||||
/** @var PKPRequest */
|
||||
public $_request;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param PKPRequest $request
|
||||
*/
|
||||
public function __construct($request)
|
||||
{
|
||||
parent::__construct('user.authorization.submissionQuery');
|
||||
$this->_request = $request;
|
||||
}
|
||||
|
||||
//
|
||||
// Implement template methods from AuthorizationPolicy
|
||||
//
|
||||
/**
|
||||
* @see AuthorizationPolicy::effect()
|
||||
*/
|
||||
public function effect()
|
||||
{
|
||||
// A query should already be in the context.
|
||||
$query = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_QUERY);
|
||||
if (!$query instanceof \PKP\query\Query) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// Check that there is a currently logged in user.
|
||||
$user = $this->_request->getUser();
|
||||
if (!$user instanceof \PKP\user\User) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// Determine if the query is assigned to the user.
|
||||
$queryDao = DAORegistry::getDAO('QueryDAO'); /** @var QueryDAO $queryDao */
|
||||
if ($queryDao->getParticipantIds($query->getId(), $user->getId())) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_PERMIT;
|
||||
}
|
||||
|
||||
// Managers are allowed to access discussions they are not participants in
|
||||
// as long as they have Manager-level access to the workflow stage
|
||||
$accessibleWorkflowStages = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ACCESSIBLE_WORKFLOW_STAGES);
|
||||
$managerAssignments = array_intersect([Role::ROLE_ID_MANAGER, Role::ROLE_ID_SITE_ADMIN], $accessibleWorkflowStages[$query->getStageId()] ?? []);
|
||||
if (!empty($managerAssignments)) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_PERMIT;
|
||||
}
|
||||
|
||||
// Otherwise, deny.
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\security\authorization\internal\QueryAssignedToUserAccessPolicy', '\QueryAssignedToUserAccessPolicy');
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
/**
|
||||
* @file classes/security/authorization/internal/QueryRequiredPolicy.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class QueryRequiredPolicy
|
||||
*
|
||||
* @ingroup security_authorization_internal
|
||||
*
|
||||
* @brief Policy that ensures that the request contains a valid query.
|
||||
*/
|
||||
|
||||
namespace PKP\security\authorization\internal;
|
||||
|
||||
use APP\core\Application;
|
||||
use APP\submission\Submission;
|
||||
use PKP\core\PKPRequest;
|
||||
use PKP\db\DAORegistry;
|
||||
use PKP\query\Query;
|
||||
use PKP\query\QueryDAO;
|
||||
use PKP\security\authorization\AuthorizationPolicy;
|
||||
use PKP\security\authorization\DataObjectRequiredPolicy;
|
||||
|
||||
class QueryRequiredPolicy extends DataObjectRequiredPolicy
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param PKPRequest $request
|
||||
* @param array $args request parameters
|
||||
* @param null|mixed $operations
|
||||
*/
|
||||
public function __construct($request, &$args, $parameterName = 'queryId', $operations = null)
|
||||
{
|
||||
parent::__construct($request, $args, $parameterName, 'user.authorization.invalidQuery', $operations);
|
||||
}
|
||||
|
||||
//
|
||||
// Implement template methods from AuthorizationPolicy
|
||||
//
|
||||
/**
|
||||
* @see DataObjectRequiredPolicy::dataObjectEffect()
|
||||
*/
|
||||
public function dataObjectEffect()
|
||||
{
|
||||
$queryId = (int)$this->getDataObjectId();
|
||||
if (!$queryId) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// Make sure the query belongs to the submission.
|
||||
$queryDao = DAORegistry::getDAO('QueryDAO'); /** @var QueryDAO $queryDao */
|
||||
$query = $queryDao->getById($queryId);
|
||||
if (!$query instanceof Query) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
switch ($query->getAssocType()) {
|
||||
case Application::ASSOC_TYPE_SUBMISSION:
|
||||
$submission = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION);
|
||||
if (!$submission instanceof Submission) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
if ($query->getAssocId() != $submission->getId()) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// Save the query to the authorization context.
|
||||
$this->addAuthorizedContextObject(Application::ASSOC_TYPE_QUERY, $query);
|
||||
return AuthorizationPolicy::AUTHORIZATION_PERMIT;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\security\authorization\internal\QueryRequiredPolicy', '\QueryRequiredPolicy');
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
/**
|
||||
* @file classes/security/authorization/internal/QueryUserAccessibleWorkflowStageRequiredPolicy.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class QueryUserAccessibleWorkflowStageRequiredPolicy
|
||||
*
|
||||
* @ingroup security_authorization_internal
|
||||
*
|
||||
* @brief Policy to extend access to queries to assigned reviewers.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace PKP\security\authorization\internal;
|
||||
|
||||
use APP\core\Application;
|
||||
use PKP\db\DAORegistry;
|
||||
use PKP\security\authorization\AuthorizationPolicy;
|
||||
use PKP\security\Role;
|
||||
use PKP\submission\reviewAssignment\ReviewAssignmentDAO;
|
||||
|
||||
class QueryUserAccessibleWorkflowStageRequiredPolicy extends UserAccessibleWorkflowStageRequiredPolicy
|
||||
{
|
||||
//
|
||||
// Private helper methods.
|
||||
//
|
||||
/**
|
||||
* @see AuthorizationPolicy::effect()
|
||||
*/
|
||||
public function effect()
|
||||
{
|
||||
$result = parent::effect();
|
||||
if ($result === AuthorizationPolicy::AUTHORIZATION_PERMIT) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
if (!in_array(Role::ROLE_ID_REVIEWER, $this->getAuthorizedContextObject(Application::ASSOC_TYPE_USER_ROLES) ?? [])) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
$submission = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION);
|
||||
$reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */
|
||||
$reviewAssignments = $reviewAssignmentDao->getBySubmissionId($submission->getId());
|
||||
foreach ($reviewAssignments as $reviewAssignment) {
|
||||
if ($reviewAssignment->getReviewerId() == $this->_request->getUser()->getId()) {
|
||||
$accessibleWorkflowStages = (array) $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ACCESSIBLE_WORKFLOW_STAGES);
|
||||
$accessibleWorkflowStages[WORKFLOW_STAGE_ID_INTERNAL_REVIEW] = array_merge(
|
||||
$accessibleWorkflowStages[WORKFLOW_STAGE_ID_INTERNAL_REVIEW] ?? [],
|
||||
[Role::ROLE_ID_REVIEWER]
|
||||
);
|
||||
$accessibleWorkflowStages[WORKFLOW_STAGE_ID_EXTERNAL_REVIEW] = array_merge(
|
||||
$accessibleWorkflowStages[WORKFLOW_STAGE_ID_EXTERNAL_REVIEW] ?? [],
|
||||
[Role::ROLE_ID_REVIEWER]
|
||||
);
|
||||
$this->addAuthorizedContextObject(Application::ASSOC_TYPE_ACCESSIBLE_WORKFLOW_STAGES, $accessibleWorkflowStages);
|
||||
return AuthorizationPolicy::AUTHORIZATION_PERMIT;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\security\authorization\internal\QueryUserAccessibleWorkflowStageRequiredPolicy', '\QueryUserAccessibleWorkflowStageRequiredPolicy');
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
/**
|
||||
* @file classes/security/authorization/internal/RepresentationRequiredPolicy.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class RepresentationRequiredPolicy
|
||||
*
|
||||
* @ingroup security_authorization_internal
|
||||
*
|
||||
* @brief Policy that ensures that the request contains a valid representation.
|
||||
*/
|
||||
|
||||
namespace PKP\security\authorization\internal;
|
||||
|
||||
use APP\core\Application;
|
||||
use APP\publication\Publication;
|
||||
use APP\submission\Submission;
|
||||
use PKP\core\PKPRequest;
|
||||
use PKP\security\authorization\AuthorizationPolicy;
|
||||
use PKP\security\authorization\DataObjectRequiredPolicy;
|
||||
use PKP\submission\Representation;
|
||||
|
||||
class RepresentationRequiredPolicy extends DataObjectRequiredPolicy
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param PKPRequest $request
|
||||
* @param array $args request parameters
|
||||
* @param null|mixed $operations
|
||||
*/
|
||||
public function __construct($request, &$args, $parameterName = 'representationId', $operations = null)
|
||||
{
|
||||
parent::__construct($request, $args, $parameterName, 'user.authorization.invalidRepresentation', $operations);
|
||||
}
|
||||
|
||||
//
|
||||
// Implement template methods from AuthorizationPolicy
|
||||
//
|
||||
/**
|
||||
* @see DataObjectRequiredPolicy::dataObjectEffect()
|
||||
*/
|
||||
public function dataObjectEffect()
|
||||
{
|
||||
$representationId = (int)$this->getDataObjectId();
|
||||
if (!$representationId) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// Need a valid submission in request.
|
||||
$submission = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION);
|
||||
if (!$submission instanceof Submission) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// Need a valid publication in request
|
||||
$publication = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_PUBLICATION);
|
||||
if (!$publication instanceof Publication) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// Make sure the representation belongs to the submission.
|
||||
$representationDao = Application::getRepresentationDAO();
|
||||
$representation = $representationDao->getById($representationId, $publication->getId());
|
||||
if (!$representation instanceof Representation) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// Save the representation to the authorization context.
|
||||
$this->addAuthorizedContextObject(Application::ASSOC_TYPE_REPRESENTATION, $representation);
|
||||
return AuthorizationPolicy::AUTHORIZATION_PERMIT;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\security\authorization\internal\RepresentationRequiredPolicy', '\RepresentationRequiredPolicy');
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
/**
|
||||
* @file classes/security/authorization/internal/RepresentationUploadAccessPolicy.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class RepresentationUploadAccessPolicy
|
||||
*
|
||||
* @ingroup security_authorization_internal
|
||||
*
|
||||
* @brief Policy that checks whether a file can be uploaded to a representation.
|
||||
* It checks whether the user is allowed to access the representation file stage,
|
||||
* whether the representation exists, whether it matches the authorized submission,
|
||||
* and whether it is not part of a published publication. This policy expects an
|
||||
* authorized submission in the authorization context.
|
||||
*/
|
||||
|
||||
namespace PKP\security\authorization\internal;
|
||||
|
||||
use APP\core\Application;
|
||||
use APP\facades\Repo;
|
||||
use PKP\core\PKPRequest;
|
||||
use PKP\security\authorization\AuthorizationPolicy;
|
||||
use PKP\security\authorization\DataObjectRequiredPolicy;
|
||||
use PKP\submission\PKPSubmission;
|
||||
use PKP\submissionFile\SubmissionFile;
|
||||
|
||||
class RepresentationUploadAccessPolicy extends DataObjectRequiredPolicy
|
||||
{
|
||||
/** @var int */
|
||||
public $_representationId;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param PKPRequest $request
|
||||
* @param array $args request parameters
|
||||
* @param int $representationId
|
||||
*/
|
||||
public function __construct($request, &$args, $representationId)
|
||||
{
|
||||
parent::__construct($request, $args, 'user.authorization.accessDenied');
|
||||
$this->_representationId = $representationId;
|
||||
}
|
||||
|
||||
//
|
||||
// Implement template methods from AuthorizationPolicy
|
||||
//
|
||||
/**
|
||||
* @see DataObjectRequiredPolicy::dataObjectEffect()
|
||||
*/
|
||||
public function dataObjectEffect()
|
||||
{
|
||||
$assignedFileStages = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ACCESSIBLE_FILE_STAGES);
|
||||
if (empty($assignedFileStages) || !in_array(SubmissionFile::SUBMISSION_FILE_PROOF, $assignedFileStages)) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
if (empty($this->_representationId)) {
|
||||
$this->setAdvice(AuthorizationPolicy::AUTHORIZATION_ADVICE_DENY_MESSAGE, 'user.authorization.representationNotFound');
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
$representationDao = Application::get()->getRepresentationDAO();
|
||||
$representation = $representationDao->getById($this->_representationId);
|
||||
|
||||
if (!$representation) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
$submission = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION);
|
||||
if (!$submission) {
|
||||
$this->setAdvice(AuthorizationPolicy::AUTHORIZATION_ADVICE_DENY_MESSAGE, 'user.authorization.invalidSubmission');
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
$publication = Repo::publication()->get($representation->getData('publicationId'));
|
||||
if (!$publication) {
|
||||
$this->setAdvice(AuthorizationPolicy::AUTHORIZATION_ADVICE_DENY_MESSAGE, 'galley.publicationNotFound');
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// Publication and submission must match
|
||||
if ($publication->getData('submissionId') !== $submission->getId()) {
|
||||
$this->setAdvice(AuthorizationPolicy::AUTHORIZATION_ADVICE_DENY_MESSAGE, 'user.authorization.invalidPublication');
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// Representations can not be modified on published publications
|
||||
if ($publication->getData('status') === PKPSubmission::STATUS_PUBLISHED) {
|
||||
$this->setAdvice(AuthorizationPolicy::AUTHORIZATION_ADVICE_DENY_MESSAGE, 'galley.editPublishedDisabled');
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
$this->addAuthorizedContextObject(Application::ASSOC_TYPE_REPRESENTATION, $representation);
|
||||
|
||||
return AuthorizationPolicy::AUTHORIZATION_PERMIT;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\security\authorization\internal\RepresentationUploadAccessPolicy', '\RepresentationUploadAccessPolicy');
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
/**
|
||||
* @file classes/security/authorization/internal/ReviewAssignmentAccessPolicy.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class ReviewAssignmentAccessPolicy
|
||||
*
|
||||
* @ingroup security_authorization_internal
|
||||
*
|
||||
* @brief Class to control access to a submission based on whether the user is an assigned reviewer.
|
||||
*
|
||||
* NB: This policy expects a previously authorized submission in the
|
||||
* authorization context.
|
||||
*/
|
||||
|
||||
namespace PKP\security\authorization\internal;
|
||||
|
||||
use APP\core\Application;
|
||||
use APP\submission\Submission;
|
||||
use PKP\core\PKPRequest;
|
||||
use PKP\db\DAORegistry;
|
||||
use PKP\security\authorization\AuthorizationPolicy;
|
||||
use PKP\submission\reviewAssignment\ReviewAssignmentDAO;
|
||||
use PKP\user\User;
|
||||
|
||||
class ReviewAssignmentAccessPolicy extends AuthorizationPolicy
|
||||
{
|
||||
/** @var PKPRequest */
|
||||
public $_request;
|
||||
|
||||
/** @var bool */
|
||||
public $_permitDeclined;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param PKPRequest $request
|
||||
* @param bool $permitDeclined True if declined or cancelled reviews are acceptable.
|
||||
*/
|
||||
public function __construct($request, $permitDeclined = false)
|
||||
{
|
||||
parent::__construct('user.authorization.submissionReviewer');
|
||||
$this->_request = $request;
|
||||
$this->_permitDeclined = $permitDeclined;
|
||||
}
|
||||
|
||||
//
|
||||
// Implement template methods from AuthorizationPolicy
|
||||
//
|
||||
/**
|
||||
* @see AuthorizationPolicy::effect()
|
||||
*/
|
||||
public function effect()
|
||||
{
|
||||
// Get the user
|
||||
$user = $this->_request->getUser();
|
||||
if (!$user instanceof User) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// Get the submission
|
||||
$submission = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION);
|
||||
if (!$submission instanceof Submission) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// Check if a review assignment exists between the submission and the user
|
||||
$reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */
|
||||
$reviewAssignment = $reviewAssignmentDao->getLastReviewRoundReviewAssignmentByReviewer($submission->getId(), $user->getId());
|
||||
|
||||
// Ensure a valid review assignment was fetched from the database
|
||||
if (!($reviewAssignment instanceof \PKP\submission\reviewAssignment\ReviewAssignment)) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// If the assignment has been cancelled, deny access.
|
||||
if ($reviewAssignment->getCancelled()) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// Ensure that the assignment isn't declined, unless that's permitted
|
||||
if (!$this->_permitDeclined && $reviewAssignment->getDeclined()) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// Save the review assignment to the authorization context.
|
||||
$this->addAuthorizedContextObject(Application::ASSOC_TYPE_REVIEW_ASSIGNMENT, $reviewAssignment);
|
||||
return AuthorizationPolicy::AUTHORIZATION_PERMIT;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\security\authorization\internal\ReviewAssignmentAccessPolicy', '\ReviewAssignmentAccessPolicy');
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
/**
|
||||
* @file classes/security/authorization/internal/ReviewAssignmentRequiredPolicy.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class ReviewAssignmentRequiredPolicy
|
||||
*
|
||||
* @ingroup security_authorization_internal
|
||||
*
|
||||
* @brief Policy that ensures that the request contains a valid review assignment.
|
||||
*/
|
||||
|
||||
namespace PKP\security\authorization\internal;
|
||||
|
||||
use APP\core\Application;
|
||||
use APP\submission\Submission;
|
||||
use PKP\core\PKPRequest;
|
||||
use PKP\db\DAORegistry;
|
||||
use PKP\security\authorization\AuthorizationPolicy;
|
||||
use PKP\security\authorization\DataObjectRequiredPolicy;
|
||||
use PKP\submission\reviewAssignment\ReviewAssignmentDAO;
|
||||
|
||||
class ReviewAssignmentRequiredPolicy extends DataObjectRequiredPolicy
|
||||
{
|
||||
/** @var array Allowed review methods */
|
||||
public $_reviewMethods = [];
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param PKPRequest $request
|
||||
* @param array $args request parameters
|
||||
* @param string $parameterName the request parameter we
|
||||
* expect the submission id in.
|
||||
* @param array|string $operations either a single operation or a list of operations that
|
||||
* this policy is targeting.
|
||||
* @param array $reviewMethods limit the policy to specific review methods
|
||||
*/
|
||||
public function __construct($request, &$args, $parameterName = 'reviewAssignmentId', $operations = null, $reviewMethods = null)
|
||||
{
|
||||
parent::__construct($request, $args, $parameterName, 'user.authorization.invalidReviewAssignment', $operations);
|
||||
$this->_reviewMethods = $reviewMethods;
|
||||
}
|
||||
|
||||
//
|
||||
// Implement template methods from AuthorizationPolicy
|
||||
//
|
||||
/**
|
||||
* @see DataObjectRequiredPolicy::dataObjectEffect()
|
||||
*/
|
||||
public function dataObjectEffect()
|
||||
{
|
||||
$reviewId = (int)$this->getDataObjectId();
|
||||
if (!$reviewId) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
$reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */
|
||||
$reviewAssignment = $reviewAssignmentDao->getById($reviewId);
|
||||
if (!($reviewAssignment instanceof \PKP\submission\reviewAssignment\ReviewAssignment)) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// If reviewMethods is defined, check that the assignment uses the defined method(s)
|
||||
if ($this->_reviewMethods) {
|
||||
if (!in_array($reviewAssignment->getReviewMethod(), $this->_reviewMethods)) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that the review assignment actually belongs to the
|
||||
// authorized submission.
|
||||
$submission = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION);
|
||||
assert($submission instanceof Submission);
|
||||
if ($reviewAssignment->getSubmissionId() != $submission->getId()) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// Ensure that the review assignment is for this workflow stage
|
||||
$stageId = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_WORKFLOW_STAGE);
|
||||
if ($reviewAssignment->getStageId() != $stageId) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// Save the review Assignment to the authorization context.
|
||||
$this->addAuthorizedContextObject(Application::ASSOC_TYPE_REVIEW_ASSIGNMENT, $reviewAssignment);
|
||||
return AuthorizationPolicy::AUTHORIZATION_PERMIT;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\security\authorization\internal\ReviewAssignmentRequiredPolicy', '\ReviewAssignmentRequiredPolicy');
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
/**
|
||||
* @file classes/security/authorization/internal/ReviewRoundRequiredPolicy.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class ReviewRoundRequiredPolicy
|
||||
*
|
||||
* @ingroup security_authorization_internal
|
||||
*
|
||||
* @brief Policy that ensures that the request contains a valid review round.
|
||||
*/
|
||||
|
||||
namespace PKP\security\authorization\internal;
|
||||
|
||||
use APP\core\Application;
|
||||
use PKP\core\PKPRequest;
|
||||
use PKP\db\DAORegistry;
|
||||
use PKP\security\authorization\AuthorizationPolicy;
|
||||
use PKP\security\authorization\DataObjectRequiredPolicy;
|
||||
use PKP\submission\reviewRound\ReviewRound;
|
||||
use PKP\submission\reviewRound\ReviewRoundDAO;
|
||||
|
||||
class ReviewRoundRequiredPolicy extends DataObjectRequiredPolicy
|
||||
{
|
||||
/** @var int Review round id. */
|
||||
public $_reviewRoundId;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param PKPRequest $request
|
||||
* @param array $args request parameters
|
||||
* @param string $parameterName the request parameter we expect
|
||||
* the submission id in.
|
||||
* @param array $operations Optional list of operations for which this check takes effect. If specified, operations outside this set will not be checked against this policy.
|
||||
* @param int $reviewRoundId Optionally pass the review round id directly. If passed, the $parameterName will be ignored.
|
||||
*/
|
||||
public function __construct($request, &$args, $parameterName = 'reviewRoundId', $operations = null, $reviewRoundId = null)
|
||||
{
|
||||
parent::__construct($request, $args, $parameterName, 'user.authorization.invalidReviewRound', $operations);
|
||||
if ($reviewRoundId) {
|
||||
$this->_reviewRoundId = $reviewRoundId;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Implement template methods from AuthorizationPolicy
|
||||
//
|
||||
/**
|
||||
* @see DataObjectRequiredPolicy::dataObjectEffect()
|
||||
*/
|
||||
public function dataObjectEffect()
|
||||
{
|
||||
// Get the review round id.
|
||||
if (!$this->_reviewRoundId) {
|
||||
$this->_reviewRoundId = $this->getDataObjectId();
|
||||
}
|
||||
if ($this->_reviewRoundId === false) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// Validate the review round id.
|
||||
$reviewRoundDao = DAORegistry::getDAO('ReviewRoundDAO'); /** @var ReviewRoundDAO $reviewRoundDao */
|
||||
$reviewRound = $reviewRoundDao->getById($this->_reviewRoundId);
|
||||
if (!$reviewRound instanceof ReviewRound) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// Ensure that the review round actually belongs to the
|
||||
// authorized submission.
|
||||
$submission = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION);
|
||||
if ($reviewRound->getSubmissionId() != $submission->getId()) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// Ensure that the review round is for this workflow stage
|
||||
$stageId = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_WORKFLOW_STAGE);
|
||||
if ($reviewRound->getStageId() != $stageId) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// Save the review round to the authorization context.
|
||||
$this->addAuthorizedContextObject(Application::ASSOC_TYPE_REVIEW_ROUND, $reviewRound);
|
||||
return AuthorizationPolicy::AUTHORIZATION_PERMIT;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\security\authorization\internal\ReviewRoundRequiredPolicy', '\ReviewRoundRequiredPolicy');
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
/**
|
||||
* @file classes/security/authorization/internal/SubmissionAuthorPolicy.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class SubmissionAuthorPolicy
|
||||
*
|
||||
* @ingroup security_authorization_internal
|
||||
*
|
||||
* @brief Class to control access to a submission based on authorship.
|
||||
*
|
||||
* NB: This policy expects a previously authorized submission in the
|
||||
* authorization context.
|
||||
*/
|
||||
|
||||
namespace PKP\security\authorization\internal;
|
||||
|
||||
use APP\core\Application;
|
||||
use APP\facades\Repo;
|
||||
use APP\submission\Submission;
|
||||
use PKP\core\PKPApplication;
|
||||
use PKP\core\PKPRequest;
|
||||
use PKP\security\authorization\AuthorizationPolicy;
|
||||
use PKP\security\Role;
|
||||
use PKP\user\User;
|
||||
|
||||
class SubmissionAuthorPolicy extends AuthorizationPolicy
|
||||
{
|
||||
/** @var PKPRequest */
|
||||
public $_request;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param PKPRequest $request
|
||||
*/
|
||||
public function __construct($request)
|
||||
{
|
||||
parent::__construct('user.authorization.submissionAuthor');
|
||||
$this->_request = $request;
|
||||
}
|
||||
|
||||
//
|
||||
// Implement template methods from AuthorizationPolicy
|
||||
//
|
||||
/**
|
||||
* @see AuthorizationPolicy::effect()
|
||||
*/
|
||||
public function effect()
|
||||
{
|
||||
// Get the user
|
||||
$user = $this->_request->getUser();
|
||||
if (!$user instanceof User) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// Get the submission
|
||||
$submission = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION);
|
||||
if (!$submission instanceof Submission) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
$context = $this->_request->getContext();
|
||||
|
||||
// Check authorship of the submission. Any ROLE_ID_AUTHOR assignment will do.
|
||||
$accessibleWorkflowStages = Repo::user()->getAccessibleWorkflowStages(
|
||||
$user->getId(),
|
||||
$context->getId(),
|
||||
$submission,
|
||||
$this->getAuthorizedContextObject(PKPApplication::ASSOC_TYPE_USER_ROLES)
|
||||
);
|
||||
|
||||
if (empty($accessibleWorkflowStages)) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
foreach ($accessibleWorkflowStages as $roles) {
|
||||
if (in_array(Role::ROLE_ID_AUTHOR, $roles)) {
|
||||
$this->addAuthorizedContextObject(Application::ASSOC_TYPE_ACCESSIBLE_WORKFLOW_STAGES, $accessibleWorkflowStages);
|
||||
return AuthorizationPolicy::AUTHORIZATION_PERMIT;
|
||||
}
|
||||
}
|
||||
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\security\authorization\internal\SubmissionAuthorPolicy', '\SubmissionAuthorPolicy');
|
||||
}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
/**
|
||||
* @file classes/security/authorization/internal/SubmissionFileAssignedQueryAccessPolicy.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class SubmissionFileAssignedQueryAccessPolicy
|
||||
*
|
||||
* @ingroup security_authorization_internal
|
||||
*
|
||||
* @brief Submission file policy to check if the current user is a participant
|
||||
* in a query the file belongs to.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace PKP\security\authorization\internal;
|
||||
|
||||
use APP\core\Application;
|
||||
use PKP\db\DAORegistry;
|
||||
use PKP\note\NoteDAO;
|
||||
use PKP\query\QueryDAO;
|
||||
use PKP\security\authorization\AuthorizationPolicy;
|
||||
|
||||
class SubmissionFileAssignedQueryAccessPolicy extends SubmissionFileBaseAccessPolicy
|
||||
{
|
||||
//
|
||||
// Implement template methods from AuthorizationPolicy
|
||||
//
|
||||
/**
|
||||
* @see AuthorizationPolicy::effect()
|
||||
*/
|
||||
public function effect()
|
||||
{
|
||||
$request = $this->getRequest();
|
||||
|
||||
// Get the user
|
||||
$user = $request->getUser();
|
||||
if (!$user instanceof \PKP\user\User) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// Get the submission file
|
||||
$submissionFile = $this->getSubmissionFile($request);
|
||||
if (!$submissionFile instanceof \PKP\submissionFile\SubmissionFile) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// Check if it's associated with a note.
|
||||
if ($submissionFile->getData('assocType') != Application::ASSOC_TYPE_NOTE) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
$noteDao = DAORegistry::getDAO('NoteDAO'); /** @var NoteDAO $noteDao */
|
||||
$note = $noteDao->getById($submissionFile->getData('assocId'));
|
||||
if (!$note instanceof \PKP\note\Note) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
if ($note->getAssocType() != Application::ASSOC_TYPE_QUERY) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
$queryDao = DAORegistry::getDAO('QueryDAO'); /** @var QueryDAO $queryDao */
|
||||
$query = $queryDao->getById($note->getAssocId());
|
||||
if (!$query) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
if ($queryDao->getParticipantIds($note->getAssocId(), $user->getId())) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_PERMIT;
|
||||
}
|
||||
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\security\authorization\internal\SubmissionFileAssignedQueryAccessPolicy', '\SubmissionFileAssignedQueryAccessPolicy');
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
/**
|
||||
* @file classes/security/authorization/internal/SubmissionFileAssignedReviewerAccessPolicy.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class SubmissionFileAssignedReviewerAccessPolicy
|
||||
*
|
||||
* @ingroup security_authorization_internal
|
||||
*
|
||||
* @brief Submission file policy to check if the current user is an assigned
|
||||
* reviewer of the file.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace PKP\security\authorization\internal;
|
||||
|
||||
use APP\core\Application;
|
||||
use Exception;
|
||||
use PKP\db\DAORegistry;
|
||||
use PKP\security\authorization\AuthorizationPolicy;
|
||||
use PKP\submission\reviewAssignment\ReviewAssignmentDAO;
|
||||
use PKP\submission\ReviewFilesDAO;
|
||||
use PKP\submissionFile\SubmissionFile;
|
||||
|
||||
class SubmissionFileAssignedReviewerAccessPolicy extends SubmissionFileBaseAccessPolicy
|
||||
{
|
||||
//
|
||||
// Implement template methods from AuthorizationPolicy
|
||||
//
|
||||
/**
|
||||
* @see AuthorizationPolicy::effect()
|
||||
*/
|
||||
public function effect()
|
||||
{
|
||||
$request = $this->getRequest();
|
||||
|
||||
// Get the user
|
||||
$user = $request->getUser();
|
||||
if (!$user instanceof \PKP\user\User) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// Get the submission file
|
||||
$submissionFile = $this->getSubmissionFile($request);
|
||||
if (!$submissionFile instanceof SubmissionFile) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
$context = $request->getContext();
|
||||
$reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */
|
||||
$reviewAssignments = $reviewAssignmentDao->getByUserId($user->getId());
|
||||
$reviewFilesDao = DAORegistry::getDAO('ReviewFilesDAO'); /** @var ReviewFilesDAO $reviewFilesDao */
|
||||
foreach ($reviewAssignments as $reviewAssignment) {
|
||||
if ($context->getData('restrictReviewerFileAccess') && !$reviewAssignment->getDateConfirmed()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Determine which file stage the requested file should be in.
|
||||
$reviewFileStage = null;
|
||||
switch ($reviewAssignment->getStageId()) {
|
||||
case WORKFLOW_STAGE_ID_INTERNAL_REVIEW:
|
||||
$reviewFileStage = SubmissionFile::SUBMISSION_FILE_INTERNAL_REVIEW_FILE;
|
||||
break;
|
||||
case WORKFLOW_STAGE_ID_EXTERNAL_REVIEW:
|
||||
$reviewFileStage = SubmissionFile::SUBMISSION_FILE_REVIEW_FILE;
|
||||
break;
|
||||
default: throw new Exception('Unknown review workflow stage ID!');
|
||||
}
|
||||
|
||||
if (
|
||||
$submissionFile->getData('submissionId') == $reviewAssignment->getSubmissionId() &&
|
||||
$submissionFile->getData('fileStage') == $reviewFileStage &&
|
||||
$reviewFilesDao->check($reviewAssignment->getId(), $submissionFile->getId())
|
||||
) {
|
||||
$this->addAuthorizedContextObject(Application::ASSOC_TYPE_REVIEW_ASSIGNMENT, $reviewAssignment);
|
||||
return AuthorizationPolicy::AUTHORIZATION_PERMIT;
|
||||
}
|
||||
}
|
||||
|
||||
// If a pass condition wasn't found above, deny access.
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\security\authorization\internal\SubmissionFileAssignedReviewerAccessPolicy', '\SubmissionFileAssignedReviewerAccessPolicy');
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
/**
|
||||
* @file classes/security/authorization/internal/SubmissionFileAuthorEditorPolicy.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class SubmissionFileAuthorEditorPolicy
|
||||
*
|
||||
* @ingroup security_authorization_internal
|
||||
*
|
||||
* @brief Submission file policy to ensure that an editor is denied access to
|
||||
* anonymous review files when they are also assigned to the submission as an
|
||||
* author.
|
||||
*/
|
||||
|
||||
namespace PKP\security\authorization\internal;
|
||||
|
||||
use APP\core\Application;
|
||||
use PKP\db\DAORegistry;
|
||||
use PKP\security\authorization\AuthorizationPolicy;
|
||||
use PKP\security\Role;
|
||||
use PKP\submission\reviewAssignment\ReviewAssignment;
|
||||
use PKP\submission\reviewAssignment\ReviewAssignmentDAO;
|
||||
use PKP\submissionFile\SubmissionFile;
|
||||
|
||||
class SubmissionFileAuthorEditorPolicy extends SubmissionFileBaseAccessPolicy
|
||||
{
|
||||
/**
|
||||
* @copydoc AuthorizationPolicy::effect()
|
||||
*/
|
||||
public function effect()
|
||||
{
|
||||
$request = $this->getRequest();
|
||||
|
||||
// Get the submission file.
|
||||
$submissionFile = $this->getSubmissionFile($request);
|
||||
if (!$submissionFile instanceof SubmissionFile) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// Allow if this is not a file submitted with a review
|
||||
if ($submissionFile->getFileStage() != SubmissionFile::SUBMISSION_FILE_REVIEW_ATTACHMENT) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_PERMIT;
|
||||
}
|
||||
|
||||
// Deny if the user is assigned as an author to any stage, and this file is
|
||||
// attached to an anonymous review
|
||||
$userRoles = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ACCESSIBLE_WORKFLOW_STAGES);
|
||||
foreach ($userRoles as $stageRoles) {
|
||||
if (in_array(Role::ROLE_ID_AUTHOR, $stageRoles)) {
|
||||
$reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */
|
||||
$reviewAssignment = $reviewAssignmentDao->getById((int) $submissionFile->getData('assocId'));
|
||||
if ($reviewAssignment && $reviewAssignment->getReviewMethod() != ReviewAssignment::SUBMISSION_REVIEW_METHOD_OPEN) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return AuthorizationPolicy::AUTHORIZATION_PERMIT;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\security\authorization\internal\SubmissionFileAuthorEditorPolicy', '\SubmissionFileAuthorEditorPolicy');
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
/**
|
||||
* @file classes/security/authorization/internal/SubmissionFileBaseAccessPolicy.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class SubmissionFileBaseAccessPolicy
|
||||
*
|
||||
* @ingroup security_authorization_internal
|
||||
*
|
||||
* @brief Abstract class for submission file access policies.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace PKP\security\authorization\internal;
|
||||
|
||||
use APP\facades\Repo;
|
||||
use PKP\core\PKPRequest;
|
||||
use PKP\security\authorization\AuthorizationPolicy;
|
||||
use PKP\submissionFile\SubmissionFile;
|
||||
|
||||
class SubmissionFileBaseAccessPolicy extends AuthorizationPolicy
|
||||
{
|
||||
/** @var PKPRequest */
|
||||
public $_request;
|
||||
|
||||
/** @var int Submission file id */
|
||||
public $_submissionFileId;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param PKPRequest $request
|
||||
* @param int $submissionFileId If passed, this policy will try to
|
||||
* get the submission file from this data.
|
||||
*/
|
||||
public function __construct($request, $submissionFileId = null)
|
||||
{
|
||||
parent::__construct('user.authorization.submissionFile');
|
||||
$this->_request = $request;
|
||||
$this->_submissionFileId = $submissionFileId;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Private methods
|
||||
//
|
||||
/**
|
||||
* Get a cache of submission files. Used because many policy subclasses
|
||||
* may be combined to fetch a single submission file.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function &_getCache()
|
||||
{
|
||||
static $cache = [];
|
||||
return $cache;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Protected methods
|
||||
//
|
||||
/**
|
||||
* Get the requested submission file.
|
||||
*
|
||||
* @param PKPRequest $request
|
||||
*
|
||||
* @return SubmissionFile
|
||||
*/
|
||||
public function getSubmissionFile($request)
|
||||
{
|
||||
// Get the identifying info from the request
|
||||
if (is_null($this->_submissionFileId)) {
|
||||
$this->_submissionFileId = (int) $request->getUserVar('submissionFileId');
|
||||
assert($this->_submissionFileId > 0);
|
||||
}
|
||||
|
||||
// Fetch the object, caching if possible
|
||||
$cache = & $this->_getCache();
|
||||
return $cache[$this->_submissionFileId] ??= Repo::submissionFile()->get($this->_submissionFileId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current request object.
|
||||
*
|
||||
* @return PKPRequest
|
||||
*/
|
||||
public function getRequest()
|
||||
{
|
||||
return $this->_request;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\security\authorization\internal\SubmissionFileBaseAccessPolicy', '\SubmissionFileBaseAccessPolicy');
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
/**
|
||||
* @file classes/security/authorization/internal/SubmissionFileMatchesSubmissionPolicy.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class SubmissionFileMatchesSubmissionPolicy
|
||||
*
|
||||
* @ingroup security_authorization_internal
|
||||
*
|
||||
* @brief Submission file policy to check if the file belongs to the submission
|
||||
*
|
||||
* NB: This policy expects a previously authorized submission in the
|
||||
* authorization context.
|
||||
*/
|
||||
|
||||
namespace PKP\security\authorization\internal;
|
||||
|
||||
use APP\core\Application;
|
||||
use APP\submission\Submission;
|
||||
use PKP\security\authorization\AuthorizationPolicy;
|
||||
use PKP\submissionFile\SubmissionFile;
|
||||
|
||||
class SubmissionFileMatchesSubmissionPolicy extends SubmissionFileBaseAccessPolicy
|
||||
{
|
||||
//
|
||||
// Implement template methods from AuthorizationPolicy
|
||||
//
|
||||
/**
|
||||
* @see AuthorizationPolicy::effect()
|
||||
*/
|
||||
public function effect()
|
||||
{
|
||||
// Get the submission file
|
||||
$request = $this->getRequest();
|
||||
$submissionFile = $this->getSubmissionFile($request);
|
||||
if (!$submissionFile instanceof SubmissionFile) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// Get the submission
|
||||
$submission = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION);
|
||||
if (!$submission instanceof Submission) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
|
||||
// Check if the submission file belongs to the submission.
|
||||
if ($submissionFile->getData('submissionId') == $submission->getId()) {
|
||||
// We add this submission file to the context submission files array.
|
||||
$submissionFilesArray = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION_FILES);
|
||||
if (is_null($submissionFilesArray)) {
|
||||
$submissionFilesArray = [];
|
||||
}
|
||||
array_push($submissionFilesArray, $submissionFile);
|
||||
$this->addAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION_FILES, $submissionFilesArray);
|
||||
|
||||
// Save the submission file to the authorization context.
|
||||
$this->addAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION_FILE, $submissionFile);
|
||||
return AuthorizationPolicy::AUTHORIZATION_PERMIT;
|
||||
} else {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\security\authorization\internal\SubmissionFileMatchesSubmissionPolicy', '\SubmissionFileMatchesSubmissionPolicy');
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
/**
|
||||
* @file classes/security/authorization/internal/SubmissionFileMatchesWorkflowStageIdPolicy.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class SubmissionFileMatchesWorkflowStageIdPolicy
|
||||
*
|
||||
* @ingroup security_authorization_internal
|
||||
*
|
||||
* @brief Submission file policy to check if the file belongs to the specified workflow stage ID
|
||||
*/
|
||||
|
||||
namespace PKP\security\authorization\internal;
|
||||
|
||||
use APP\facades\Repo;
|
||||
use PKP\core\PKPRequest;
|
||||
use PKP\security\authorization\AuthorizationPolicy;
|
||||
use PKP\submissionFile\SubmissionFile;
|
||||
|
||||
class SubmissionFileMatchesWorkflowStageIdPolicy extends SubmissionFileBaseAccessPolicy
|
||||
{
|
||||
/** @var int|null Workflow stage ID (WORKFLOW_STAGE_ID_...) */
|
||||
protected $_stageId = null;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param PKPRequest $request
|
||||
* @param int $stageId Workflow stage ID (WORKFLOW_STAGE_ID_...)
|
||||
* @param null|mixed $submissionFileId
|
||||
*/
|
||||
public function __construct($request, $submissionFileId = null, $stageId = null)
|
||||
{
|
||||
parent::__construct($request, $submissionFileId);
|
||||
$this->_stageId = (int) $stageId;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Implement template methods from AuthorizationPolicy
|
||||
//
|
||||
/**
|
||||
* @see AuthorizationPolicy::effect()
|
||||
*/
|
||||
public function effect()
|
||||
{
|
||||
// Get the submission file
|
||||
$request = $this->getRequest();
|
||||
$submissionFile = $this->getSubmissionFile($request);
|
||||
if (!$submissionFile instanceof SubmissionFile) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
$workflowStageId = Repo::submissionFile()->getWorkflowStageId($submissionFile);
|
||||
|
||||
// Check if the submission file belongs to the specified workflow stage.
|
||||
if ($workflowStageId != $this->_stageId) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
return AuthorizationPolicy::AUTHORIZATION_PERMIT;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\security\authorization\internal\SubmissionFileMatchesWorkflowStageIdPolicy', '\SubmissionFileMatchesWorkflowStageIdPolicy');
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
/**
|
||||
* @file classes/security/authorization/internal/SubmissionFileNotQueryAccessPolicy.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class SubmissionFileNotQueryAccessPolicy
|
||||
*
|
||||
* @ingroup security_authorization_internal
|
||||
*
|
||||
* @brief Submission file policy to check if the requested file is not attached
|
||||
* to a query. This returns AUTHORIZATION_PERMIT for _any_ file that is not
|
||||
* attached to a query note.
|
||||
*/
|
||||
|
||||
namespace PKP\security\authorization\internal;
|
||||
|
||||
use APP\core\Application;
|
||||
use PKP\db\DAORegistry;
|
||||
use PKP\note\NoteDAO;
|
||||
use PKP\security\authorization\AuthorizationPolicy;
|
||||
|
||||
class SubmissionFileNotQueryAccessPolicy extends SubmissionFileBaseAccessPolicy
|
||||
{
|
||||
/**
|
||||
* @see AuthorizationPolicy::effect()
|
||||
*/
|
||||
public function effect()
|
||||
{
|
||||
$request = $this->getRequest();
|
||||
|
||||
// Get the submission file
|
||||
$submissionFile = $this->getSubmissionFile($request);
|
||||
if (!$submissionFile instanceof \PKP\submissionFile\SubmissionFile) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// Check if it's associated with a note.
|
||||
if ($submissionFile->getData('assocType') != Application::ASSOC_TYPE_NOTE) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_PERMIT;
|
||||
}
|
||||
|
||||
// Check if that note is associated with a query
|
||||
$noteDao = DAORegistry::getDAO('NoteDAO'); /** @var NoteDAO $noteDao */
|
||||
$note = $noteDao->getById($submissionFile->getData('assocId'));
|
||||
if ($note->getAssocType() != Application::ASSOC_TYPE_QUERY) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_PERMIT;
|
||||
}
|
||||
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\security\authorization\internal\SubmissionFileNotQueryAccessPolicy', '\SubmissionFileNotQueryAccessPolicy');
|
||||
}
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
/**
|
||||
* @file classes/security/authorization/internal/SubmissionFileRequestedRevisionRequiredPolicy.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class SubmissionFileRequestedRevisionRequiredPolicy
|
||||
*
|
||||
* @ingroup security_authorization_internal
|
||||
*
|
||||
* @brief Base Submission file policy to ensure we have a viewable file that is part of
|
||||
* a review round with the requested revision decision.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace PKP\security\authorization\internal;
|
||||
|
||||
use APP\core\Application;
|
||||
use APP\decision\Decision;
|
||||
use APP\facades\Repo;
|
||||
use PKP\db\DAORegistry;
|
||||
use PKP\security\authorization\AuthorizationPolicy;
|
||||
use PKP\submission\reviewRound\ReviewRound;
|
||||
use PKP\submission\reviewRound\ReviewRoundDAO;
|
||||
use PKP\submissionFile\SubmissionFile;
|
||||
|
||||
class SubmissionFileRequestedRevisionRequiredPolicy extends SubmissionFileBaseAccessPolicy
|
||||
{
|
||||
//
|
||||
// Implement template methods from AuthorizationPolicy
|
||||
// Note: This class is subclassed in each Application, so that Policies have the opportunity to add
|
||||
// constraints to the effect() method. See e.g. SubmissionFileRequestedRevisionRequiredPolicy.php in OMP.
|
||||
//
|
||||
/**
|
||||
* @see AuthorizationPolicy::effect()
|
||||
*/
|
||||
public function effect()
|
||||
{
|
||||
$request = $this->getRequest();
|
||||
$reviewRoundDao = DAORegistry::getDAO('ReviewRoundDAO'); /** @var ReviewRoundDAO $reviewRoundDao */
|
||||
|
||||
// Get the submission file.
|
||||
$submissionFile = $this->getSubmissionFile($request);
|
||||
if (!$submissionFile instanceof SubmissionFile) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// Make sure the file is part of a review round
|
||||
// with a requested revision decision.
|
||||
$reviewRound = $reviewRoundDao->getBySubmissionFileId($submissionFile->getId());
|
||||
if (!$reviewRound instanceof ReviewRound) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
$countRevisionDecisions = Repo::decision()->getCollector()
|
||||
->filterBySubmissionIds([$submissionFile->getData('submissionId)')])
|
||||
->filterByReviewRoundIds([$reviewRound->getId()])
|
||||
->filterByDecisionTypes([Decision::PENDING_REVISIONS])
|
||||
->getCount();
|
||||
|
||||
if (!$countRevisionDecisions) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// Make sure review round stage is the same of the current stage in request.
|
||||
$stageId = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_WORKFLOW_STAGE);
|
||||
if ($reviewRound->getStageId() != $stageId) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// Make sure the file stage is SubmissionFile::SUBMISSION_FILE_REVIEW_REVISION.
|
||||
if ($submissionFile->getData('fileStage') != SubmissionFile::SUBMISSION_FILE_REVIEW_REVISION) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
$reviewRoundDao = DAORegistry::getDAO('ReviewRoundDAO'); /** @var ReviewRoundDAO $reviewRoundDao */
|
||||
|
||||
// Make sure that the last review round editor decision is request revisions.
|
||||
$reviewRoundDecisions = Repo::decision()->getCollector()
|
||||
->filterBySubmissionIds([$submissionFile->getData('submissionId')])
|
||||
->filterByStageIds([$reviewRound->getStageId()])
|
||||
->filterByReviewRoundIds([$reviewRound->getId()])
|
||||
->getMany();
|
||||
|
||||
if ($reviewRoundDecisions->isEmpty()) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
$lastEditorDecision = $reviewRoundDecisions->last();
|
||||
if ($lastEditorDecision->getData('decision') != Decision::PENDING_REVISIONS) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// Made it through -- permit access.
|
||||
return AuthorizationPolicy::AUTHORIZATION_PERMIT;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\security\authorization\internal\SubmissionFileRequestedRevisionRequiredPolicy', '\SubmissionFileRequestedRevisionRequiredPolicy');
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
/**
|
||||
* @file classes/security/authorization/internal/SubmissionFileStageAccessPolicy.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class SubmissionFileStageAccessPolicy
|
||||
*
|
||||
* @ingroup security_authorization_internal
|
||||
*
|
||||
* @brief Submission file policy to ensure that the user can read or write to a particular
|
||||
* file stage based on their stage assignments. This policy expects submission, user roles
|
||||
* and workflow stage assignments in the authorized context.
|
||||
*/
|
||||
|
||||
namespace PKP\security\authorization\internal;
|
||||
|
||||
use APP\core\Application;
|
||||
use APP\decision\Decision;
|
||||
use APP\facades\Repo;
|
||||
use PKP\db\DAORegistry;
|
||||
use PKP\security\authorization\AuthorizationPolicy;
|
||||
use PKP\security\authorization\SubmissionFileAccessPolicy;
|
||||
use PKP\security\Role;
|
||||
use PKP\submission\reviewRound\ReviewRoundDAO;
|
||||
use PKP\submissionFile\SubmissionFile;
|
||||
|
||||
class SubmissionFileStageAccessPolicy extends AuthorizationPolicy
|
||||
{
|
||||
/** @var int SubmissionFile::SUBMISSION_FILE_... */
|
||||
public $_fileStage;
|
||||
|
||||
/** @var int SubmissionFileAccessPolicy::SUBMISSION_FILE_ACCESS_READ... */
|
||||
public $_action;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param int $fileStage SubmissionFile::SUBMISSION_FILE_...
|
||||
* @param int $action SubmissionFileAccessPolicy::SUBMISSION_FILE_ACCESS_READ or SubmissionFileAccessPolicy::SUBMISSION_FILE_ACCESS_MODIFY
|
||||
* @param string $message The message to display when authorization is denied
|
||||
*/
|
||||
public function __construct($fileStage, $action, $message)
|
||||
{
|
||||
parent::__construct($message);
|
||||
$this->_fileStage = $fileStage;
|
||||
$this->_action = $action;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Implement template methods from AuthorizationPolicy
|
||||
//
|
||||
/**
|
||||
* @see AuthorizationPolicy::effect()
|
||||
*/
|
||||
public function effect()
|
||||
{
|
||||
$submission = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION);
|
||||
$userRoles = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_USER_ROLES);
|
||||
$stageAssignments = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ACCESSIBLE_WORKFLOW_STAGES);
|
||||
|
||||
// File stage required
|
||||
if (empty($this->_fileStage)) {
|
||||
$this->setAdvice(AuthorizationPolicy::AUTHORIZATION_ADVICE_DENY_MESSAGE, $msg = 'api.submissionFiles.400.noFileStageId');
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// Managers and site admins can access file stages when not assigned or when assigned as a manager
|
||||
if (empty($stageAssignments)) {
|
||||
if (count(array_intersect([Role::ROLE_ID_MANAGER, Role::ROLE_ID_SITE_ADMIN], $userRoles))) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_PERMIT;
|
||||
}
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// Determine the allowed file stages
|
||||
$assignedFileStages = Repo::submissionFile()
|
||||
->getAssignedFileStages(
|
||||
$stageAssignments,
|
||||
$this->_action
|
||||
);
|
||||
|
||||
// Authors may write to the submission files stage if the submission
|
||||
// is not yet complete
|
||||
if ($this->_fileStage === SubmissionFile::SUBMISSION_FILE_SUBMISSION && $this->_action === SubmissionFileAccessPolicy::SUBMISSION_FILE_ACCESS_MODIFY) {
|
||||
if (!empty($stageAssignments[WORKFLOW_STAGE_ID_SUBMISSION])
|
||||
&& count($stageAssignments[WORKFLOW_STAGE_ID_SUBMISSION]) === 1
|
||||
&& in_array(Role::ROLE_ID_AUTHOR, $stageAssignments[WORKFLOW_STAGE_ID_SUBMISSION])
|
||||
&& $submission->getData('submissionProgress')) {
|
||||
$assignedFileStages[] = SubmissionFile::SUBMISSION_FILE_SUBMISSION;
|
||||
}
|
||||
}
|
||||
|
||||
// Authors may write to the revision files stage if an accept or request revisions
|
||||
// decision has been made in the latest round
|
||||
if (in_array($this->_fileStage, [SubmissionFile::SUBMISSION_FILE_INTERNAL_REVIEW_REVISION, SubmissionFile::SUBMISSION_FILE_REVIEW_REVISION]) && $this->_action === SubmissionFileAccessPolicy::SUBMISSION_FILE_ACCESS_MODIFY) {
|
||||
$reviewStage = $this->_fileStage === SubmissionFile::SUBMISSION_FILE_INTERNAL_REVIEW_REVISION
|
||||
? WORKFLOW_STAGE_ID_INTERNAL_REVIEW
|
||||
: WORKFLOW_STAGE_ID_EXTERNAL_REVIEW;
|
||||
|
||||
if (count($stageAssignments[$reviewStage]) === 1 && in_array(Role::ROLE_ID_AUTHOR, $stageAssignments[$reviewStage])) {
|
||||
$reviewRoundDao = DAORegistry::getDAO('ReviewRoundDAO'); /** @var ReviewRoundDAO $reviewRoundDao */
|
||||
$reviewRound = $reviewRoundDao->getLastReviewRoundBySubmissionId($submission->getId(), $reviewStage);
|
||||
if ($reviewRound) {
|
||||
$countDecisions = Repo::decision()->getCollector()
|
||||
->filterBySubmissionIds([$submission->getId()])
|
||||
->filterByStageIds([$reviewRound->getStageId()])
|
||||
->filterByReviewRoundIds([$reviewRound->getId()])
|
||||
->filterByDecisionTypes([
|
||||
Decision::ACCEPT,
|
||||
Decision::PENDING_REVISIONS,
|
||||
Decision::NEW_EXTERNAL_ROUND,
|
||||
Decision::RESUBMIT
|
||||
])
|
||||
->getCount();
|
||||
|
||||
if ($countDecisions) {
|
||||
$assignedFileStages[] = $this->_fileStage;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (in_array($this->_fileStage, $assignedFileStages)) {
|
||||
$this->addAuthorizedContextObject(Application::ASSOC_TYPE_ACCESSIBLE_FILE_STAGES, $assignedFileStages);
|
||||
return AuthorizationPolicy::AUTHORIZATION_PERMIT;
|
||||
}
|
||||
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\security\authorization\internal\SubmissionFileStageAccessPolicy', '\SubmissionFileStageAccessPolicy');
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
/**
|
||||
* @file classes/security/authorization/internal/SubmissionFileStageRequiredPolicy.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class SubmissionFileStageRequiredPolicy
|
||||
*
|
||||
* @ingroup security_authorization_internal
|
||||
*
|
||||
* @brief Submission file policy to ensure that we have a file at a required stage.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace PKP\security\authorization\internal;
|
||||
|
||||
use APP\core\Application;
|
||||
use PKP\core\PKPRequest;
|
||||
use PKP\db\DAORegistry;
|
||||
use PKP\security\authorization\AuthorizationPolicy;
|
||||
use PKP\submission\reviewAssignment\ReviewAssignment;
|
||||
use PKP\submission\reviewAssignment\ReviewAssignmentDAO;
|
||||
|
||||
class SubmissionFileStageRequiredPolicy extends SubmissionFileBaseAccessPolicy
|
||||
{
|
||||
/** @var int SubmissionFile::SUBMISSION_FILE_... */
|
||||
public $_fileStage;
|
||||
|
||||
/** @var bool Whether the file has to be viewable */
|
||||
public $_viewable;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param PKPRequest $request
|
||||
* @param int $submissionFileId This policy will try to
|
||||
* get the submission file from this data.
|
||||
* @param int $fileStage SubmissionFile::SUBMISSION_FILE_...
|
||||
* @param bool $viewable Whether the file has to be viewable
|
||||
*/
|
||||
public function __construct($request, $submissionFileId, $fileStage, $viewable = false)
|
||||
{
|
||||
parent::__construct($request, $submissionFileId);
|
||||
$this->_fileStage = $fileStage;
|
||||
$this->_viewable = $viewable;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Implement template methods from AuthorizationPolicy
|
||||
//
|
||||
/**
|
||||
* @see AuthorizationPolicy::effect()
|
||||
*/
|
||||
public function effect()
|
||||
{
|
||||
$request = $this->getRequest();
|
||||
|
||||
// Get the submission file.
|
||||
$submissionFile = $this->getSubmissionFile($request);
|
||||
if (!$submissionFile instanceof \PKP\submissionFile\SubmissionFile) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// Make sure that it's in the required stage
|
||||
if ($submissionFile->getFileStage() != $this->_fileStage) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
if ($this->_viewable) {
|
||||
// Make sure the file is visible. Unless file is included in an open review.
|
||||
if (!$submissionFile->getViewable()) {
|
||||
if ($submissionFile->getData('assocType') === Application::ASSOC_TYPE_REVIEW_ASSIGNMENT) {
|
||||
$reviewAssignmentDao = DAORegistry::getDAO('ReviewAssignmentDAO'); /** @var ReviewAssignmentDAO $reviewAssignmentDao */
|
||||
$reviewAssignment = $reviewAssignmentDao->getById((int) $submissionFile->getData('assocId'));
|
||||
if ($reviewAssignment->getReviewMethod() != ReviewAssignment::SUBMISSION_REVIEW_METHOD_OPEN) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
} else {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Made it through -- permit access.
|
||||
return AuthorizationPolicy::AUTHORIZATION_PERMIT;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\security\authorization\internal\SubmissionFileStageRequiredPolicy', '\SubmissionFileStageRequiredPolicy');
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file classes/security/authorization/internal/SubmissionFileUploaderAccessPolicy.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class SubmissionFileUploaderAccessPolicy
|
||||
*
|
||||
* @ingroup security_authorization_internal
|
||||
*
|
||||
* @brief Submission file policy to check if the current user is the uploader.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace PKP\security\authorization\internal;
|
||||
|
||||
use PKP\security\authorization\AuthorizationPolicy;
|
||||
|
||||
class SubmissionFileUploaderAccessPolicy extends SubmissionFileBaseAccessPolicy
|
||||
{
|
||||
//
|
||||
// Implement template methods from AuthorizationPolicy
|
||||
//
|
||||
/**
|
||||
* @see AuthorizationPolicy::effect()
|
||||
*/
|
||||
public function effect()
|
||||
{
|
||||
$request = $this->getRequest();
|
||||
|
||||
// Get the user
|
||||
$user = $request->getUser();
|
||||
if (!$user instanceof \PKP\user\User) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// Get the submission file
|
||||
$submissionFile = $this->getSubmissionFile($request);
|
||||
if (!$submissionFile instanceof \PKP\submissionFile\SubmissionFile) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// Check if the uploader is the current user.
|
||||
if ($submissionFile->getUploaderUserId() == $user->getId()) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_PERMIT;
|
||||
} else {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\security\authorization\internal\SubmissionFileUploaderAccessPolicy', '\SubmissionFileUploaderAccessPolicy');
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
/**
|
||||
* @file classes/security/authorization/internal/SubmissionRequiredPolicy.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class SubmissionRequiredPolicy
|
||||
*
|
||||
* @ingroup security_authorization_internal
|
||||
*
|
||||
* @brief Policy that ensures that the request contains a valid submission.
|
||||
*/
|
||||
|
||||
namespace PKP\security\authorization\internal;
|
||||
|
||||
use APP\core\Application;
|
||||
use APP\facades\Repo;
|
||||
use APP\submission\Submission;
|
||||
use PKP\core\PKPRequest;
|
||||
use PKP\security\authorization\AuthorizationPolicy;
|
||||
use PKP\security\authorization\DataObjectRequiredPolicy;
|
||||
|
||||
class SubmissionRequiredPolicy extends DataObjectRequiredPolicy
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param PKPRequest $request
|
||||
* @param array $args request parameters
|
||||
* @param string $submissionParameterName the request parameter we expect
|
||||
* the submission id in.
|
||||
* @param null|mixed $operations
|
||||
*/
|
||||
public function __construct($request, &$args, $submissionParameterName = 'submissionId', $operations = null)
|
||||
{
|
||||
parent::__construct($request, $args, $submissionParameterName, 'user.authorization.invalidSubmission', $operations);
|
||||
|
||||
$callOnDeny = [$request->getDispatcher(), 'handle404', []];
|
||||
$this->setAdvice(
|
||||
AuthorizationPolicy::AUTHORIZATION_ADVICE_CALL_ON_DENY,
|
||||
$callOnDeny
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// Implement template methods from AuthorizationPolicy
|
||||
//
|
||||
/**
|
||||
* @see DataObjectRequiredPolicy::dataObjectEffect()
|
||||
*/
|
||||
public function dataObjectEffect()
|
||||
{
|
||||
// Get the submission id.
|
||||
$submissionId = $this->getDataObjectId();
|
||||
if ($submissionId === false) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// Validate the submission id.
|
||||
$submission = Repo::submission()->get((int) $submissionId);
|
||||
if (!$submission instanceof Submission) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// Validate that this submission belongs to the current context.
|
||||
$context = $this->_request->getContext();
|
||||
if ($context->getId() != $submission->getData('contextId')) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// Save the submission to the authorization context.
|
||||
$this->addAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION, $submission);
|
||||
return AuthorizationPolicy::AUTHORIZATION_PERMIT;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\security\authorization\internal\SubmissionRequiredPolicy', '\SubmissionRequiredPolicy');
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
/**
|
||||
* @file classes/security/authorization/internal/UserAccessibleWorkflowStagePolicy.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class UserAccessibleWorkflowStagePolicy
|
||||
*
|
||||
* @ingroup security_authorization_internal
|
||||
*
|
||||
* @brief Class to control access to a
|
||||
*
|
||||
*/
|
||||
|
||||
namespace PKP\security\authorization\internal;
|
||||
|
||||
use APP\core\Application;
|
||||
use PKP\security\authorization\AuthorizationPolicy;
|
||||
|
||||
class UserAccessibleWorkflowStagePolicy extends AuthorizationPolicy
|
||||
{
|
||||
/** @var int */
|
||||
public $_stageId;
|
||||
|
||||
/** @var string Workflow type. One of PKPApplication::WORKFLOW_TYPE_... */
|
||||
public $_workflowType;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param int $stageId The one that will be checked against accessible
|
||||
* user workflow stages.
|
||||
* @param string $workflowType Which workflow the stage access must be granted
|
||||
* for. One of PKPApplication::WORKFLOW_TYPE_*.
|
||||
*/
|
||||
public function __construct($stageId, $workflowType = null)
|
||||
{
|
||||
parent::__construct('user.authorization.accessibleWorkflowStage');
|
||||
$this->_stageId = $stageId;
|
||||
if (!is_null($workflowType)) {
|
||||
$this->_workflowType = $workflowType;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Implement template methods from AuthorizationPolicy
|
||||
//
|
||||
/**
|
||||
* @see AuthorizationPolicy::effect()
|
||||
*/
|
||||
public function effect()
|
||||
{
|
||||
$userAccessibleStages = $this->getAuthorizedContextObject(Application::ASSOC_TYPE_ACCESSIBLE_WORKFLOW_STAGES);
|
||||
|
||||
// User has no access to any stage in any workflow
|
||||
if (empty($userAccessibleStages)) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
|
||||
// Does user have access to this stage in the requested workflow?
|
||||
} elseif (!is_null($this->_workflowType)) {
|
||||
$workflowTypeRoles = Application::getWorkflowTypeRoles();
|
||||
if (array_key_exists($this->_stageId, $userAccessibleStages) && array_intersect($workflowTypeRoles[$this->_workflowType], $userAccessibleStages[$this->_stageId])) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_PERMIT;
|
||||
}
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
|
||||
// The user has access to this stage in any workflow
|
||||
} elseif (array_key_exists($this->_stageId, $userAccessibleStages)) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_PERMIT;
|
||||
}
|
||||
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\security\authorization\internal\UserAccessibleWorkflowStagePolicy', '\UserAccessibleWorkflowStagePolicy');
|
||||
}
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
/**
|
||||
* @file classes/security/authorization/internal/UserAccessibleWorkflowStageRequiredPolicy.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class UserAccessibleWorkflowStageRequiredPolicy
|
||||
*
|
||||
* @ingroup security_authorization_internal
|
||||
*
|
||||
* @brief Policy to deny access if an user assigned workflow stage is not found.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace PKP\security\authorization\internal;
|
||||
|
||||
use APP\core\Application;
|
||||
use APP\facades\Repo;
|
||||
use PKP\core\PKPApplication;
|
||||
use PKP\core\PKPRequest;
|
||||
use PKP\security\authorization\AuthorizationPolicy;
|
||||
|
||||
class UserAccessibleWorkflowStageRequiredPolicy extends AuthorizationPolicy
|
||||
{
|
||||
/** @var PKPRequest */
|
||||
public $_request;
|
||||
|
||||
/** @var string Workflow type. One of PKPApplication::WORKFLOW_TYPE_... */
|
||||
public $_workflowType;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param PKPRequest $request
|
||||
* @param string $workflowType Which workflow the stage access must be granted
|
||||
* for. One of PKPApplication::WORKFLOW_TYPE_*.
|
||||
*/
|
||||
public function __construct($request, $workflowType = null)
|
||||
{
|
||||
parent::__construct('user.authorization.accessibleWorkflowStage');
|
||||
$this->_request = $request;
|
||||
$this->_workflowType = $workflowType;
|
||||
}
|
||||
|
||||
//
|
||||
// Implement template methods from AuthorizationPolicy
|
||||
//
|
||||
/**
|
||||
* @see AuthorizationPolicy::effect()
|
||||
*/
|
||||
public function effect()
|
||||
{
|
||||
$request = $this->_request;
|
||||
$context = $request->getContext();
|
||||
$contextId = $context->getId();
|
||||
$user = $request->getUser();
|
||||
if (!$user instanceof \PKP\user\User) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
$accessibleWorkflowStages = Repo::user()->getAccessibleWorkflowStages(
|
||||
$user->getId(),
|
||||
$contextId,
|
||||
$this->getAuthorizedContextObject(Application::ASSOC_TYPE_SUBMISSION),
|
||||
$this->getAuthorizedContextObject(PKPApplication::ASSOC_TYPE_USER_ROLES)
|
||||
);
|
||||
|
||||
$this->addAuthorizedContextObject(Application::ASSOC_TYPE_ACCESSIBLE_WORKFLOW_STAGES, $accessibleWorkflowStages);
|
||||
|
||||
// Does the user have a role which matches the requested workflow?
|
||||
if (!is_null($this->_workflowType)) {
|
||||
$workflowTypeRoles = Application::getWorkflowTypeRoles();
|
||||
foreach ($accessibleWorkflowStages as $stageId => $roles) {
|
||||
if (array_intersect($workflowTypeRoles[$this->_workflowType], $roles)) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_PERMIT;
|
||||
}
|
||||
}
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
|
||||
// User has at least one role in any stage in any workflow
|
||||
} elseif (!empty($accessibleWorkflowStages)) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_PERMIT;
|
||||
}
|
||||
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\security\authorization\internal\UserAccessibleWorkflowStageRequiredPolicy', '\UserAccessibleWorkflowStageRequiredPolicy');
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
/**
|
||||
* @file classes/security/authorization/internal/WorkflowStageRequiredPolicy.php
|
||||
*
|
||||
* Copyright (c) 2014-2021 Simon Fraser University
|
||||
* Copyright (c) 2000-2021 John Willinsky
|
||||
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
||||
*
|
||||
* @class WorkflowStageRequiredPolicy
|
||||
*
|
||||
* @ingroup security_authorization_internal
|
||||
*
|
||||
* @brief Policy that ensures that the given workflow stage is valid.
|
||||
*/
|
||||
|
||||
namespace PKP\security\authorization\internal;
|
||||
|
||||
use APP\core\Application;
|
||||
use PKP\security\authorization\AuthorizationPolicy;
|
||||
|
||||
class WorkflowStageRequiredPolicy extends AuthorizationPolicy
|
||||
{
|
||||
/** @var int */
|
||||
public $_stageId;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param int $stageId One of the WORKFLOW_STAGE_ID_* constants.
|
||||
*/
|
||||
public function __construct($stageId)
|
||||
{
|
||||
parent::__construct('user.authorization.workflowStageRequired');
|
||||
$this->_stageId = $stageId;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Implement template methods from AuthorizationPolicy
|
||||
//
|
||||
/**
|
||||
* @see AuthorizationPolicy::effect()
|
||||
*/
|
||||
public function effect()
|
||||
{
|
||||
// Check the stage id.
|
||||
$validAppStages = Application::getApplicationStages();
|
||||
if (!in_array($this->_stageId, array_values($validAppStages))) {
|
||||
return AuthorizationPolicy::AUTHORIZATION_DENY;
|
||||
}
|
||||
|
||||
// Save the workflow stage to the authorization context.
|
||||
$this->addAuthorizedContextObject(Application::ASSOC_TYPE_WORKFLOW_STAGE, $this->_stageId);
|
||||
return AuthorizationPolicy::AUTHORIZATION_PERMIT;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PKP_STRICT_MODE) {
|
||||
class_alias('\PKP\security\authorization\internal\WorkflowStageRequiredPolicy', '\WorkflowStageRequiredPolicy');
|
||||
}
|
||||
Reference in New Issue
Block a user