Passed
Push — dev5 ( 8c60e2...9d175d )
by Ron
09:02
created

UserController   A

Complexity

Total Complexity 35

Size/Duplication

Total Lines 355
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 176
c 1
b 0
f 0
dl 0
loc 355
ccs 174
cts 174
cp 1
rs 9.6
wmc 35

11 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A destroy() 0 41 4
A checkUser() 0 17 3
A reactivateUser() 0 8 1
A show() 0 19 2
A update() 0 38 2
B edit() 0 44 9
A create() 0 31 6
A submitPassword() 0 53 5
A index() 0 12 1
A store() 0 45 1
1
<?php
2
3
namespace App\Http\Controllers\Admin;
4
5
use App\User;
6
use Carbon\Carbon;
7
use App\UserSettings;
8
use App\UserRoleType;
9
use App\UserInitialize;
10
use Illuminate\Support\Str;
11
use Illuminate\Http\Request;
12
use Illuminate\Validation\Rule;
13
use App\Notifications\NewUserEmail;
14
use Illuminate\Support\Facades\Log;
15
use Illuminate\Support\Facades\Auth;
16
use App\Http\Controllers\Controller;
17
use Illuminate\Support\Facades\Route;
18
use App\Http\Resources\UserCollection;
19
use App\Http\Resources\User as UserResource;
20
use Illuminate\Support\Facades\Notification;
21
22
class UserController extends Controller
23
{
24
    //  Constructor sets up middleware
25 142
    public function __construct()
26
    {
27 142
        $this->middleware('auth')->except('initializeUser', 'submitInitializeUser');
28
        $this->middleware(function($request, $next) {
29 122
            $this->authorize('hasAccess', 'Manage Users');
30 102
            return $next($request);
31 142
        });
32 142
    }
33
34
    //  Show the list of current users to edit
35 2
    public function index()
36
    {
37 2
        Log::debug('Route ' . Route::currentRouteName() . ' visited by ' . Auth::user()->full_name);
38
39 2
        $userList = User::with('LastUserLogin')->get()->makeVisible('user_id');
40 2
        $route    = 'admin.user.edit';
41
42 2
        Log::debug('User list:', $userList->toArray());
43
44 2
        return view('admin.userIndex', [
45 2
            'userList' => $userList,
46 2
            'route'    => $route,
47
        ]);
48
    }
49
50
    //  Check if a username is in use
51 12
    public function checkUser($username, $type)
52
    {
53 12
        Log::debug('Route '.Route::currentRouteName().' visited by '.Auth::user()->full_name.'. Submitted Data:', ['username' => $username, 'type' => $type]);
54
55 12
        $user = User::where($type, $username)->first();
56
57 12
        if(!$user)
58
        {
59 4
            Log::debug('Username '.$username.' is available for use');
60 4
            return response()->json(['duplicate' => false]);
61
        }
62
63 8
        Log::debug('Username '.$username.' is in use by '.$user->full_name);
64 8
        return response()->json([
65 8
            'duplicate' => true,
66 8
            'user'      => $user->full_name,
67 8
            'active'    => $user->deleted_at == null ? 1 : 0,
68
        ]);
69
    }
70
71
    //  Show the Add User form
72 8
    public function create()
73
    {
74 8
        Log::debug('Route ' . Route::currentRouteName() . ' visited by ' . Auth::user()->full_name);
75
76 8
        $roles = UserRoleType::all();
77 8
        $roleArr = [];
78
        //  Cycle through the roles and determine if admin and installer roles should be removed
79 8
        foreach($roles as $role)
80
        {
81 8
            if($role->role_id == 1 && Auth::user()->role_id != 1)
82
            {
83 4
                Log::debug('Installer Role skipped for User '.Auth::user()->full_name);
84 4
                continue;
85
            }
86 8
            else if($role->role_id == 2 && Auth::user()->role_id > 2)
87
            {
88 2
                Log::debug('Admin Role skipped for User '.Auth::user()->full_name);
89 2
                continue;
90
            }
91
            else
92
            {
93 8
                $roleArr[] = [
94 8
                    'value' => $role->role_id,
95 8
                    'text'  => $role->name,
96
                ];
97
            }
98
        }
99
100 8
        Log::debug('Role data gathered: ', $roleArr);
101 8
        return view('admin.newUser', [
102 8
            'roles' => $roleArr
103
        ]);
104
    }
105
106
    //  Submit the Add User form
107 16
    public function store(Request $request)
108
    {
109 16
        Log::debug('Route '.Route::currentRouteName().' visited by '.Auth::user()->full_name.'. Submitted Data:', $request->toArray());
110
111
        //  Validate the new user form
112 16
        $request->validate([
113 16
            'role'       => 'required|numeric|exists:user_role_types,role_id',
114
            'username'   => 'required|unique:users|regex:/^[a-zA-Z0-9_]*$/',
115
            'first_name' => 'required',
116
            'last_name'  => 'required',
117
            'email'      => 'required|unique:users',
118
        ]);
119
120
        //  Create the user
121 2
        $newUser = User::create([
122 2
            'role_id'    => $request->role,
123 2
            'username'   => $request->username,
124 2
            'first_name' => $request->first_name,
125 2
            'last_name'  => $request->last_name,
126 2
            'email'      => $request->email,
127 2
            'password'   => bcrypt(strtolower(Str::random(15))),
128
        ]);
129 2
        $userID = $newUser->user_id;
130 2
        Log::debug('New User created.  Data - ', $newUser->toArray());
131
        //  Create the user settings table
132 2
        UserSettings::create([
133 2
            'user_id' => $userID,
134
        ]);
135 2
        Log::debug('User Settings table created for user ID '.$userID);
136
137
        //  Create the setup user link
138 2
        $hash = strtolower(Str::random(30));
139 2
        UserInitialize::create([
140 2
            'username' => $request->username,
141 2
            'token'    => $hash
142
        ]);
143 2
        Log::debug('User Initialize link created for User ID '.$userID.'. New Link Hash - '.$hash);
144
145
        //  Email the new user
146 2
        Notification::send($newUser, new NewUserEmail($newUser, $hash));
147
148 2
        Log::notice('New user '.$newUser->first_name.' '.$newUser->last_name.' created by '.Auth::user()->full_name.'. User Data:', $newUser->toArray());
149
150
        // return redirect()->back()->with('success', 'New User Created');
151 2
        return response()->json(['success' => true]);
152
    }
153
154
    //  List all inactive users
155 6
    public function show($type)
156
    {
157 6
        Log::debug('Route ' . Route::currentRouteName() . ' visited by ' . Auth::user()->full_name);
158 6
        $route = '';
159
160 6
        if($type !== 'inactive')
161
        {
162 2
            Log::error('Someone tried to access the Inactive Users link with an improper argument - Argument: '.$type);
163 2
            return abort(404);
1 ignored issue
show
Bug introduced by
Are you sure the usage of abort(404) is correct as it seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
164
        }
165 4
        $userList = new UserCollection(User::onlyTrashed()->get()
166
                /** @scrutinizer ignore-call */
167 4
                ->makeVisible('user_id')
168 4
                ->makeVisible('deleted_at'));
169
170 4
        Log::debug('List of inactive users - ', array($userList));
171 4
        return view('admin.userDeleted', [
172 4
            'userList' => $userList,
173 4
            'route'    => $route,
174
        ]);
175
    }
176
177
    //  Reactivate a disabled user
178 4
    public function reactivateUser($id)
179
    {
180 4
        Log::debug('Route ' . Route::currentRouteName() . ' visited by ' . Auth::user()->full_name);
181 4
        User::withTrashed()->where('user_id', $id)->restore();
182
183 4
        Log::notice('User ID ' . $id . ' reactivated by ' . Auth::user()->full_name);
184 4
        return response()->json([
185 4
            'success' => true,
186
        ]);
187
    }
188
189
    //  Open the edit user form
190 12
    public function edit($id)
191
    {
192 12
        Log::debug('Route ' . Route::currentRouteName() . ' visited by ' . Auth::user()->full_name);
193
194 12
        $roles = UserRoleType::all();
195 12
        $user  = new UserResource(User::findOrFail($id));
196
197
        //  Make sure that the user is not trying to edit someone with more permissions
198 10
        if(($user->role_id == 1 || $user->role_id == 2) && Auth::user()->role_id <=2)
199
        {
200 2
            Log::warning('User '.Auth::user()->full_name.' tried to update user ID '.$id.' that has more permissions than they do.  This request was denied.');
201 2
            return abort(403);
202
        }
203
204 8
        Log::debug('User Data gathered - ', array($user));
205
206
        //  Good to go - get role information
207 8
        $roleArr = [];
208 8
        foreach ($roles as $role)
209
        {
210 8
            if ($role->role_id == 1 && Auth::user()->role_id != 1)
211
            {
212 4
                continue;
213
            }
214 8
            else if ($role->role_id == 2 && Auth::user()->role_id > 2)
215
            {
216 2
                continue;
217
            }
218
            else
219
            {
220
                // $roleArr[$role->role_id] = $role->name;
221 8
                $roleArr[] = [
222 8
                    'value' => $role->role_id,
223 8
                    'text'  => $role->name,
224
                ];
225
            }
226
        }
227
228 8
        Log::debug('Role Data gathered:', $roleArr);
229 8
        return view('admin.userEdit', [
230 8
            'roles' => $roleArr,
231
            'user'  => $user->
232
            /** @scrutinizer ignore-call */
233 8
            makeVisible(['user_id', 'username']),
234
        ]);
235
    }
236
237
    //  Submit the update user form
238 22
    public function update(Request $request, $id)
239
    {
240 22
        Log::debug('Route '.Route::currentRouteName().' visited by '.Auth::user()->full_name.'. Submitted Data:', $request->toArray());
241
242 22
        $request->validate([
243
            'username'   => [
244 22
                                'required',
245 22
                                Rule::unique('users')->ignore($id, 'user_id')
246
                            ],
247 22
            'first_name' => 'required',
248 22
            'last_name'  => 'required',
249
            'email'      => [
250 22
                                'required',
251 22
                                Rule::unique('users')->ignore($id, 'user_id')
252
                            ],
253 22
            'role'       => 'required',
254
        ]);
255
256
        //  Update the user data
257 8
        $user = User::findOrFail($id);
258 6
        if($user->role_id < Auth::user()->role_id)
259
        {
260 2
            Log::warning('User ' . Auth::user()->full_name . ' tried to update user ID ' . $id . ' that has more permissions than they do.  This request was denied.');
261 2
            return abort(403);
1 ignored issue
show
Bug introduced by
Are you sure the usage of abort(403) is correct as it seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
262
        }
263
264 4
        $user->update(
265
        [
266 4
            'username'   => $request->username,
267 4
            'first_name' => $request->first_name,
268 4
            'last_name'  => $request->last_name,
269 4
            'email'      => $request->email,
270 4
            'role_id'    => $request->role,
271
        ]);
272
273
        //  Update the user's role
274 4
        Log::info('User information for '.$request->first_name.' '.$request->last_name.' (ID: '.$id.') has been updated by '.Auth::user()->full_name);
275 4
        return response()->json(['success' => true]);
276
    }
277
278
    //  Submit the change password form
279 12
    public function submitPassword(Request $request)
280
    {
281 12
        Log::debug('Route '.Route::currentRouteName().' visited by '.Auth::user()->full_name);
282
283 12
        $request->validate([
284 12
            'password' => 'required|string|min:6|confirmed',
285
            'user_id'  => 'required',
286
        ]);
287
288 8
        if($request->force_change)
289
        {
290 6
            $nextChange = Carbon::now()->subDay();
291
        }
292
        else
293
        {
294 2
            $nextChange = config('auth.passwords.settings.expire') != null ? Carbon::now()->addDays(config('auth.passwords.settings.expire')) : null;
295
        }
296
297 8
        $user = User::find($request->user_id);
298
299
        //  Verify this is a valid user ID
300 8
        if (!$user)
301
        {
302 2
            $success = false;
303 2
            $reason  = 'Cannot find user with this ID';
304
        }
305
        //  Make sure that the user is not trying to deactivate someone with more permissions
306 6
        else if ($user->role_id < Auth::user()->role_id)
307
        {
308 2
            $success = false;
309 2
            $reason  = 'You cannot change password for a user with higher permissions that you.  If this user has locked themselves out, have then use the reset link on the login page.';
310
        }
311
        //  Good to go - update user password
312
        else
313
        {
314
            //  Update the user data
315 4
            $user->update(
316
            [
317 4
                'password'         => bcrypt($request->password),
318 4
                'password_expires' => $nextChange
319
            ]);
320 4
            $success = true;
321 4
            $reason  = 'Password for '.$user->full_name.' successfully reset.';
322
        }
323
324 8
        Log::notice('User ID-'.$request->user_id.' password chagned by '.Auth::user()->Full_name, [
325 8
            'success' => $success,
326 8
            'reason'  => $reason,
327
        ]);
328
329 8
        return response()->json([
330 8
            'success' => $success,
331 8
            'reason'  => $reason,
332
        ]);
333
    }
334
335
    //  Disable the user
336 8
    public function destroy($id)
337
    {
338 8
        Log::debug('Route ' . Route::currentRouteName() . ' visited by ' . Auth::user()->full_name);
339
340 8
        $user = User::find($id);
341
342
        //  Verify this is a valid user ID
343 8
        if(!$user)
344
        {
345 2
            $success = false;
346 2
            $reason  = 'Cannot find user with this ID';
347
        }
348
        //  Make suer that the user is not trying to deactivate themselves
349 6
        else if(Auth::user()->user_id == $id)
350
        {
351 2
            $success = false;
352 2
            $reason  = 'You cannot deactivate yourself';
353
        }
354
        //  Make sure that the user is not trying to deactivate someone with more permissions
355 4
        else if($user->role_id < Auth::user()->role_id)
356
        {
357 2
            $success = false;
358 2
            $reason  = 'You cannot deactivate a user with higher permissions that you.';
359
        }
360
        //  Good to go - deactivate user
361
        else
362
        {
363
            // $user->update(['active' => 0]);
364 2
            $user->delete();
365 2
            $success = true;
366 2
            $reason  = 'User '.$user->full_name.' successfully deactivated.';
367
        }
368
369 8
        Log::notice('User ID-'.$id.' disabled by '.Auth::user()->full_name, [
370 8
            'success' => $success,
371 8
            'reason'  => $reason,
372
        ]);
373
374 8
        return response()->json([
375 8
            'success' => $success,
376 8
            'reason'  => $reason,
377
        ]);
378
    }
379
}
380