Completed
Branch develop-3.0 (4fe777)
by Mohamed
11:06
created

Permission::handle()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 11
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 11
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 5
nc 2
nop 2
1
<?php
2
3
/*
4
 * This file is part of the Tinyissue package.
5
 *
6
 * (c) Mohamed Alsharaf <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Tinyissue\Http\Middleware;
13
14
use Closure;
15
use Illuminate\Database\Eloquent\Model as ModelAbstract;
16
use Illuminate\Http\Request;
17
use Illuminate\Routing\Route;
18
use Tinyissue\Contracts\Model\AccessControl;
19
use Tinyissue\Model\Permission as PermissionModel;
20
use Tinyissue\Model\Project as ProjectModel;
21
use Tinyissue\Model\User;
22
23
/**
24
 * Permission is a Middleware class to for checking if current user has the permission to access the request.
25
 *
26
 * @author Mohamed Alsharaf <[email protected]>
27
 */
28
class Permission extends MiddlewareAbstract
29
{
30
    /**
31
     * List of permissions that can be accessed by public users.
32
     *
33
     * @var array
34
     */
35
    protected $publicAccess = [
36
        'issue-view',
37
    ];
38
39
    /**
40
     * Ordered list of contexts.
41
     *
42
     * @var array
43
     */
44
    protected $contexts = [
45
        'comment',
46
        'attachment',
47
        'issue',
48
        'project',
49
    ];
50
51
    /**
52
     * Handle an incoming request.
53
     *
54
     * @param Request  $request
55
     * @param \Closure $next
56
     *
57
     * @return mixed
58
     */
59
    public function handle(Request $request, Closure $next)
60
    {
61
        $permission = $this->getPermission($request);
62
63
        // Can't access if public project disabled or user does not have access
64
        if (!$this->isInPublicProjectContext($request, $permission) && !$this->canAccess($request, $permission)) {
65
            abort(401);
66
        }
67
68
        return $next($request);
69
    }
70
71
    /**
72
     * Whether or not the current context is in public project.
73
     *
74
     * @param Request $request
75
     * @param string  $permission
76
     *
77
     * @return bool
78
     */
79
    protected function isInPublicProjectContext(Request $request, $permission)
80
    {
81
        /** @var ProjectModel|null $project */
82
        $project         = $request->route()->getParameter('project');
83
        $isPublicEnabled = app('tinyissue.settings')->isPublicProjectsEnabled();
84
        $isPublicAccess  = in_array($permission, $this->publicAccess);
85
        $isPublicProject = $project instanceof ProjectModel && $project->isPublic();
86
87
        return $isPublicEnabled && $isPublicAccess && $isPublicProject;
88
    }
89
90
    /**
91
     * Whether or not the user can access the current context.
92
     *
93
     * @param Request $request
94
     * @param string  $permission
95
     *
96
     * @return bool
97
     */
98
    protected function canAccess(Request $request, $permission)
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $permission is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
99
    {
100
        if (!$this->isLoggedIn()) {
101
            return false;
102
        }
103
104
        return true; /// @todo fix
105
        $user = $this->isLoggedIn();
0 ignored issues
show
Unused Code introduced by
/// @todo fix $user = $this->isLoggedIn(); does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
106
107
        // Can access all projects
108
        if ($permission !== PermissionModel::PERM_ADMIN && $user->permission(PermissionModel::PERM_PROJECT_ALL)) {
109
            return true;
110
        }
111
112
//        $hasPermission = $user->permission($permission);
113
114
        // Can access the current context
115
        $context       = $this->getCurrentContext($request->route());
0 ignored issues
show
Unused Code introduced by
$context is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
116
        $contextAccess = true;
0 ignored issues
show
Unused Code introduced by
$contextAccess is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
117
118
        return true; /// @todo fix
119
        if ($context instanceof AccessControl) {
0 ignored issues
show
Unused Code introduced by
/// @todo fix if ($conte... } return true; } does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
120
            $contextAccess = $context->can($permission, $user);
121
            if (!$contextAccess) {
122
                return false;
123
            }
124
125
            return true;
126
        }
127
128
        return $hasPermission;
129
    }
130
131
    /**
132
     * Return the model object of the current context.
133
     * We check the lowest ( Comment ) first, to the highest ( Project ).
134
     *
135
     * @param Route $route
136
     *
137
     * @return ModelAbstract|null
138
     */
139
    protected function getCurrentContext(Route $route)
140
    {
141
        foreach ($this->contexts as $context) {
142
            $parameter = $route->getParameter($context);
143
            if ($parameter instanceof ModelAbstract) {
144
                return $parameter;
145
            }
146
        }
147
148
        return null;
149
    }
150
151
    /**
152
     * Returns the permission defined in route action.
153
     *
154
     * @param Request $request
155
     *
156
     * @return mixed
157
     */
158
    protected function getPermission(Request $request)
159
    {
160
        $actions = $request->route()->getAction();
161
162
        return $actions['permission'];
163
    }
164
}
165