ServersController   C
last analyzed

Complexity

Total Complexity 53

Size/Duplication

Total Lines 579
Duplicated Lines 0 %

Test Coverage

Coverage 32.65%

Importance

Changes 1
Bugs 1 Features 0
Metric Value
wmc 53
eloc 250
dl 0
loc 579
ccs 32
cts 98
cp 0.3265
rs 6.96
c 1
b 1
f 0

23 Methods

Rating   Name   Duplication   Size   Complexity  
A consoleLog() 0 7 1
A abilities() 0 23 5
A summary() 0 20 2
A save() 0 13 1
A search() 0 4 1
A restart() 0 22 4
A handleException() 0 12 2
A allServersAbilities() 0 31 6
A update() 0 20 3
A __construct() 0 18 1
A store() 0 11 1
A get() 0 56 2
A makeErrorResponse() 0 6 1
A destroy() 0 15 3
A getList() 0 29 2
A install() 0 20 3
A start() 0 22 4
A getDocMessage() 0 9 3
A sendCommand() 0 9 1
A reinstall() 0 14 2
A query() 0 7 1
A getStatus() 0 6 1
A stop() 0 20 3

How to fix   Complexity   

Complex Class

Complex classes like ServersController often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use ServersController, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Gameap\Http\Controllers\API;
4
5
use Exception;
6
use Gameap\Exceptions\Repositories\GdaemonTaskRepository\EmptyServerStartCommandException;
7
use Gameap\Exceptions\Repositories\GdaemonTaskRepository\GdaemonTaskRepositoryException;
8
use Gameap\Exceptions\Repositories\RecordExistExceptions;
9
use Gameap\Helpers\PermissionHelper;
10
use Gameap\Helpers\ServerPermissionHelper;
11
use Gameap\Http\Controllers\AuthController;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Gameap\Http\Controllers\API\AuthController. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
12
use Gameap\Http\Requests\Admin\ServerDestroyRequest;
13
use Gameap\Http\Requests\API\SaveServerRequest;
14
use Gameap\Http\Requests\API\ServerConsoleCommandRequest;
15
use Gameap\Models\GdaemonTask;
16
use Gameap\Models\Server;
17
use Gameap\Models\User;
18
use Gameap\Repositories\GdaemonTaskRepository;
19
use Gameap\Repositories\ServerRepository;
20
use Gameap\Services\ServerControlService;
21
use Gameap\Services\ServerService;
22
use Gameap\UseCases\Commands\CreateGameServerCommand;
23
use Gameap\UseCases\Commands\EditGameServerCommand;
24
use Gameap\UseCases\CreateGameServer;
25
use Gameap\UseCases\EditGameServer;
26
use Illuminate\Contracts\Auth\Factory as AuthFactory;
27
use Psr\SimpleCache\CacheInterface;
28
use Illuminate\Http\Request;
29
use Illuminate\Http\Response;
30
use Symfony\Component\Serializer\SerializerInterface;
31
32
class ServersController extends AuthController
33
{
34
    /**
35
     * The ServerRepository instance.
36
     *
37
     * @var \Gameap\Repositories\ServerRepository
38
     */
39
    public $repository;
40
41
    /**
42
     * The GdaemonTaskRepository instance.
43
     *
44
     * @var GdaemonTaskRepository
45
     */
46
    public $gdaemonTaskRepository;
47
48 9
    /** @var \Gameap\Services\ServerService  */
49
    public $serverService;
50
51
    /** @var \Gameap\Services\ServerControlService */
52
    public $serverControlService;
53
54 9
    /** @var SerializerInterface */
55
    protected $serializer;
56 9
57 9
    /** @var AuthFactory */
58 9
    protected $authFactory;
59 9
60 9
    /** @var CacheInterface */
61
    protected $cache;
62
63
    /**
64
     * ServersController constructor.
65
     * @param ServerRepository $repository
66
     */
67
    public function __construct(
68
        ServerRepository $repository,
69 9
        GdaemonTaskRepository $gdaemonTaskRepository,
70
        ServerService $serverService,
71 9
        ServerControlService $serverControlService,
72 9
        SerializerInterface $serializer,
73
        AuthFactory $authFactory,
74
        CacheInterface $cache
75 9
    ) {
76 6
        parent::__construct();
77 3
78 3
        $this->repository            = $repository;
79 3
        $this->gdaemonTaskRepository = $gdaemonTaskRepository;
80 3
        $this->serverService         = $serverService;
81 3
        $this->serverControlService  = $serverControlService;
82
        $this->serializer            = $serializer;
83
        $this->authFactory           = $authFactory;
84 3
        $this->cache                 = $cache;
85
    }
86
87
    /**
88
     * @param Server $server
89
     *
90 6
     * @return array|\Illuminate\Http\JsonResponse
91
     *
92
     * @throws \Illuminate\Auth\Access\AuthorizationException
93
     */
94
    public function get(Server $server)
95
    {
96
        $this->authorize(ServerPermissionHelper::CONTROL_ABILITY, $server);
97
98
        /** @var User $currentUser */
99
        $currentUser = $this->authFactory->guard()->user();
100
        $isAdmin = $currentUser->can(PermissionHelper::ADMIN_PERMISSIONS);
101
102
        if ($isAdmin) {
103
            return $server->only([
104
                'id',
105
                'uuid',
106
                'uuid_short',
107
                'enabled',
108
                'installed',
109
                'blocked',
110
                'name',
111
                'ds_id',
112
                'game_id',
113
                'game_mod_id',
114
                'server_ip',
115
                'server_port',
116
                'query_port',
117
                'rcon_port',
118
                'game',
119
                'last_process_check',
120
                'online',
121
122
                // Admin details
123
                'rcon',
124
                'dir',
125
                'su_user',
126
                'start_command',
127
                'aliases',
128
                'vars',
129
            ]);
130
        }
131
132
        return $server->only([
133
            'id',
134
            'uuid',
135
            'uuid_short',
136
            'enabled',
137
            'installed',
138
            'blocked',
139
            'name',
140
            'ds_id',
141
            'game_id',
142
            'game_mod_id',
143
            'server_ip',
144
            'server_port',
145
            'query_port',
146
            'rcon_port',
147
            'game',
148
            'last_process_check',
149
            'online',
150
        ]);
151
    }
152
153
    /**
154
     * @param Server $server
155
     *
156
     * @return array|\Illuminate\Http\JsonResponse
157
     *
158
     * @throws \Illuminate\Auth\Access\AuthorizationException
159
     */
160
    public function abilities(Server $server)
161
    {
162
        /** @var User $currentUser */
163
        $currentUser = $this->authFactory->guard()->user();
164
        $isAdmin = $currentUser->can(PermissionHelper::ADMIN_PERMISSIONS);
165
166
        if (!$isAdmin) {
167
            $servers = $this->repository->getServersForUser($currentUser->id);
168
            if (!$servers->contains($server)) {
169
                return response()->json([
170
                    'message'   => 'Forbidden',
171
                    'http_code' => Response::HTTP_FORBIDDEN,
172
                ], Response::HTTP_FORBIDDEN);
173
            }
174
        }
175
176
        $abilities = [];
177
178
        foreach (ServerPermissionHelper::getAllPermissions() as $permission) {
179
            $abilities[$permission] = $isAdmin || $currentUser->can($permission, $server);
180
        }
181
182
        return $abilities;
183
    }
184
185
    /**
186
     * @param Server $server
187
     *
188
     * @return array|\Illuminate\Http\JsonResponse
189
     *
190
     * @throws \Illuminate\Auth\Access\AuthorizationException
191
     */
192
    public function start(Server $server)
193
    {
194
        $this->authorize(ServerPermissionHelper::CONTROL_ABILITY, $server);
195
        $this->authorize(ServerPermissionHelper::START_ABILITY, $server);
196
197
        try {
198
            $gdaemonTaskId = $this->serverControlService->start($server);
199
        } catch (GdaemonTaskRepositoryException $exception) {
200
            return $this->handleException($exception);
201
        } catch (RecordExistExceptions $exception) {
202
            $gdaemonTaskId = $this->gdaemonTaskRepository->getOneWorkingTaskId(
203
                $server->id,
204
                GdaemonTask::TASK_SERVER_START
205
            );
206
207
            if (!$gdaemonTaskId) {
208
                return $this->makeErrorResponse($exception->getMessage());
209
            }
210
        }
211
212
        return [
213
            'gdaemonTaskId' => $gdaemonTaskId,
214
        ];
215
    }
216
217
    /**
218
     * @param Server $server
219
     *
220
     * @return array|\Illuminate\Http\JsonResponse
221
     *
222
     * @throws \Illuminate\Auth\Access\AuthorizationException
223
     */
224
    public function stop(Server $server)
225
    {
226
        $this->authorize(ServerPermissionHelper::CONTROL_ABILITY, $server);
227
        $this->authorize(ServerPermissionHelper::STOP_ABILITY, $server);
228
229
        try {
230
            $gdaemonTaskId = $this->serverControlService->stop($server);
231
        } catch (RecordExistExceptions $exception) {
232
            $gdaemonTaskId = $this->gdaemonTaskRepository->getOneWorkingTaskId(
233
                $server->id,
234
                GdaemonTask::TASK_SERVER_STOP
235
            );
236
237
            if (!$gdaemonTaskId) {
238
                return $this->makeErrorResponse($exception->getMessage());
239
            }
240
        }
241
242
        return [
243
            'gdaemonTaskId' => $gdaemonTaskId,
244
        ];
245
    }
246
247
    /**
248
     * @param Server $server
249
     * @return array|\Illuminate\Http\JsonResponse
250
     *
251
     * @throws \Gameap\Exceptions\Repositories\RecordExistExceptions
252
     * @throws \Illuminate\Auth\Access\AuthorizationException
253
     */
254
    public function restart(Server $server)
255
    {
256
        $this->authorize(ServerPermissionHelper::CONTROL_ABILITY, $server);
257
        $this->authorize(ServerPermissionHelper::RESTART_ABILITY, $server);
258
259
        try {
260
            $gdaemonTaskId = $this->serverControlService->restart($server);
261
        } catch (GdaemonTaskRepositoryException $exception) {
262
            return $this->handleException($exception);
263
        } catch (RecordExistExceptions $exception) {
264
            $gdaemonTaskId = $this->gdaemonTaskRepository->getOneWorkingTaskId(
265
                $server->id,
266
                GdaemonTask::TASK_SERVER_RESTART
267
            );
268
269
            if (!$gdaemonTaskId) {
270
                return $this->makeErrorResponse($exception->getMessage());
271
            }
272
        }
273
274
        return [
275
            'gdaemonTaskId' => $gdaemonTaskId,
276
        ];
277
    }
278
279
    /**
280
     * @param Server $server
281
     * @return array|\Illuminate\Http\JsonResponse
282
     *
283
     * @throws \Illuminate\Auth\Access\AuthorizationException
284
     */
285
    public function update(Server $server)
286
    {
287
        $this->authorize(ServerPermissionHelper::CONTROL_ABILITY, $server);
288
        $this->authorize(ServerPermissionHelper::UPDATE_ABILITY, $server);
289
290
        try {
291 3
            $gdaemonTaskId = $this->serverControlService->update($server);
292
        } catch (RecordExistExceptions $exception) {
293 3
            $gdaemonTaskId = $this->gdaemonTaskRepository->getOneWorkingTaskId(
294 3
                $server->id,
295
                GdaemonTask::TASK_SERVER_UPDATE
296
            );
297
298
            if (!$gdaemonTaskId) {
299 3
                return $this->makeErrorResponse($exception->getMessage());
300
            }
301
        }
302
303
        return [
304
            'gdaemonTaskId' => $gdaemonTaskId,
305
        ];
306 3
    }
307
308 3
    /**
309
     * @param Server $server
310 3
     * @return array|\Illuminate\Http\JsonResponse
311
     *
312
     * @throws \Illuminate\Auth\Access\AuthorizationException
313
     */
314 3
    public function install(Server $server)
315
    {
316
        $this->authorize(ServerPermissionHelper::CONTROL_ABILITY, $server);
317
        $this->authorize(ServerPermissionHelper::UPDATE_ABILITY, $server);
318
319
        try {
320
            $gdaemonTaskId = $this->serverControlService->install($server);
321
        } catch (RecordExistExceptions $exception) {
322 3
            $gdaemonTaskId = $this->gdaemonTaskRepository->getOneWorkingTaskId(
323
                $server->id,
324 3
                GdaemonTask::TASK_SERVER_INSTALL
325 3
            );
326 3
327 1
            if (!$gdaemonTaskId) {
328
                return $this->makeErrorResponse($exception->getMessage());
329
            }
330
        }
331
332
        return [
333
            'gdaemonTaskId' => $gdaemonTaskId,
334
        ];
335
    }
336
337
    /**
338
     * @param Server $server
339
     * @return array|\Illuminate\Http\JsonResponse
340
     *
341
     * @throws \Gameap\Exceptions\Repositories\RecordExistExceptions
342
     * @throws \Illuminate\Auth\Access\AuthorizationException
343
     */
344
    public function reinstall(Server $server)
345
    {
346
        $this->authorize(ServerPermissionHelper::CONTROL_ABILITY, $server);
347
        $this->authorize(ServerPermissionHelper::UPDATE_ABILITY, $server);
348
349
        try {
350
            $deleteTaskId  = $this->gdaemonTaskRepository->addServerDelete($server);
351
            $gdaemonTaskId = $this->gdaemonTaskRepository->addServerInstall($server, $deleteTaskId);
352
        } catch (RecordExistExceptions $exception) {
353
            return $this->makeErrorResponse($exception->getMessage());
354
        }
355
356
        return [
357
            'gdaemonTaskId' => $gdaemonTaskId,
358
        ];
359
    }
360
361
    /**
362
     * Get server status
363
     * @param Server $server
364
     * @return array
365
     *
366
     * @throws \Illuminate\Auth\Access\AuthorizationException
367
     */
368
    public function getStatus(Server $server)
369
    {
370
        $this->authorize(ServerPermissionHelper::CONTROL_ABILITY, $server);
371
372
        return [
373
            'processActive' => $server->processActive(),
374
        ];
375
    }
376
377
    /**
378
     * @param Server $server
379
     * @return array
380
     *
381
     * @throws \Illuminate\Auth\Access\AuthorizationException
382
     */
383
    public function query(Server $server)
384
    {
385
        $this->authorize(ServerPermissionHelper::CONTROL_ABILITY, $server);
386
387
        $query = $this->serverService->query($server);
388
389
        return $query;
390
    }
391
392
    /**
393
     * @param Server $server
394
     * @return array
395
     *
396
     * @throws \Illuminate\Auth\Access\AuthorizationException
397
     */
398
    public function consoleLog(Server $server)
399
    {
400
        $this->authorize(ServerPermissionHelper::CONTROL_ABILITY, $server);
401
        $this->authorize(ServerPermissionHelper::CONSOLE_VIEW_ABILITY, $server);
402
403
        return [
404
            'console' => $this->serverService->getConsoleLog($server),
405
        ];
406
    }
407
408
    /**
409
     * @param ServerConsoleCommandRequest $request
410
     * @param Server $server
411
     * @return array
412
     *
413
     * @throws \Illuminate\Auth\Access\AuthorizationException
414
     */
415
    public function sendCommand(ServerConsoleCommandRequest $request, Server $server)
416
    {
417
        $this->authorize(ServerPermissionHelper::CONTROL_ABILITY, $server);
418
        $this->authorize(ServerPermissionHelper::CONSOLE_SEND_ABILITY, $server);
419
420
        $command = $request->input('command');
421
        $this->serverService->sendConsoleCommand($server, $command);
422
423
        return ['message' => 'success'];
424
    }
425
426
    public function search(Request $request)
427
    {
428
        $query = $request->input('q');
429
        return $this->repository->search($query);
430
    }
431
432
    public function getList()
433
    {
434
        /** @var User $currentUser */
435
        $currentUser = $this->authFactory->guard()->user();
436
437
        if ($currentUser->can(PermissionHelper::ADMIN_PERMISSIONS)) {
438
            $collection = $this->repository->getAllServers()->collect();
439
        } else {
440
            $collection = $this->repository->getServersForUser($currentUser->id);
441
        }
442
443
        return $collection->map(function ($item) {
444
            return $item->only([
445
                'id',
446
                'uuid',
447
                'uuid_short',
448
                'enabled',
449
                'installed',
450
                'blocked',
451
                'name',
452
                'ds_id',
453
                'game_id',
454
                'game_mod_id',
455
                'server_ip',
456
                'server_port',
457
                'query_port',
458
                'rcon_port',
459
                'game',
460
                'online'
461
            ]);
462
        });
463
    }
464
465
    public function allServersAbilities()
466
    {
467
        /** @var User $currentUser */
468
        $currentUser = $this->authFactory->guard()->user();
469
470
        $cacheKey = 'users:' . $currentUser->id . ':servers-abilities';
471
472
        if ($this->cache->has($cacheKey)) {
473
            return $this->cache->get($cacheKey);
474
        }
475
476
        $isAdmin = $currentUser->can(PermissionHelper::ADMIN_PERMISSIONS);
477
478
        if ($isAdmin) {
479
            $servers = $this->repository->getAllServers()->collect();
480
        } else {
481
            $servers = $this->repository->getServersForUser($currentUser->id);
482
        }
483
484
        $abilities = [];
485
        foreach ($servers as $server) {
486
            $abilities[$server->id] = [];
487
488
            foreach (ServerPermissionHelper::getAllPermissions() as $permission) {
489
                $abilities[$server->id][$permission] = $isAdmin || $currentUser->can($permission, $server);
490
            }
491
        }
492
493
        $this->cache->set($cacheKey, $abilities, 60);
494
495
        return $abilities;
496
    }
497
498
    public function summary()
499
    {
500
        /** @var User $currentUser */
501
        $currentUser = $this->authFactory->guard()->user();
502
503
        if ($currentUser->can(PermissionHelper::ADMIN_PERMISSIONS)) {
504
            $collection = $this->repository->getAllServers()->collect();
505
        } else {
506
            $collection = $this->repository->getServersForUser($currentUser->id);
507
        }
508
509
        $total = $collection->count();
510
        $online = $collection->filter(function ($item) {
511
            return $item->online;
512
        })->count();
513
514
        return [
515
            'total' => $total,
516
            'online' => $online,
517
            'offline' => $total - $online,
518
        ];
519
    }
520
521
    public function store(SaveServerRequest $request, CreateGameServer $createGameServer): array
522
    {
523
        /** @var CreateGameServerCommand $command */
524
        $command = $this->serializer->denormalize(
525
            $request->all(),
526
            CreateGameServerCommand::class,
527
        );
528
529
        $result = $createGameServer($command);
530
531
        return ['message' => 'success', 'result' => $result];
532
    }
533
534
    public function save(int $id, SaveServerRequest $request, EditGameServer $saveGameServer): array
535
    {
536
        /** @var EditGameServerCommand $command */
537
        $command = $this->serializer->denormalize(
538
            $request->all(),
539
            EditGameServerCommand::class,
540
        );
541
542
        $command->id = $id;
543
544
        $result = $saveGameServer($command);
545
546
        return ['message' => 'success', 'result' => $result->id];
547
    }
548
549
    public function destroy(ServerDestroyRequest $request, Server $server)
550
    {
551
        if ($request->input('delete_files')) {
552
            try {
553
                $this->gdaemonTaskRepository->addServerDelete($server);
554
            } catch (RecordExistExceptions $e) {
555
                // Nothing
556
            }
557
558
            $server->delete();
559
        } else {
560
            $server->forceDelete();
561
        }
562
563
        return ['message' => 'success'];
564
    }
565
566
    /**
567
     * @param Exception $exception
568
     *
569
     * @return \Illuminate\Http\JsonResponse
570
     */
571
    private function handleException(\Throwable $exception)
572
    {
573
        /** @var User $currentUser */
574
        $currentUser = $this->authFactory->guard()->user();
575
576
        if ($currentUser->can(PermissionHelper::ADMIN_PERMISSIONS)) {
577
            $extraMessage = $this->getDocMessage($exception);
578
        } else {
579
            $extraMessage = (string)__('main.common_admin_error');
580
        }
581
582
        return $this->makeErrorResponse($exception->getMessage() . $extraMessage);
583
    }
584
585
    /**
586
     * @param Exception $exception
587
     * @return string
588
     */
589
    private function getDocMessage(\Throwable $exception)
590
    {
591
        $msg = '';
592
593
        if ($exception instanceof EmptyServerStartCommandException) {
594
            $msg = __('gdaemon_tasks.empty_server_start_command_doc');
595
        }
596
597
        return is_string($msg) ? $msg : '';
598
    }
599
600
    /**
601
     * @param $message
602
     * @param int $code
603
     * @return \Illuminate\Http\JsonResponse
604
     */
605
    private function makeErrorResponse($message, $code = Response::HTTP_UNPROCESSABLE_ENTITY)
606
    {
607
        return response()->json([
608
            'message'   => $message,
609
            'http_code' => $code,
610
        ], $code);
611
    }
612
}
613