Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 42
0.00% covered (danger)
0.00%
0 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
Permission
0.00% covered (danger)
0.00%
0 / 42
0.00% covered (danger)
0.00%
0 / 4
306
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 isAuthorized
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 check
0.00% covered (danger)
0.00%
0 / 37
0.00% covered (danger)
0.00%
0 / 1
210
 getIdentity
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3/**
4 * VuFind Action Helper - Permission Checker
5 *
6 * PHP version 8
7 *
8 * Copyright (C) Villanova University 2017.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2,
12 * as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22 *
23 * @category VuFind
24 * @package  Controller_Plugins
25 * @author   Demian Katz <demian.katz@villanova.edu>
26 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
27 * @link     https://vufind.org Main Page
28 */
29
30namespace VuFind\Controller\Plugin;
31
32use Laminas\Log\LoggerAwareInterface;
33use Laminas\Mvc\Controller\Plugin\AbstractPlugin;
34use VuFind\Exception\Forbidden as ForbiddenException;
35use VuFind\I18n\Translator\TranslatorAwareInterface;
36use VuFind\Role\PermissionDeniedManager;
37use VuFind\Role\PermissionManager;
38
39/**
40 * VuFind Action Helper - Permission Checker
41 *
42 * @category VuFind
43 * @package  Controller_Plugins
44 * @author   Demian Katz <demian.katz@villanova.edu>
45 * @license  http://opensource.org/licenses/gpl-2.0.php GNU General Public License
46 * @link     https://vufind.org Main Page
47 */
48class Permission extends AbstractPlugin implements
49    LoggerAwareInterface,
50    TranslatorAwareInterface
51{
52    use \VuFind\I18n\Translator\TranslatorAwareTrait;
53    use \VuFind\Log\LoggerAwareTrait;
54
55    /**
56     * Permission manager
57     *
58     * @var PermissionManager
59     */
60    protected $permissionManager;
61
62    /**
63     * Permission denied manager
64     *
65     * @var PermissionDeniedManager
66     */
67    protected $permissionDeniedManager;
68
69    /**
70     * Auth manager
71     *
72     * @var \VuFind\Auth\Manager
73     */
74    protected $authManager;
75
76    /**
77     * Constructor
78     *
79     * @param PermissionManager       $pm   Permission Manager
80     * @param PermissionDeniedManager $pdm  Permission Denied Manager
81     * @param \VuFind\Auth\Manager    $auth Auth manager
82     */
83    public function __construct(
84        PermissionManager $pm,
85        PermissionDeniedManager $pdm,
86        \VuFind\Auth\Manager $auth
87    ) {
88        $this->permissionManager = $pm;
89        $this->permissionDeniedManager = $pdm;
90        $this->authManager = $auth;
91    }
92
93    /**
94     * Check if a permission is authorized, returning a boolean value without
95     * applying any additional behavior.
96     *
97     * @param string $permission Permission to check
98     * @param mixed  $context    Context for the permission behavior (optional)
99     *
100     * @return bool
101     */
102    public function isAuthorized($permission, $context = null)
103    {
104        return $this->permissionManager->isAuthorized($permission, $context);
105    }
106
107    /**
108     * Check if a permission is denied; if so, throw an exception or return an
109     * error response as configured in permissionBehavior.ini.
110     *
111     * @param string $permission      Permission to check
112     * @param string $defaultBehavior Default behavior to use if none configured
113     * (null to use default configured in the manager, false to take no action).
114     * @param bool   $passIfUndefined Should the check pass if no rules are
115     * defined for $permission in permissions.ini?
116     *
117     * @return mixed
118     */
119    public function check(
120        $permission,
121        $defaultBehavior = null,
122        $passIfUndefined = false
123    ) {
124        // If no permission rule is defined and we're only checking defined
125        // permissions, bail out now....
126        if (
127            !$this->permissionManager->permissionRuleExists($permission)
128            && $passIfUndefined
129        ) {
130            return null;
131        }
132
133        // Make sure the current user has permission to access the module:
134        if ($this->permissionManager->isAuthorized($permission) !== true) {
135            $dl = $this->permissionDeniedManager->getDeniedControllerBehavior(
136                $permission,
137                $defaultBehavior
138            );
139            if ($dl === false) {
140                return null;
141            }
142            $exceptionDescription = $dl['exceptionMessage'] ?? 'Access denied.';
143            switch (strtolower($dl['action'])) {
144                case 'promptlogin':
145                    // If the user is already logged in, but we're getting a "prompt
146                    // login" denied permission requirement, there is probably a
147                    // configuration error somewhere; throw an exception rather than
148                    // triggering an infinite login redirection loop.
149                    if ($this->getIdentity()) {
150                        throw new ForbiddenException(
151                            'Trying to prompt login due to denied ' . $permission
152                            . ' permission, but a user is already logged in; '
153                            . 'possible configuration problem in permissions.ini.'
154                        );
155                    }
156                    $msg = empty($dl['value']) ? null : $dl['value'];
157                    return $this->getController()->forceLogin($msg, [], false);
158                case 'showmessage':
159                    return $this->getController()->redirect()->toRoute(
160                        'error-permissiondenied',
161                        [],
162                        ['query' => ['msg' => $dl['value']]]
163                    );
164                case 'exception':
165                    $exceptionClass
166                        = (isset($dl['value']) && class_exists($dl['value']))
167                        ? $dl['value'] : \VuFind\Exception\Forbidden::class;
168                    $exception = new $exceptionClass($exceptionDescription);
169                    if ($exception instanceof \Exception) {
170                        throw $exception;
171                    }
172                    $this->logError('Permission configuration problem.');
173                    throw new \Exception("$exceptionClass is not an exception!");
174                default:
175                    throw new ForbiddenException($exceptionDescription);
176            }
177        }
178        return null;
179    }
180
181    /**
182     * Get the current identity from the authentication manager.
183     *
184     * @return \LmcRbacMvc\Identity\IdentityInterface|null
185     */
186    public function getIdentity()
187    {
188        return $this->authManager->getIdentity();
189    }
190}