Completed
Push — master ( 1b8ca6...90d75c )
by Mahmoud
03:54
created

TestsAuthHelperTrait::getTestingUser()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 3
nc 2
nop 2
1
<?php
2
3
namespace App\Ship\Features\Tests\PhpUnit;
4
5
use App;
6
use App\Containers\Authentication\Tasks\ApiLoginThisUserObjectTask;
7
use App\Containers\User\Models\User;
8
use Artisan;
9
use Dingo\Api\Http\Response as DingoAPIResponse;
10
use Illuminate\Support\Facades\Hash;
11
12
/**
13
 * Class TestsAuthHelperTrait.
14
 *
15
 * Tests helper for authentication and authorization.
16
 *
17
 * @author  Mahmoud Zalt <[email protected]>
18
 */
19
trait TestsAuthHelperTrait
20
{
21
22
    /**
23
     * Logged in user object.
24
     *
25
     * @var User
26
     */
27
    protected $testingUser;
28
29
    /**
30
     * Roles and permissions, to be attached on the user
31
     *
32
     * @var array
33
     */
34
    protected $access = [
35
        'permissions' => '',
36
        'roles'       => '',
37
    ];
38
39
    /**
40
     * Try to get the last logged in User, if not found then create new one.
41
     * Note: if $userDetails are provided it will always create new user, even
42
     * if another one was previously created during the execution of your test.
43
     *
44
     * By default Users will be given the Roles and Permissions found int he class
45
     * `$access` property. But the $access parameter can be used to override the
46
     * defined roles and permissions in the `$access` property of your class.
47
     *
48
     * @param null $access      roles and permissions you'd like to provide this user with
49
     * @param null $userDetails what to be attached on the User object
50
     *
51
     * @return  \App\Containers\User\Models\User
52
     */
53
    public function getTestingUser($userDetails = null, $access = null)
54
    {
55
        return is_null($userDetails) ? $this->findOrCreateTestingUser($userDetails, $access)
56
            : $this->createTestingUser($userDetails, $access);
57
    }
58
59
    /**
60
     * Same as `getTestingUser()` but always overrides the User Access
61
     * (roles and permissions) with null. So the user can be used to test
62
     * if unauthorized user tried to access your protected endpoint.
63
     *
64
     * @param null $userDetails
65
     *
66
     * @return  \App\Containers\User\Models\User
67
     */
68
    public function getTestingUserWithoutAccess($userDetails = null)
69
    {
70
        return $this->getTestingUser($userDetails, $this->getNullAccess());
71
    }
72
73
    /**
74
     * @param $userDetails
75
     * @param $access
76
     *
77
     * @return  \App\Containers\User\Models\User
78
     */
79
    private function findOrCreateTestingUser($userDetails, $access)
80
    {
81
        return $this->testingUser ? : $this->createTestingUser($userDetails, $access);
82
    }
83
84
    /**
85
     * @param null $access
86
     * @param null $userDetails
87
     *
88
     * @return  User
89
     */
90
    private function createTestingUser($userDetails = null, $access = null)
91
    {
92
        // create new user
93
        $user = $this->factoryCreateUser($userDetails);
94
95
        // assign user roles and permissions based on the access property
96
        $user = $this->setupTestingUserAccess($user, $access);
97
98
        // log the user in
99
        $user = App::make(ApiLoginThisUserObjectTask::class)->run($user);
100
101
        // set the created user
102
        return $this->testingUser = $user;
103
    }
104
105
    /**
106
     * @param null $userDetails
107
     *
108
     * @return  User
109
     */
110
    private function factoryCreateUser($userDetails = null)
111
    {
112
        return factory(User::class)->create($this->prepareUserDetails($userDetails));
113
    }
114
115
    /**
116
     * @param null $userDetails
117
     *
118
     * @return  array
119
     */
120
    private function prepareUserDetails($userDetails = null)
121
    {
122
        $defaultUserDetails = [
123
            'name'     => $this->faker->name,
0 ignored issues
show
Bug introduced by
The property faker does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
124
            'email'    => $this->faker->email,
125
            'password' => 'testing-password',
126
        ];
127
128
        // if no user detail provided, use the default details, to find the password or generate one before encoding it
129
        return $this->prepareUserPassword($userDetails ? : $defaultUserDetails);;
130
    }
131
132
    /**
133
     * @param $userDetails
134
     *
135
     * @return  null
136
     */
137
    private function prepareUserPassword($userDetails)
138
    {
139
        // get password from the user details or generate one
140
        $password = isset($userDetails['password']) ? $userDetails['password'] : $this->faker->password;
141
142
        // hash the password and set it back at the user details
143
        $userDetails['password'] = Hash::make($password);
144
145
        return $userDetails;
146
    }
147
148
    /**
149
     * @return  array|null
150
     */
151
    private function getAccess()
152
    {
153
        return isset($this->access) ? $this->access : null;
154
    }
155
156
    /**
157
     * @param $user
158
     * @param $access
159
     *
160
     * @return  mixed
161
     */
162
    private function setupTestingUserAccess($user, $access)
163
    {
164
        $access = $access ? : $this->getAccess();
165
166
        $user = $this->setupTestingUserPermissions($user, $access);
167
        $user = $this->setupTestingUserRoles($user, $access);
168
169
        return $user;
170
    }
171
172
    /**
173
     * @param $user
174
     * @param $access
175
     *
176
     * @return  mixed
177
     */
178
    private function setupTestingUserRoles($user, $access)
179
    {
180
        if (isset($access['roles']) && !empty($access['roles'])) {
181
            if (!$user->hasRole($access['roles'])) {
182
                $user->assignRole($access['roles']);
183
            }
184
        }
185
186
        return $user;
187
    }
188
189
    /**
190
     * @param $user
191
     * @param $access
192
     *
193
     * @return  mixed
194
     */
195
    private function setupTestingUserPermissions($user, $access)
196
    {
197
        if (isset($access['permissions']) && !empty($access['permissions'])) {
198
            $user->givePermissionTo($access['permissions']);
199
        }
200
201
        return $user;
202
    }
203
204
205
    /**
206
     * @return  array
207
     */
208
    private function getNullAccess()
209
    {
210
        return [
211
            'permissions' => null,
212
            'roles'       => null
213
        ];
214
    }
215
216
}
217