Browse Source

Merge pull request #225 from ControlPanel-gg/api_improvements

Api improvements
AVMG 3 years ago
parent
commit
5902819776

+ 25 - 3
app/Http/Controllers/Api/NotificationController.php

@@ -6,11 +6,13 @@ use App\Http\Controllers\Controller;
 use App\Models\DiscordUser;
 use App\Models\DiscordUser;
 use App\Models\User;
 use App\Models\User;
 use App\Notifications\DynamicNotification;
 use App\Notifications\DynamicNotification;
+use Illuminate\Database\Eloquent\Builder;
 use Illuminate\Http\JsonResponse;
 use Illuminate\Http\JsonResponse;
 use Illuminate\Http\Request;
 use Illuminate\Http\Request;
 use Illuminate\Notifications\Messages\MailMessage;
 use Illuminate\Notifications\Messages\MailMessage;
 use Illuminate\Support\Facades\Notification;
 use Illuminate\Support\Facades\Notification;
 use Illuminate\Support\HtmlString;
 use Illuminate\Support\HtmlString;
+use Illuminate\Validation\ValidationException;
 use Spatie\ValidationRules\Rules\Delimited;
 use Spatie\ValidationRules\Rules\Delimited;
 
 
 class NotificationController extends Controller
 class NotificationController extends Controller
@@ -55,19 +57,21 @@ class NotificationController extends Controller
      *
      *
      * @param Request $request
      * @param Request $request
      * @return JsonResponse
      * @return JsonResponse
+     * @throws ValidationException
      */
      */
     public function send(Request $request)
     public function send(Request $request)
     {
     {
         $data = $request->validate([
         $data = $request->validate([
             "via" => ["required", new Delimited("in:mail,database")],
             "via" => ["required", new Delimited("in:mail,database")],
             "all" => "required_without:users|boolean",
             "all" => "required_without:users|boolean",
-            "users" => ["required_without:all", new Delimited("exists:users,id")],
+            "users" => ["required_without:all"],
             "title" => "required|string|min:1",
             "title" => "required|string|min:1",
             "content" => "required|string|min:1"
             "content" => "required|string|min:1"
         ]);
         ]);
         $via = explode(",", $data["via"]);
         $via = explode(",", $data["via"]);
         $mail = null;
         $mail = null;
         $database = null;
         $database = null;
+
         if (in_array("database", $via)) {
         if (in_array("database", $via)) {
             $database = [
             $database = [
                 "title" => $data["title"],
                 "title" => $data["title"],
@@ -79,10 +83,28 @@ class NotificationController extends Controller
                 ->subject($data["title"])
                 ->subject($data["title"])
                 ->line(new HtmlString($data["content"]));
                 ->line(new HtmlString($data["content"]));
         }
         }
+
         $all = $data["all"] ?? false;
         $all = $data["all"] ?? false;
-        $users = $all ? User::all() : User::whereIn("id", explode(",", $data["users"]))->get();
+        if ($all) {
+            $users = User::all();
+        } else {
+            $userIds = explode(",", $data["users"]);
+            $users = User::query()
+                ->whereIn("id", $userIds)
+                ->orWhereHas('discordUser', function (Builder $builder) use ($userIds) {
+                    $builder->whereIn('id', $userIds);
+                })
+                ->get();
+        }
+
+        if ($users->count() == 0) {
+            throw ValidationException::withMessages([
+                'users' => ['No users found!'],
+            ]);
+        }
+
         Notification::send($users, new DynamicNotification($via, $database, $mail));
         Notification::send($users, new DynamicNotification($via, $database, $mail));
-        return response()->json(["message" => "Notification successfully sent."]);
+        return response()->json(["message" => "Notification successfully sent.", 'user_count' => $users->count()]);
     }
     }
 
 
     /**
     /**

+ 16 - 5
app/Http/Controllers/Api/ServerController.php

@@ -6,11 +6,16 @@ use App\Http\Controllers\Controller;
 use App\Models\Server;
 use App\Models\Server;
 use Exception;
 use Exception;
 use Illuminate\Contracts\Pagination\LengthAwarePaginator;
 use Illuminate\Contracts\Pagination\LengthAwarePaginator;
+use Illuminate\Database\Eloquent\Collection;
 use Illuminate\Http\JsonResponse;
 use Illuminate\Http\JsonResponse;
 use Illuminate\Http\Request;
 use Illuminate\Http\Request;
+use Spatie\QueryBuilder\QueryBuilder;
 
 
 class ServerController extends Controller
 class ServerController extends Controller
 {
 {
+    const ALLOWED_INCLUDES = ['product', 'user'];
+    const ALLOWED_FILTERS = ['name', 'suspended', 'identifier', 'pterodactyl_id', 'user_id', 'product_id'];
+
     /**
     /**
      * Display a listing of the resource.
      * Display a listing of the resource.
      *
      *
@@ -19,21 +24,27 @@ class ServerController extends Controller
      */
      */
     public function index(Request $request)
     public function index(Request $request)
     {
     {
-        return Server::with('product')->paginate($request->query('per_page') ?? 50);
-    }
+        $query = QueryBuilder::for(Server::class)
+            ->allowedIncludes(self::ALLOWED_INCLUDES)
+            ->allowedFilters(self::ALLOWED_FILTERS);
 
 
+        return $query->paginate($request->input('per_page') ?? 50);
+    }
 
 
     /**
     /**
      * Display the specified resource.
      * Display the specified resource.
      *
      *
      * @param Server $server
      * @param Server $server
-     * @return Server
+     * @return Server|Collection
      */
      */
     public function show(Server $server)
     public function show(Server $server)
     {
     {
-        return $server->load('product');
-    }
+        $query = QueryBuilder::for(Server::class)
+            ->where('id', '=', $server->id)
+            ->allowedIncludes(self::ALLOWED_INCLUDES);
 
 
+        return $query->get();
+    }
 
 
     /**
     /**
      * Remove the specified resource from storage.
      * Remove the specified resource from storage.

+ 92 - 21
app/Http/Controllers/Api/UserController.php

@@ -2,28 +2,44 @@
 
 
 namespace App\Http\Controllers\Api;
 namespace App\Http\Controllers\Api;
 
 
+use App\Classes\Pterodactyl;
 use App\Events\UserUpdateCreditsEvent;
 use App\Events\UserUpdateCreditsEvent;
 use App\Http\Controllers\Controller;
 use App\Http\Controllers\Controller;
+use App\Models\Configuration;
 use App\Models\DiscordUser;
 use App\Models\DiscordUser;
 use App\Models\User;
 use App\Models\User;
 use Illuminate\Contracts\Foundation\Application;
 use Illuminate\Contracts\Foundation\Application;
+use Illuminate\Contracts\Pagination\LengthAwarePaginator;
 use Illuminate\Contracts\Routing\ResponseFactory;
 use Illuminate\Contracts\Routing\ResponseFactory;
+use Illuminate\Database\Eloquent\Builder;
+use Illuminate\Database\Eloquent\Collection;
 use Illuminate\Http\Request;
 use Illuminate\Http\Request;
 use Illuminate\Http\Response;
 use Illuminate\Http\Response;
+use Illuminate\Support\Facades\App;
+use Illuminate\Support\Facades\Hash;
+use Illuminate\Support\Str;
 use Illuminate\Validation\Rule;
 use Illuminate\Validation\Rule;
 use Illuminate\Validation\ValidationException;
 use Illuminate\Validation\ValidationException;
+use Spatie\QueryBuilder\QueryBuilder;
 
 
 class UserController extends Controller
 class UserController extends Controller
 {
 {
+    const ALLOWED_INCLUDES = ['servers', 'notifications', 'payments', 'vouchers', 'discordUser'];
+    const ALLOWED_FILTERS = ['name', 'server_limit', 'email', 'pterodactyl_id', 'role', 'suspended'];
+
     /**
     /**
      * Display a listing of the resource.
      * Display a listing of the resource.
      *
      *
      * @param Request $request
      * @param Request $request
-     * @return Response
+     * @return LengthAwarePaginator
      */
      */
     public function index(Request $request)
     public function index(Request $request)
     {
     {
-        return User::paginate($request->query('per_page') ?? 50);
+        $query = QueryBuilder::for(User::class)
+            ->allowedIncludes(self::ALLOWED_INCLUDES)
+            ->allowedFilters(self::ALLOWED_FILTERS);
+
+        return $query->paginate($request->input('per_page') ?? 50);
     }
     }
 
 
 
 
@@ -31,12 +47,22 @@ class UserController extends Controller
      * Display the specified resource.
      * Display the specified resource.
      *
      *
      * @param int $id
      * @param int $id
-     * @return User
+     * @return User|Collection
      */
      */
     public function show(int $id)
     public function show(int $id)
     {
     {
         $discordUser = DiscordUser::find($id);
         $discordUser = DiscordUser::find($id);
-        return $discordUser ? $discordUser->user : User::findOrFail($id);
+        $user = $discordUser ? $discordUser->user : User::findOrFail($id);
+
+        $query = QueryBuilder::for($user)
+            ->with('discordUser')
+            ->allowedIncludes(self::ALLOWED_INCLUDES)
+            ->where('users.id', '=', $id)
+            ->orWhereHas('discordUser', function (Builder $builder) use ($id) {
+                $builder->where('id', '=', $id);
+            });
+
+        return $query->get();
     }
     }
 
 
 
 
@@ -53,11 +79,11 @@ class UserController extends Controller
         $user = $discordUser ? $discordUser->user : User::findOrFail($id);
         $user = $discordUser ? $discordUser->user : User::findOrFail($id);
 
 
         $request->validate([
         $request->validate([
-            "name"         => "sometimes|string|min:4|max:30",
-            "email"        => "sometimes|string|email",
-            "credits"      => "sometimes|numeric|min:0|max:1000000",
+            "name" => "sometimes|string|min:4|max:30",
+            "email" => "sometimes|string|email",
+            "credits" => "sometimes|numeric|min:0|max:1000000",
             "server_limit" => "sometimes|numeric|min:0|max:1000000",
             "server_limit" => "sometimes|numeric|min:0|max:1000000",
-            "role"         => ['sometimes', Rule::in(['admin', 'mod', 'client', 'member'])],
+            "role" => ['sometimes', Rule::in(['admin', 'mod', 'client', 'member'])],
         ]);
         ]);
 
 
         $user->update($request->all());
         $user->update($request->all());
@@ -81,23 +107,23 @@ class UserController extends Controller
         $user = $discordUser ? $discordUser->user : User::findOrFail($id);
         $user = $discordUser ? $discordUser->user : User::findOrFail($id);
 
 
         $request->validate([
         $request->validate([
-            "credits"      => "sometimes|numeric|min:0|max:1000000",
+            "credits" => "sometimes|numeric|min:0|max:1000000",
             "server_limit" => "sometimes|numeric|min:0|max:1000000",
             "server_limit" => "sometimes|numeric|min:0|max:1000000",
         ]);
         ]);
 
 
-        if($request->credits){
-             if ($user->credits + $request->credits >= 99999999) throw ValidationException::withMessages([
+        if ($request->credits) {
+            if ($user->credits + $request->credits >= 99999999) throw ValidationException::withMessages([
                 'credits' => "You can't add this amount of credits because you would exceed the credit limit"
                 'credits' => "You can't add this amount of credits because you would exceed the credit limit"
             ]);
             ]);
             event(new UserUpdateCreditsEvent($user));
             event(new UserUpdateCreditsEvent($user));
             $user->increment('credits', $request->credits);
             $user->increment('credits', $request->credits);
-         }
+        }
 
 
-        if($request->server_limit){
+        if ($request->server_limit) {
             if ($user->server_limit + $request->server_limit >= 2147483647) throw ValidationException::withMessages([
             if ($user->server_limit + $request->server_limit >= 2147483647) throw ValidationException::withMessages([
                 'server_limit' => "You cannot add this amount of servers because it would exceed the server limit."
                 'server_limit' => "You cannot add this amount of servers because it would exceed the server limit."
             ]);
             ]);
-           $user->increment('server_limit', $request->server_limit);
+            $user->increment('server_limit', $request->server_limit);
         }
         }
 
 
         return $user;
         return $user;
@@ -117,27 +143,72 @@ class UserController extends Controller
         $user = $discordUser ? $discordUser->user : User::findOrFail($id);
         $user = $discordUser ? $discordUser->user : User::findOrFail($id);
 
 
         $request->validate([
         $request->validate([
-            "credits"      => "sometimes|numeric|min:0|max:1000000",
+            "credits" => "sometimes|numeric|min:0|max:1000000",
             "server_limit" => "sometimes|numeric|min:0|max:1000000",
             "server_limit" => "sometimes|numeric|min:0|max:1000000",
         ]);
         ]);
 
 
-        if($request->credits){
-            if($user->credits - $request->credits < 0) throw ValidationException::withMessages([
+        if ($request->credits) {
+            if ($user->credits - $request->credits < 0) throw ValidationException::withMessages([
                 'credits' => "You can't remove this amount of credits because you would exceed the minimum credit limit"
                 'credits' => "You can't remove this amount of credits because you would exceed the minimum credit limit"
             ]);
             ]);
             $user->decrement('credits', $request->credits);
             $user->decrement('credits', $request->credits);
-         }
+        }
 
 
-        if($request->server_limit){
-            if($user->server_limit - $request->server_limit < 0) throw ValidationException::withMessages([
+        if ($request->server_limit) {
+            if ($user->server_limit - $request->server_limit < 0) throw ValidationException::withMessages([
                 'server_limit' => "You cannot remove this amount of servers because it would exceed the minimum server."
                 'server_limit' => "You cannot remove this amount of servers because it would exceed the minimum server."
             ]);
             ]);
-           $user->decrement('server_limit', $request->server_limit);
+            $user->decrement('server_limit', $request->server_limit);
         }
         }
 
 
         return $user;
         return $user;
     }
     }
 
 
+    /**
+     * @throws ValidationException
+     */
+    public function store(Request $request)
+    {
+        $request->validate([
+            'name' => ['required', 'string', 'max:30', 'min:4', 'alpha_num', 'unique:users'],
+            'email' => ['required', 'string', 'email', 'max:64', 'unique:users'],
+            'password' => ['required', 'string', 'min:8', 'max:191'],
+        ]);
+
+        $user = User::create([
+            'name' => $request->input('name'),
+            'email' => $request->input('email'),
+            'credits' => Configuration::getValueByKey('INITIAL_CREDITS', 150),
+            'server_limit' => Configuration::getValueByKey('INITIAL_SERVER_LIMIT', 1),
+            'password' => Hash::make($request->input('password')),
+        ]);
+
+        $response = Pterodactyl::client()->post('/application/users', [
+            "external_id" => App::environment('local') ? Str::random(16) : (string)$user->id,
+            "username" => $user->name,
+            "email" => $user->email,
+            "first_name" => $user->name,
+            "last_name" => $user->name,
+            "password" => $request->input('password'),
+            "root_admin" => false,
+            "language" => "en"
+        ]);
+
+        if ($response->failed()) {
+            $user->delete();
+            throw ValidationException::withMessages([
+                'pterodactyl_error_message' => $response->toException()->getMessage(),
+                'pterodactyl_error_status' => $response->toException()->getCode()
+            ]);
+        }
+
+        $user->update([
+            'pterodactyl_id' => $response->json()['attributes']['id']
+        ]);
+
+        return $user;
+    }
+
     /**
     /**
      * Remove the specified resource from storage.
      * Remove the specified resource from storage.
      *
      *

+ 25 - 12
app/Http/Controllers/Api/VoucherController.php

@@ -5,20 +5,29 @@ namespace App\Http\Controllers\Api;
 use App\Http\Controllers\Controller;
 use App\Http\Controllers\Controller;
 use App\Models\Voucher;
 use App\Models\Voucher;
 use Illuminate\Contracts\Pagination\LengthAwarePaginator;
 use Illuminate\Contracts\Pagination\LengthAwarePaginator;
+use Illuminate\Database\Eloquent\Collection;
 use Illuminate\Http\Request;
 use Illuminate\Http\Request;
 use Illuminate\Http\Response;
 use Illuminate\Http\Response;
 use Illuminate\Validation\Rule;
 use Illuminate\Validation\Rule;
+use Spatie\QueryBuilder\QueryBuilder;
 
 
 class VoucherController extends Controller
 class VoucherController extends Controller
 {
 {
+    const ALLOWED_INCLUDES = ['users'];
+    const ALLOWED_FILTERS = ['code', 'memo', 'credits', 'uses'];
+
     /**
     /**
      * Display a listing of the resource.
      * Display a listing of the resource.
      *
      *
-     * @return Response
+     * @return LengthAwarePaginator
      */
      */
     public function index(Request $request)
     public function index(Request $request)
     {
     {
-        return Voucher::paginate($request->query('per_page') ?? 50);
+        $query = QueryBuilder::for(Voucher::class)
+            ->allowedIncludes(self::ALLOWED_INCLUDES)
+            ->allowedFilters(self::ALLOWED_FILTERS);
+
+        return $query->paginate($request->input('per_page') ?? 50);
     }
     }
 
 
     /**
     /**
@@ -40,10 +49,10 @@ class VoucherController extends Controller
     public function store(Request $request)
     public function store(Request $request)
     {
     {
         $request->validate([
         $request->validate([
-            'memo'       => 'nullable|string|max:191',
-            'code'       => 'required|string|alpha_dash|max:36|min:4|unique:vouchers',
-            'uses'       => 'required|numeric|max:2147483647|min:1',
-            'credits'    => 'required|numeric|between:0,99999999',
+            'memo' => 'nullable|string|max:191',
+            'code' => 'required|string|alpha_dash|max:36|min:4|unique:vouchers',
+            'uses' => 'required|numeric|max:2147483647|min:1',
+            'credits' => 'required|numeric|between:0,99999999',
             'expires_at' => 'nullable|multiple_date_format:d-m-Y H:i:s,d-m-Y|after:now|before:10 years'
             'expires_at' => 'nullable|multiple_date_format:d-m-Y H:i:s,d-m-Y|after:now|before:10 years'
         ]);
         ]);
 
 
@@ -54,11 +63,15 @@ class VoucherController extends Controller
      * Display the specified resource.
      * Display the specified resource.
      *
      *
      * @param int $id
      * @param int $id
-     * @return Response
+     * @return Collection|Voucher
      */
      */
     public function show(int $id)
     public function show(int $id)
     {
     {
-        return Voucher::findOrFail($id);
+        $query = QueryBuilder::for(Voucher::class)
+            ->where('id', '=', $id)
+            ->allowedIncludes(self::ALLOWED_INCLUDES);
+
+        return $query->get();
     }
     }
 
 
     /**
     /**
@@ -84,10 +97,10 @@ class VoucherController extends Controller
         $voucher = Voucher::findOrFail($id);
         $voucher = Voucher::findOrFail($id);
 
 
         $request->validate([
         $request->validate([
-            'memo'       => 'nullable|string|max:191',
-            'code'       => "required|string|alpha_dash|max:36|min:4|unique:vouchers,code,{$voucher->id}",
-            'uses'       => 'required|numeric|max:2147483647|min:1',
-            'credits'    => 'required|numeric|between:0,99999999',
+            'memo' => 'nullable|string|max:191',
+            'code' => "required|string|alpha_dash|max:36|min:4|unique:vouchers,code,{$voucher->id}",
+            'uses' => 'required|numeric|max:2147483647|min:1',
+            'credits' => 'required|numeric|between:0,99999999',
             'expires_at' => 'nullable|multiple_date_format:d-m-Y H:i:s,d-m-Y|after:now|before:10 years'
             'expires_at' => 'nullable|multiple_date_format:d-m-Y H:i:s,d-m-Y|after:now|before:10 years'
         ]);
         ]);
 
 

+ 0 - 1
app/Providers/AppServiceProvider.php

@@ -29,7 +29,6 @@ class AppServiceProvider extends ServiceProvider
     {
     {
         Paginator::useBootstrap();
         Paginator::useBootstrap();
         Schema::defaultStringLength(191);
         Schema::defaultStringLength(191);
-        QueryBuilderRequest::setArrayValueDelimiter('|');
 
 
         Validator::extend('multiple_date_format', function ($attribute, $value, $parameters, $validator) {
         Validator::extend('multiple_date_format', function ($attribute, $value, $parameters, $validator) {
 
 

+ 1 - 1
composer.json

@@ -23,7 +23,7 @@
         "paypal/rest-api-sdk-php": "^1.14",
         "paypal/rest-api-sdk-php": "^1.14",
         "socialiteproviders/discord": "^4.1",
         "socialiteproviders/discord": "^4.1",
         "spatie/laravel-activitylog": "^3.16",
         "spatie/laravel-activitylog": "^3.16",
-        "spatie/laravel-query-builder": "^3.5",
+        "spatie/laravel-query-builder": "^3.6",
         "spatie/laravel-validation-rules": "^3.0",
         "spatie/laravel-validation-rules": "^3.0",
         "yajra/laravel-datatables-oracle": "~9.0"
         "yajra/laravel-datatables-oracle": "~9.0"
     },
     },

+ 7 - 7
composer.lock

@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
         "This file is @generated automatically"
     ],
     ],
-    "content-hash": "b3b61a46d5d4d6560d052cfda863d12c",
+    "content-hash": "f7ba581ff6641d3ab79d558070e99f3c",
     "packages": [
     "packages": [
         {
         {
             "name": "asm89/stack-cors",
             "name": "asm89/stack-cors",
@@ -3462,16 +3462,16 @@
         },
         },
         {
         {
             "name": "spatie/laravel-query-builder",
             "name": "spatie/laravel-query-builder",
-            "version": "3.5.0",
+            "version": "3.6.0",
             "source": {
             "source": {
                 "type": "git",
                 "type": "git",
                 "url": "https://github.com/spatie/laravel-query-builder.git",
                 "url": "https://github.com/spatie/laravel-query-builder.git",
-                "reference": "4e5257be24139836dc092f618d7c73bcb1c00302"
+                "reference": "03d8e1307dcb58b16fcc9c4947633fc60ae74802"
             },
             },
             "dist": {
             "dist": {
                 "type": "zip",
                 "type": "zip",
-                "url": "https://api.github.com/repos/spatie/laravel-query-builder/zipball/4e5257be24139836dc092f618d7c73bcb1c00302",
-                "reference": "4e5257be24139836dc092f618d7c73bcb1c00302",
+                "url": "https://api.github.com/repos/spatie/laravel-query-builder/zipball/03d8e1307dcb58b16fcc9c4947633fc60ae74802",
+                "reference": "03d8e1307dcb58b16fcc9c4947633fc60ae74802",
                 "shasum": ""
                 "shasum": ""
             },
             },
             "require": {
             "require": {
@@ -3528,7 +3528,7 @@
                     "type": "custom"
                     "type": "custom"
                 }
                 }
             ],
             ],
-            "time": "2021-07-05T14:17:44+00:00"
+            "time": "2021-09-06T08:03:10+00:00"
         },
         },
         {
         {
             "name": "spatie/laravel-validation-rules",
             "name": "spatie/laravel-validation-rules",
@@ -8713,5 +8713,5 @@
         "ext-intl": "*"
         "ext-intl": "*"
     },
     },
     "platform-dev": [],
     "platform-dev": [],
-    "plugin-api-version": "2.0.0"
+    "plugin-api-version": "2.1.0"
 }
 }

+ 46 - 0
config/query-builder.php

@@ -0,0 +1,46 @@
+<?php
+/**
+ * @see https://github.com/spatie/laravel-query-builder
+ */
+
+return [
+
+    /*
+     * By default the package will use the `include`, `filter`, `sort`
+     * and `fields` query parameters as described in the readme.
+     *
+     * You can customize these query string parameters here.
+     */
+    'parameters' => [
+        'include' => 'include',
+
+        'filter' => 'filter',
+
+        'sort' => 'sort',
+
+        'fields' => 'fields',
+
+        'append' => 'append',
+    ],
+
+    /*
+     * Related model counts are included using the relationship name suffixed with this string.
+     * For example: GET /users?include=postsCount
+     */
+    'count_suffix' => 'Count',
+
+    /*
+     * By default the package will throw an `InvalidFilterQuery` exception when a filter in the
+     * URL is not allowed in the `allowedFilters()` method.
+     */
+    'disable_invalid_filter_query_exception' => false,
+
+    /*
+     * By default the package inspects query string of request using $request->query().
+     * You can change this behavior to inspect the request body using $request->input()
+     * by setting this value to `body`.
+     *
+     * Possible values: `query_string`, `body`
+     */
+    'request_data_source' => 'query_string',
+];

+ 1 - 1
routes/api.php

@@ -20,7 +20,7 @@ use Illuminate\Support\Facades\Route;
 Route::middleware('api.token')->group(function () {
 Route::middleware('api.token')->group(function () {
     Route::patch('/users/{user}/increment', [UserController::class, 'increment']);
     Route::patch('/users/{user}/increment', [UserController::class, 'increment']);
     Route::patch('/users/{user}/decrement', [UserController::class, 'decrement']);
     Route::patch('/users/{user}/decrement', [UserController::class, 'decrement']);
-    Route::resource('users', UserController::class)->except(['store', 'create']);
+    Route::resource('users', UserController::class)->except(['create']);
 
 
     Route::patch('/servers/{server}/suspend', [ServerController::class, 'suspend']);
     Route::patch('/servers/{server}/suspend', [ServerController::class, 'suspend']);
     Route::patch('/servers/{server}/unsuspend', [ServerController::class, 'unSuspend']);
     Route::patch('/servers/{server}/unsuspend', [ServerController::class, 'unSuspend']);