diff --git a/app/Classes/PterodactylClient.php b/app/Classes/PterodactylClient.php index a94fca74..8f1b116c 100644 --- a/app/Classes/PterodactylClient.php +++ b/app/Classes/PterodactylClient.php @@ -24,19 +24,18 @@ class PterodactylClient public PendingRequest $client; - public PendingRequest $client_admin; - + public PendingRequest $application; + public function __construct(PterodactylSettings $ptero_settings) { $server_settings = new ServerSettings(); - + try { $this->client = $this->client($ptero_settings); - $this->client_admin = $this->clientAdmin($ptero_settings); + $this->application = $this->clientAdmin($ptero_settings); $this->per_page_limit = $ptero_settings->per_page_limit; $this->allocation_limit = $server_settings->allocation_limit; - } - catch (Exception $exception) { + } catch (Exception $exception) { logger('Failed to construct Pterodactyl client, Settings table not available?', ['exception' => $exception]); } } @@ -94,7 +93,7 @@ class PterodactylClient public function getEggs(Nest $nest) { try { - $response = $this->client_admin->get("application/nests/{$nest->id}/eggs?include=nest,variables&per_page=" . $this->per_page_limit); + $response = $this->application->get("application/nests/{$nest->id}/eggs?include=nest,variables&per_page=" . $this->per_page_limit); } catch (Exception $e) { throw self::getException($e->getMessage()); } @@ -113,7 +112,7 @@ class PterodactylClient public function getNodes() { try { - $response = $this->client_admin->get('application/nodes?per_page=' . $this->per_page_limit); + $response = $this->application->get('application/nodes?per_page=' . $this->per_page_limit); } catch (Exception $e) { throw self::getException($e->getMessage()); } @@ -133,7 +132,7 @@ class PterodactylClient public function getNode($id) { try { - $response = $this->client_admin->get('application/nodes/' . $id); + $response = $this->application->get('application/nodes/' . $id); } catch (Exception $e) { throw self::getException($e->getMessage()); } @@ -147,7 +146,7 @@ class PterodactylClient public function getServers() { try { - $response = $this->client_admin->get('application/servers?per_page=' . $this->per_page_limit); + $response = $this->application->get('application/servers?per_page=' . $this->per_page_limit); } catch (Exception $e) { throw self::getException($e->getMessage()); } @@ -166,7 +165,7 @@ class PterodactylClient public function getNests() { try { - $response = $this->client_admin->get('application/nests?per_page=' . $this->per_page_limit); + $response = $this->application->get('application/nests?per_page=' . $this->per_page_limit); } catch (Exception $e) { throw self::getException($e->getMessage()); } @@ -185,7 +184,7 @@ class PterodactylClient public function getLocations() { try { - $response = $this->client_admin->get('application/locations?per_page=' . $this->per_page_limit); + $response = $this->application->get('application/locations?per_page=' . $this->per_page_limit); } catch (Exception $e) { throw self::getException($e->getMessage()); } @@ -240,7 +239,7 @@ class PterodactylClient public function getAllocations(Node $node) { try { - $response = $this->client_admin->get("application/nodes/{$node->id}/allocations?per_page={$this->allocation_limit}"); + $response = $this->application->get("application/nodes/{$node->id}/allocations?per_page={$this->allocation_limit}"); } catch (Exception $e) { throw self::getException($e->getMessage()); } @@ -259,7 +258,7 @@ class PterodactylClient */ public function createServer(Server $server, Egg $egg, int $allocationId) { - return $this->client_admin->post('application/servers', [ + return $this->application->post('application/servers', [ 'name' => $server->name, 'external_id' => $server->id, 'user' => $server->user->pterodactyl_id, @@ -288,7 +287,7 @@ class PterodactylClient public function suspendServer(Server $server) { try { - $response = $this->client_admin->post("application/servers/$server->pterodactyl_id/suspend"); + $response = $this->application->post("application/servers/$server->pterodactyl_id/suspend"); } catch (Exception $e) { throw self::getException($e->getMessage()); } @@ -302,7 +301,7 @@ class PterodactylClient public function unSuspendServer(Server $server) { try { - $response = $this->client_admin->post("application/servers/$server->pterodactyl_id/unsuspend"); + $response = $this->application->post("application/servers/$server->pterodactyl_id/unsuspend"); } catch (Exception $e) { throw self::getException($e->getMessage()); } @@ -322,7 +321,7 @@ class PterodactylClient public function getUser(int $pterodactylId) { try { - $response = $this->client_admin->get("application/users/{$pterodactylId}"); + $response = $this->application->get("application/users/{$pterodactylId}"); } catch (Exception $e) { throw self::getException($e->getMessage()); } @@ -342,7 +341,7 @@ class PterodactylClient public function getServerAttributes(int $pterodactylId, bool $deleteOn404 = false) { try { - $response = $this->client_admin->get("application/servers/{$pterodactylId}?include=egg,node,nest,location"); + $response = $this->application->get("application/servers/{$pterodactylId}?include=egg,node,nest,location"); } catch (Exception $e) { throw self::getException($e->getMessage()); } @@ -371,7 +370,7 @@ class PterodactylClient */ public function updateServer(Server $server, Product $product) { - return $this->client_admin->patch("application/servers/{$server->pterodactyl_id}/build", [ + return $this->application->patch("application/servers/{$server->pterodactyl_id}/build", [ 'allocation' => $server->allocation, 'memory' => $product->memory, 'swap' => $product->swap, @@ -396,7 +395,7 @@ class PterodactylClient */ public function updateServerOwner(Server $server, int $userId) { - return $this->client_admin->patch("application/servers/{$server->pterodactyl_id}/details", [ + return $this->application->patch("application/servers/{$server->pterodactyl_id}/details", [ 'name' => $server->name, 'user' => $userId, ]); @@ -435,7 +434,7 @@ class PterodactylClient public function checkNodeResources(Node $node, int $requireMemory, int $requireDisk) { try { - $response = $this->client_admin->get("application/nodes/{$node->id}"); + $response = $this->application->get("application/nodes/{$node->id}"); } catch (Exception $e) { throw self::getException($e->getMessage()); } diff --git a/app/Http/Controllers/Admin/SettingsController.php b/app/Http/Controllers/Admin/SettingsController.php index 6a7527bb..7e1c5457 100644 --- a/app/Http/Controllers/Admin/SettingsController.php +++ b/app/Http/Controllers/Admin/SettingsController.php @@ -109,26 +109,18 @@ class SettingsController extends Controller $settingsClass = new $settings_class(); foreach ($settingsClass->toArray() as $key => $value) { - switch (gettype($request->input($key))) { - case 'boolean': - $settingsClass->$key = $request->has($key); - break; - case 'string': - $settingsClass->$key = $request->input($key) ?? ''; - break; - case 'integer': - $settingsClass->$key = $request->input($key) ?? 0; - break; - case 'array': - $settingsClass->$key = $request->input($key) ?? []; - break; - case 'double': - $settingsClass->$key = $request->input($key) ?? 0.0; - break; - case 'NULL': - $settingsClass->$key = null; - break; + // Get the type of the settingsclass property + $rp = new \ReflectionProperty($settingsClass, $key); + $rpType = $rp->getType(); + + if ($rpType == 'bool') { + $settingsClass->$key = $request->has($key); + continue; } + + $nullable = $rpType->allowsNull(); + if ($nullable) $settingsClass->$key = $request->input($key) ?? null; + else $settingsClass->$key = $request->input($key); } $settingsClass->save(); diff --git a/app/Http/Controllers/Admin/UserController.php b/app/Http/Controllers/Admin/UserController.php index eafc351d..4dfcb219 100644 --- a/app/Http/Controllers/Admin/UserController.php +++ b/app/Http/Controllers/Admin/UserController.php @@ -35,7 +35,7 @@ class UserController extends Controller { $this->pterodactyl = new PterodactylClient($ptero_settings); } - + /** * Display a listing of the resource. * @@ -166,6 +166,10 @@ class UserController extends Controller */ public function destroy(User $user) { + if ($user->role === 'admin' && User::query()->where('role', 'admin')->count() === 1) { + return redirect()->back()->with('error', __('You can not delete the last admin!')); + } + $user->delete(); return redirect()->back()->with('success', __('user has been removed!')); @@ -258,8 +262,7 @@ class UserController extends Controller $users = $all ? User::all() : User::whereIn('id', $data['users'])->get(); try { Notification::send($users, new DynamicNotification($data['via'], $database, $mail)); - } - catch (Exception $e) { + } catch (Exception $e) { return redirect()->route('admin.users.notifications')->with('error', __('The attempt to send the email failed with the error: ' . $e->getMessage())); } diff --git a/app/Http/Controllers/Api/UserController.php b/app/Http/Controllers/Api/UserController.php index 797ae7b7..1a6ef3eb 100644 --- a/app/Http/Controllers/Api/UserController.php +++ b/app/Http/Controllers/Api/UserController.php @@ -43,7 +43,7 @@ class UserController extends Controller { $this->pterodactyl = new PterodactylClient($ptero_settings); } - + /** * Display a listing of the resource. * @@ -105,7 +105,7 @@ class UserController extends Controller //Update Users Password on Pterodactyl //Username,Mail,First and Lastname are required aswell - $response = $this->pterodactyl->client_admin->patch('/application/users/' . $user->pterodactyl_id, [ + $response = $this->pterodactyl->application->patch('/application/users/' . $user->pterodactyl_id, [ 'username' => $request->name, 'first_name' => $request->name, 'last_name' => $request->name, @@ -280,7 +280,7 @@ class UserController extends Controller 'referral_code' => $this->createReferralCode(), ]); - $response = $this->pterodactyl->client_admin->post('/application/users', [ + $response = $this->pterodactyl->application->post('/application/users', [ 'external_id' => App::environment('local') ? Str::random(16) : (string) $user->id, 'username' => $user->name, 'email' => $user->email, diff --git a/app/Http/Controllers/Auth/RegisterController.php b/app/Http/Controllers/Auth/RegisterController.php index fc27b7b5..29a4b6e0 100644 --- a/app/Http/Controllers/Auth/RegisterController.php +++ b/app/Http/Controllers/Auth/RegisterController.php @@ -135,11 +135,12 @@ class RegisterController extends Controller 'server_limit' => $this->initial_server_limit, 'password' => Hash::make($data['password']), 'referral_code' => $this->createReferralCode(), + 'pterodactyl_id' => Str::uuid(), ]); - $response = $this->pterodactyl->client_admin->post('/application/users', [ - 'external_id' => App::environment('local') ? Str::random(16) : (string) $user->id, + $response = $this->pterodactyl->application->post('/application/users', [ + 'external_id' => $user->pterodactyl_id, 'username' => $user->name, 'email' => $user->email, 'first_name' => $user->name, @@ -157,9 +158,8 @@ class RegisterController extends Controller ]); } - $user->update([ - 'pterodactyl_id' => $response->json()['attributes']['id'], - ]); + // delete activity log for user creation where description = 'created' or 'deleted' and subject_id = user_id + DB::table('activity_log')->where('description', 'created')->orWhere('description', 'deleted')->where('subject_id', $user->id)->delete(); //INCREMENT REFERRAL-USER CREDITS if (!empty($data['referral_code'])) { diff --git a/app/Http/Controllers/ProfileController.php b/app/Http/Controllers/ProfileController.php index ea6ffcf6..b3156f96 100644 --- a/app/Http/Controllers/ProfileController.php +++ b/app/Http/Controllers/ProfileController.php @@ -78,15 +78,15 @@ class ProfileController extends Controller $user = User::findOrFail($id); //update password if necessary - if (! is_null($request->input('new_password'))) { + if (!is_null($request->input('new_password'))) { //validate password request $request->validate([ 'current_password' => [ 'required', function ($attribute, $value, $fail) use ($user) { - if (! Hash::check($value, $user->password)) { - $fail('The '.$attribute.' is invalid.'); + if (!Hash::check($value, $user->password)) { + $fail('The ' . $attribute . ' is invalid.'); } }, ], @@ -96,7 +96,7 @@ class ProfileController extends Controller //Update Users Password on Pterodactyl //Username,Mail,First and Lastname are required aswell - $response = $this->pterodactyl->client_admin->patch('/application/users/' . $user->pterodactyl_id, [ + $response = $this->pterodactyl->application->patch('/application/users/' . $user->pterodactyl_id, [ 'password' => $request->input('new_password'), 'username' => $request->input('name'), 'first_name' => $request->input('name'), @@ -118,13 +118,13 @@ class ProfileController extends Controller //validate request $request->validate([ - 'name' => 'required|min:4|max:30|alpha_num|unique:users,name,'.$id.',id', - 'email' => 'required|email|max:64|unique:users,email,'.$id.',id', + 'name' => 'required|min:4|max:30|alpha_num|unique:users,name,' . $id . ',id', + 'email' => 'required|email|max:64|unique:users,email,' . $id . ',id', 'avatar' => 'nullable', ]); //update avatar - if (! is_null($request->input('avatar'))) { + if (!is_null($request->input('avatar'))) { $avatar = json_decode($request->input('avatar')); if ($avatar->input->size > 3000000) { abort(500); @@ -140,7 +140,7 @@ class ProfileController extends Controller } //update name and email on Pterodactyl - $response = $this->pterodactyl->client_admin->patch('/application/users/' . $user->pterodactyl_id, [ + $response = $this->pterodactyl->application->patch('/application/users/' . $user->pterodactyl_id, [ 'username' => $request->input('name'), 'first_name' => $request->input('name'), 'last_name' => $request->input('name'), diff --git a/app/Models/Server.php b/app/Models/Server.php index ca7761c3..21d2c245 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -28,9 +28,9 @@ class Server extends Model public function getActivitylogOptions(): LogOptions { return LogOptions::defaults() - -> logOnlyDirty() - -> logOnly(['*']) - -> dontSubmitEmptyLogs(); + ->logOnlyDirty() + ->logOnly(['*']) + ->dontSubmitEmptyLogs(); } /** @@ -84,8 +84,8 @@ class Server extends Model }); static::deleting(function (Server $server) { - $response = $server->pterodactyl->client_admin->delete("/application/servers/{$server->pterodactyl_id}"); - if ($response->failed() && ! is_null($server->pterodactyl_id)) { + $response = $server->pterodactyl->application->delete("/application/servers/{$server->pterodactyl_id}"); + if ($response->failed() && !is_null($server->pterodactyl_id)) { //only return error when it's not a 404 error if ($response['errors'][0]['status'] != '404') { throw new Exception($response['errors'][0]['code']); @@ -99,7 +99,7 @@ class Server extends Model */ public function isSuspended() { - return ! is_null($this->suspended); + return !is_null($this->suspended); } /** @@ -107,7 +107,7 @@ class Server extends Model */ public function getPterodactylServer() { - return $this->pterodactyl->client_admin->get("/application/servers/{$this->pterodactyl_id}"); + return $this->pterodactyl->application->get("/application/servers/{$this->pterodactyl_id}"); } /** diff --git a/app/Models/User.php b/app/Models/User.php index 2b510e45..9584bd3d 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -122,7 +122,7 @@ class User extends Authenticatable implements MustVerifyEmail $user->discordUser()->delete(); - $user->pterodactyl->client_admin->delete("/application/users/{$user->pterodactyl_id}"); + $user->pterodactyl->application->delete("/application/users/{$user->pterodactyl_id}"); }); } @@ -195,9 +195,6 @@ class User extends Authenticatable implements MustVerifyEmail return $this->suspended; } - /** - * @throws Exception - */ public function suspend() { foreach ($this->servers as $server) { @@ -211,9 +208,6 @@ class User extends Authenticatable implements MustVerifyEmail return $this; } - /** - * @throws Exception - */ public function unSuspend() { foreach ($this->getServersWithProduct() as $server) { @@ -241,23 +235,9 @@ class User extends Authenticatable implements MustVerifyEmail */ public function getAvatar() { - //TODO loading the images to confirm they exist is causing to much load time. alternative has to be found :) maybe onerror tag on the - // if ($this->discordUser()->exists()) { - // if(@getimagesize($this->discordUser->getAvatar())) { - // $avatar = $this->discordUser->getAvatar(); - // } else { - // $avatar = "https://www.gravatar.com/avatar/" . md5(strtolower(trim($this->email))); - // } - // } else { - // $avatar = "https://www.gravatar.com/avatar/" . md5(strtolower(trim($this->email))); - // } - return 'https://www.gravatar.com/avatar/' . md5(strtolower(trim($this->email))); } - /** - * @return string - */ public function creditUsage() { $usage = 0; diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 97a269c0..aad430c6 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -9,6 +9,7 @@ use Exception; use Illuminate\Pagination\Paginator; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Schema; +use Illuminate\Support\Facades\URL; use Illuminate\Support\Facades\Validator; use Illuminate\Support\ServiceProvider; @@ -54,6 +55,14 @@ class AppServiceProvider extends ServiceProvider return $ok; }); + // Force HTTPS if APP_URL is set to https + if (config('app.url') && parse_url(config('app.url'), PHP_URL_SCHEME) === 'https') { + URL::forceScheme('https'); + } + + // Do not run this code if no APP_KEY is set + if (config('app.key') == null) return; + try { if (Schema::hasColumn('useful_links', 'position')) { $useful_links = UsefulLink::where("position", "like", "%topbar%")->get()->sortby("id"); @@ -63,6 +72,7 @@ class AppServiceProvider extends ServiceProvider Log::error("Couldnt find useful_links. Probably the installation is not completet. " . $e); } + $settings = $this->app->make(MailSettings::class); $settings->setConfig(); } diff --git a/app/Settings/ReferralSettings.php b/app/Settings/ReferralSettings.php index b85d453e..e49fbaae 100644 --- a/app/Settings/ReferralSettings.php +++ b/app/Settings/ReferralSettings.php @@ -25,11 +25,11 @@ class ReferralSettings extends Settings public static function getValidations() { return [ - 'allowed' => 'required|in:everyone,clients', + 'allowed' => 'required|in:Everyone,Clients', 'always_give_commission' => 'nullable|boolean', 'enabled' => 'nullable|boolean', 'reward' => 'nullable|numeric', - 'mode' => 'required|in:commission,percentage,both', + 'mode' => 'required|in:Commission,Sign-Up,Both', 'percentage' => 'nullable|numeric', ]; } diff --git a/database/migrations/2023_04_03_231829_update_users_table.php b/database/migrations/2023_04_03_231829_update_users_table.php new file mode 100644 index 00000000..3caf98aa --- /dev/null +++ b/database/migrations/2023_04_03_231829_update_users_table.php @@ -0,0 +1,32 @@ +string('pterodactyl_id')->change(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('users', function (Blueprint $table) { + $table->integer('pterodactyl_id')->nullable->change(); + }); + } +}; diff --git a/themes/default/views/admin/servers/index.blade.php b/themes/default/views/admin/servers/index.blade.php index 351daccd..3cfec164 100644 --- a/themes/default/views/admin/servers/index.blade.php +++ b/themes/default/views/admin/servers/index.blade.php @@ -6,12 +6,13 @@
-

{{__('Servers')}}

+

{{ __('Servers') }}

@@ -27,25 +28,25 @@
- {{__('Servers')}} + {{ __('Servers') }}
- {{__('Sync')}} + {{ __('Sync') }}
- - - - - - - - - - + + + + + + + + + + @@ -61,10 +62,10 @@
{{ __('Status') }}{{__('Name')}}{{__('User')}}{{__('Server id')}}{{__('Config')}}{{__('Suspended at')}}{{__('Created at')}}{{ __('Actions') }}
{{ __('Status') }}{{ __('Name') }}{{ __('User') }}{{ __('Server id') }}{{ __('Product') }}{{ __('Suspended at') }}{{ __('Created at') }}{{ __('Actions') }}