Browse Source

Merge pull request #372 from ControlPanel-gg/settings_rewrite

Settings rewrite
Dennis 3 years ago
parent
commit
4ad5722e9c
63 changed files with 2281 additions and 1402 deletions
  1. 0 48
      .env.example
  2. 5 5
      app/Classes/Pterodactyl.php
  3. 50 0
      app/Classes/Settings/Invoices.php
  4. 61 0
      app/Classes/Settings/Language.php
  5. 85 0
      app/Classes/Settings/Misc.php
  6. 61 0
      app/Classes/Settings/Payments.php
  7. 73 0
      app/Classes/Settings/System.php
  8. 0 123
      app/Http/Controllers/Admin/ConfigurationController.php
  9. 3 2
      app/Http/Controllers/Admin/CreditProductController.php
  10. 70 0
      app/Http/Controllers/Admin/InvoiceController.php
  11. 47 30
      app/Http/Controllers/Admin/PaymentController.php
  12. 2 5
      app/Http/Controllers/Admin/ProductController.php
  13. 2 1
      app/Http/Controllers/Admin/ServerController.php
  14. 47 61
      app/Http/Controllers/Admin/SettingsController.php
  15. 2 1
      app/Http/Controllers/Admin/UserController.php
  16. 3 3
      app/Http/Controllers/Api/UserController.php
  17. 13 5
      app/Http/Controllers/Auth/LoginController.php
  18. 17 19
      app/Http/Controllers/Auth/RegisterController.php
  19. 7 7
      app/Http/Controllers/Auth/SocialiteController.php
  20. 0 3
      app/Http/Controllers/HomeController.php
  21. 11 14
      app/Http/Controllers/ProfileController.php
  22. 5 5
      app/Http/Controllers/ServerController.php
  23. 5 5
      app/Http/Controllers/StoreController.php
  24. 2 0
      app/Http/Controllers/TranslationController.php
  25. 3 2
      app/Http/Middleware/GlobalNames.php
  26. 10 200
      app/Http/Middleware/SetLocale.php
  27. 2 3
      app/Listeners/UnsuspendServers.php
  28. 3 5
      app/Listeners/Verified.php
  29. 1 1
      app/Models/CreditProduct.php
  30. 0 23
      app/Models/InvoiceSettings.php
  31. 8 6
      app/Models/Settings.php
  32. 0 1
      app/Notifications/ServersSuspendedNotification.php
  33. 19 19
      app/Notifications/WelcomeMessage.php
  34. 57 4
      app/Providers/AppServiceProvider.php
  35. 8 43
      config/app.php
  36. 16 25
      config/mail.php
  37. 0 34
      database/migrations/2021_05_08_164658_create_configurations_table.php
  38. 0 48
      database/migrations/2021_12_1_174440_invoice-settings.php
  39. 61 0
      database/migrations/2022_01_05_144858_rename_configurations_table.php
  40. 34 0
      database/migrations/2022_01_14_234418_update_settings_table_allow_nullable.php
  41. 2 3
      database/seeders/DatabaseSeeder.php
  42. 0 149
      database/seeders/Seeds/ConfigurationSeeder.php
  43. 468 0
      database/seeders/Seeds/SettingsSeeder.php
  44. 1 1
      package-lock.json
  45. BIN
      public/images/discord_logo.png
  46. 14 5
      resources/lang/de.json
  47. 32 19
      resources/lang/en.json
  48. 0 63
      resources/views/admin/configurations/editModel.blade.php
  49. 0 91
      resources/views/admin/configurations/index.blade.php
  50. 6 0
      resources/views/admin/payments/index.blade.php
  51. 26 164
      resources/views/admin/settings/index.blade.php
  52. 111 0
      resources/views/admin/settings/tabs/invoices.blade.php
  53. 91 0
      resources/views/admin/settings/tabs/language.blade.php
  54. 194 0
      resources/views/admin/settings/tabs/misc.blade.php
  55. 144 0
      resources/views/admin/settings/tabs/payment.blade.php
  56. 208 0
      resources/views/admin/settings/tabs/system.blade.php
  57. 24 15
      resources/views/layouts/app.blade.php
  58. 46 34
      resources/views/layouts/main.blade.php
  59. 83 83
      resources/views/profile/index.blade.php
  60. 2 0
      resources/views/servers/create.blade.php
  61. 3 3
      resources/views/servers/index.blade.php
  62. 2 2
      resources/views/store/checkout.blade.php
  63. 31 19
      routes/web.php

+ 0 - 48
.env.example

@@ -8,18 +8,6 @@ APP_URL=http://localhost
 APP_TIMEZONE=UTC
 APP_TIMEZONE=UTC
 ### --- App Settings End --- ###
 ### --- App Settings End --- ###
 
 
-### --- Localization settings --- ###
-# If set to true, Language is chosen automatically depending on the users browserlanguage.
-DYNAMIC_LOCALE = false
-# The language of the Dashboard. This is also the fallback if dynamic_locale is true but no translation is found
-LOCALE=en
-# You can grab the Language-Codes for the Datatables from this Website https://datatables.net/plug-ins/i18n/
-DATATABLE_LOCALE=en-gb
-#The languages you DO NOT want to support on your Controlpanel split by comma.
-#Remove the language to make it available
-UNSUPPORTED_LOCALES=german,italian,chinese
-### --- Localization settings End --- ###
-
 ### --- DB Settings (required) --- ###
 ### --- DB Settings (required) --- ###
 DB_CONNECTION=mysql
 DB_CONNECTION=mysql
 DB_HOST=127.0.0.1
 DB_HOST=127.0.0.1
@@ -29,42 +17,6 @@ DB_USERNAME=dashboarduser
 DB_PASSWORD=
 DB_PASSWORD=
 ### --- DB Settings End --- ###
 ### --- DB Settings End --- ###
 
 
-### --- Payment Options (required for payments) --- ###
-# Paypal API Credentials - https://developer.paypal.com/docs/integration/direct/rest/ - Sandbox credentials are being used when APP_ENV is set to local
-PAYPAL_SANDBOX_SECRET=
-PAYPAL_SANDBOX_CLIENT_ID=
-PAYPAL_SECRET=
-PAYPAL_CLIENT_ID=
-
-# Stripe API Credentials - https://dashboard.stripe.com/account/apikeys - Test credentials are being used when APP_ENV is set to local
-STRIPE_TEST_SECRET=
-STRIPE_SECRET=
-#https://dashboard.stripe.com/webhooks -> webhook route: <your.controlpanel.gg>/payment/StripeWebhooks
-STRIPE_ENDPOINT_TEST_SECRET=
-STRIPE_ENDPOINT_SECRET=
-# Stripe payment methods - comma seperated list of payment methods that are enabled https://stripe.com/docs/payments/payment-methods/integration-options
-STRIPE_METHODS=
-### --- Payment Options End --- ###
-
-### --- Discord Settings (optional) --- ###
-# Discord API Credentials - https://discordapp.com/developers/applications/
-DISCORD_CLIENT_ID=
-DISCORD_CLIENT_SECRET=
-# Bot Settings - will join users to your discord
-DISCORD_BOT_TOKEN=
-DISCORD_GUILD_ID=
-# Discord role that will be assigned to users when they register
-DISCORD_ROLE_ID=
-### --- Discord Settings End --- ###
-
-### --- Controlpanel Settings (required) --- ###
-# Controlpanel URL Settings - URLs must not end with a slash!
-PTERODACTYL_URL=https://panel.controlpanel.gg # required
-PHPMYADMIN_URL=https://mysql.controlpanel.gg #optional. remove to remove database button
-DISCORD_INVITE_URL=https://discord.gg/vrUYdxG4wZ #optional
-# Admin API Token from Pterodactyl Panel - Nececary for the Panel to work
-PTERODACTYL_TOKEN=
-### --- Controlpanel Settings End --- ###
 
 
 # Google Recaptcha API Credentials - https://www.google.com/recaptcha/admin - reCaptcha V2 (not v3)
 # Google Recaptcha API Credentials - https://www.google.com/recaptcha/admin - reCaptcha V2 (not v3)
 RECAPTCHA_SITE_KEY=6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI
 RECAPTCHA_SITE_KEY=6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI

+ 5 - 5
app/Classes/Pterodactyl.php

@@ -2,11 +2,11 @@
 
 
 namespace App\Classes;
 namespace App\Classes;
 
 
-use App\Models\Configuration;
 use App\Models\Egg;
 use App\Models\Egg;
 use App\Models\Nest;
 use App\Models\Nest;
 use App\Models\Node;
 use App\Models\Node;
 use App\Models\Server;
 use App\Models\Server;
+use App\Models\Settings;
 use Exception;
 use Exception;
 use Illuminate\Http\Client\PendingRequest;
 use Illuminate\Http\Client\PendingRequest;
 use Illuminate\Http\Client\Response;
 use Illuminate\Http\Client\Response;
@@ -27,10 +27,10 @@ class Pterodactyl
     public static function client()
     public static function client()
     {
     {
         return Http::withHeaders([
         return Http::withHeaders([
-            'Authorization' => 'Bearer ' . env('PTERODACTYL_TOKEN', false),
+            'Authorization' => 'Bearer ' . config("SETTINGS::SYSTEM:PTERODACTYL:TOKEN"),
             'Content-type'  => 'application/json',
             'Content-type'  => 'application/json',
             'Accept'        => 'Application/vnd.pterodactyl.v1+json',
             'Accept'        => 'Application/vnd.pterodactyl.v1+json',
-        ])->baseUrl(env('PTERODACTYL_URL') . '/api');
+        ])->baseUrl(config("SETTINGS::SYSTEM:PTERODACTYL:URL") . '/api');
     }
     }
 
 
     /**
     /**
@@ -141,7 +141,7 @@ class Pterodactyl
      */
      */
     public static function getAllocations(Node $node)
     public static function getAllocations(Node $node)
     {
     {
-        $per_page = Configuration::getValueByKey('ALLOCATION_LIMIT', 200);
+        $per_page = config('SETTINGS::SERVER:ALLOCATION_LIMIT', 200);
         try {
         try {
             $response = self::client()->get("/application/nodes/{$node->id}/allocations?per_page={$per_page}");
             $response = self::client()->get("/application/nodes/{$node->id}/allocations?per_page={$per_page}");
         } catch (Exception $e) {
         } catch (Exception $e) {
@@ -158,7 +158,7 @@ class Pterodactyl
      */
      */
     public static function url(string $route): string
     public static function url(string $route): string
     {
     {
-        return env('PTERODACTYL_URL') . $route;
+        return config("SETTINGS::SYSTEM:PTERODACTYL:URL") . $route;
     }
     }
 
 
     /**
     /**

+ 50 - 0
app/Classes/Settings/Invoices.php

@@ -0,0 +1,50 @@
+<?php
+
+namespace App\Classes\Settings;
+
+use App\Models\Settings;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Cache;
+
+class Invoices
+{
+    public function __construct()
+    {
+        return;
+    }
+
+
+    public function updateSettings(Request $request)
+    {
+        $request->validate([
+            'logo' => 'nullable|max:10000|mimes:jpg,png,jpeg',
+        ]);
+
+        $values = [
+            //SETTINGS::VALUE => REQUEST-VALUE (coming from the html-form)
+            "SETTINGS::INVOICE:COMPANY_NAME" => "company-name",
+            "SETTINGS::INVOICE:COMPANY_ADDRESS" => "company-address",
+            "SETTINGS::INVOICE:COMPANY_PHONE" => "company-phone",
+            "SETTINGS::INVOICE:COMPANY_MAIL" => "company-mail",
+            "SETTINGS::INVOICE:COMPANY_VAT" => "company-vat",
+            "SETTINGS::INVOICE:COMPANY_WEBSITE" => "company-web",
+            "SETTINGS::INVOICE:PREFIX" => "invoice-prefix",
+            "SETTINGS::INVOICE:ENABLED" => "enable-invoices",
+        ];
+
+        foreach ($values as $key => $value) {
+            $param = $request->get($value);
+
+            Settings::where('key', $key)->updateOrCreate(['key' => $key], ['value' => $param]);
+            Cache::forget("setting" . ':' . $key);
+        }
+
+
+        if ($request->hasFile('logo')) {
+            $request->file('logo')->storeAs('public', 'logo.png');
+        }
+
+
+        return redirect(route('admin.settings.index') . '#invoices')->with('success', __('Invoice settings updated!'));
+    }
+}

+ 61 - 0
app/Classes/Settings/Language.php

@@ -0,0 +1,61 @@
+<?php
+
+namespace App\Classes\Settings;
+
+use App\Models\Settings;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Cache;
+use Illuminate\Support\Facades\Session;
+use Illuminate\Support\Facades\Validator;
+
+
+class Language
+{
+    public function __construct()
+    {
+        return;
+    }
+
+
+    public function updateSettings(Request $request)
+    {
+        $validator = Validator::make($request->all(), [
+            'autotranslate' => 'string',
+            'canClientChangeLanguage' => 'string',
+            'defaultLanguage' => 'required|string',
+            'languages' => 'required|array',
+            'languages.*' => 'required|string',
+            'datatable-language' => 'required|string',
+        ]);
+
+
+        if ($validator->fails()) {
+            return redirect(route('admin.settings.index') . '#language')->with('error', __('Language settings have not been updated!'))->withErrors($validator);
+        }
+
+        $values = [
+            //SETTINGS::VALUE => REQUEST-VALUE (coming from the html-form)
+            "SETTINGS::LOCALE:DEFAULT" => "defaultLanguage",
+            "SETTINGS::LOCALE:DYNAMIC" => "autotranslate",
+            "SETTINGS::LOCALE:CLIENTS_CAN_CHANGE" => "canClientChangeLanguage",
+            "SETTINGS::LOCALE:AVAILABLE" => "languages",
+            "SETTINGS::LOCALE:DATATABLES" => "datatable-language"
+        ];
+
+
+        foreach ($values as $key => $value) {
+            $param = $request->get($value);
+
+            if (is_array($param)) {
+                $param = implode(",", $param);
+            }
+
+            Settings::where('key', $key)->updateOrCreate(['key' => $key], ['value' => $param]);
+            Cache::forget("setting" . ':' . $key);
+            Session::remove("locale");
+        }
+
+
+        return redirect(route('admin.settings.index') . '#language')->with('success', __('Language settings updated!'));
+    }
+}

+ 85 - 0
app/Classes/Settings/Misc.php

@@ -0,0 +1,85 @@
+<?php
+
+namespace App\Classes\Settings;
+
+use App\Models\Settings;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Cache;
+use Illuminate\Support\Facades\Validator;
+
+
+class Misc
+{
+    public function __construct()
+    {
+        return;
+    }
+
+    public function updateSettings(Request $request)
+    {
+        $validator = Validator::make($request->all(), [
+            'icon' => 'nullable|max:10000|mimes:jpg,png,jpeg',
+            'favicon' => 'nullable|max:10000|mimes:ico',
+            'discord-bot-token' => 'nullable|string',
+            'discord-client-id' => 'nullable|string',
+            'discord-client-secret' => 'nullable|string',
+            'discord-guild-id' => 'nullable|string',
+            'discord-invite-url' => 'nullable|string',
+            'discord-role-id' => 'nullable|string',
+            'recaptcha-site-key' => 'nullable|string',
+            'recaptcha-secret-key' => 'nullable|string',
+            'enable-recaptcha' => 'nullable|string',
+            'mailservice' => 'nullable|string',
+            'mailhost' => 'nullable|string',
+            'mailport' => 'nullable|string',
+            'mailusername' => 'nullable|string',
+            'mailpassword' => 'nullable|string',
+            'mailencryption' => 'nullable|string',
+            'mailfromadress' => 'nullable|string',
+            'mailfromname' => 'nullable|string',
+        ]);
+
+        if ($validator->fails()) {
+            return redirect(route('admin.settings.index') . '#misc')->with('error', __('Misc settings have not been updated!'))->withErrors($validator)
+                ->withInput();
+        }
+
+        if ($request->hasFile('icon')) {
+            $request->file('icon')->storeAs('public', 'icon.png');
+        }
+        if ($request->hasFile('favicon')) {
+            $request->file('favicon')->storeAs('public', 'favicon.ico');
+        }
+
+        $values = [
+            "SETTINGS::DISCORD:BOT_TOKEN" => "discord-bot-token",
+            "SETTINGS::DISCORD:CLIENT_ID" => "discord-client-id",
+            "SETTINGS::DISCORD:CLIENT_SECRET" => "discord-client-secret",
+            "SETTINGS::DISCORD:GUILD_ID" => "discord-guild-id",
+            "SETTINGS::DISCORD:INVITE_URL" => "discord-invite-url",
+            "SETTINGS::DISCORD:ROLE_ID" => "discord-role-id",
+            "SETTINGS::RECAPTCHA:SITE_KEY" => "recaptcha-site-key",
+            "SETTINGS::RECAPTCHA:SECRET_KEY" => "recaptcha-secret-key",
+            "SETTINGS::RECAPTCHA:ENABLED" => "enable-recaptcha",
+            "SETTINGS::MAIL:MAILER" => "mailservice",
+            "SETTINGS::MAIL:HOST" => "mailhost",
+            "SETTINGS::MAIL:PORT" => "mailport",
+            "SETTINGS::MAIL:USERNAME" => "mailusername",
+            "SETTINGS::MAIL:PASSWORD" => "mailpassword",
+            "SETTINGS::MAIL:ENCRYPTION" => "mailencryption",
+            "SETTINGS::MAIL:FROM_ADDRESS" => "mailfromadress",
+            "SETTINGS::MAIL:FROM_NAME" => "mailfromname",
+
+        ];
+
+        foreach ($values as $key => $value) {
+            $param = $request->get($value);
+
+            Settings::where('key', $key)->updateOrCreate(['key' => $key], ['value' => $param]);
+            Cache::forget("setting" . ':' . $key);
+        }
+
+
+        return redirect(route('admin.settings.index') . '#misc')->with('success', __('Misc settings updated!'));
+    }
+}

+ 61 - 0
app/Classes/Settings/Payments.php

@@ -0,0 +1,61 @@
+<?php
+
+namespace App\Classes\Settings;
+
+use App\Models\Settings;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Cache;
+use Illuminate\Support\Facades\Validator;
+
+
+class Payments
+{
+    public function __construct()
+    {
+        return;
+    }
+
+
+    public function updateSettings(Request $request)
+    {
+        $validator = Validator::make($request->all(), [
+            "paypal-client_id" => "nullable|string",
+            "paypal-client-secret" => "nullable|string",
+            "paypal-sandbox-secret" => "nullable|string",
+            "stripe-secret-key" => "nullable|string",
+            "stripe-endpoint-secret" => "nullable|string",
+            "stripe-test-secret-key" => "nullable|string",
+            "stripe-test-endpoint-secret" => "nullable|string",
+            "stripe-methods" => "nullable|string",
+            "sales-tax" => "nullable|numeric",
+        ]);
+        if ($validator->fails()) {
+            return redirect(route('admin.settings.index') . '#payment')->with('error', __('Payment settings have not been updated!'))->withErrors($validator)
+                ->withInput();
+        }
+
+        $values = [
+            //SETTINGS::VALUE => REQUEST-VALUE (coming from the html-form)
+            "SETTINGS::PAYMENTS:PAYPAL:SECRET" => "paypal-client-secret",
+            "SETTINGS::PAYMENTS:PAYPAL:CLIENT_ID" => "paypal-client-id",
+            "SETTINGS::PAYMENTS:PAYPAL:SANDBOX_SECRET" => "paypal-sandbox-secret",
+            "SETTINGS::PAYMENTS:PAYPAL:SANDBOX_CLIENT_ID" => "paypal-sandbox-id",
+            "SETTINGS::PAYMENTS:STRIPE:SECRET" => "stripe-secret",
+            "SETTINGS::PAYMENTS:STRIPE:ENDPOINT_SECRET" => "stripe-endpoint-secret",
+            "SETTINGS::PAYMENTS:STRIPE:TEST_SECRET" => "stripe-test-secret",
+            "SETTINGS::PAYMENTS:STRIPE:ENDPOINT_TEST_SECRET" => "stripe-endpoint-test-secret",
+            "SETTINGS::PAYMENTS:STRIPE:METHODS" => "stripe-methods",
+            "SETTINGS::PAYMENTS:SALES_TAX" => "sales-tax"
+        ];
+
+
+        foreach ($values as $key => $value) {
+            $param = $request->get($value);
+
+            Settings::where('key', $key)->updateOrCreate(['key' => $key], ['value' => $param]);
+            Cache::forget("setting" . ':' . $key);
+        }
+
+        return redirect(route('admin.settings.index') . '#payment')->with('success', __('Payment settings updated!'));
+    }
+}

+ 73 - 0
app/Classes/Settings/System.php

@@ -0,0 +1,73 @@
+<?php
+
+namespace App\Classes\Settings;
+
+use App\Models\Settings;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Cache;
+use Illuminate\Support\Facades\Validator;
+
+class System
+{
+
+
+    public function __construct()
+    {
+        return;
+    }
+
+
+
+    public function updateSettings(Request $request)
+    {
+        $validator = Validator::make($request->all(), [
+            "register-ip-check" => "string",
+            "server-create-charge-first-hour" => "string",
+            "credits-display-name" => "required|string",
+            "allocation-limit" => "required|min:0|integer",
+            "force-email-verification" => "string",
+            "force-discord-verification" => "string",
+            "initial-credits" => "required|min:0|integer",
+            "initial-server-limit" => "required|min:0|integer",
+            "credits-reward-amount-discord" => "required|min:0|integer",
+            "credits-reward-amount-email" => "required|min:0|integer",
+            "server-limit-discord" => "required|min:0|integer",
+            "server-limit-email" => "required|min:0|integer",
+            "pterodactyl-api-key" => "required|string",
+            "pterodactyl-url" => "required|string",
+
+        ]);
+        if ($validator->fails()) {
+            return redirect(route('admin.settings.index') . '#system')->with('error', __('System settings have not been updated!'))->withErrors($validator)
+                ->withInput();
+        }
+
+
+        $values = [
+            "SETTINGS::SYSTEM:REGISTER_IP_CHECK" => "register-ip-check",
+            "SETTINGS::SYSTEM:SERVER_CREATE_CHARGE_FIRST_HOUR" => "server-create-charge-first-hour",
+            "SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME" => "credits-display-name",
+            "SETTINGS::SERVER:ALLOCATION_LIMIT" => "allocation-limit",
+            "SETTINGS::USER:FORCE_DISCORD_VERIFICATION" => "force-discord-verification",
+            "SETTINGS::USER:FORCE_EMAIL_VERIFICATION" => "force-email-verification",
+            "SETTINGS::USER:INITIAL_CREDITS" => "initial-credits",
+            "SETTINGS::USER:INITIAL_SERVER_LIMIT" => "initial-server-limit",
+            "SETTINGS::USER:CREDITS_REWARD_AFTER_VERIFY_DISCORD" => "credits-reward-amount-discord",
+            "SETTINGS::USER:CREDITS_REWARD_AFTER_VERIFY_EMAIL" => "credits-reward-amount-email",
+            "SETTINGS::USER:SERVER_LIMIT_REWARD_AFTER_VERIFY_DISCORD" => "server-limit-discord",
+            "SETTINGS::USER:SERVER_LIMIT_REWARD_AFTER_VERIFY_EMAIL" => "server-limit-email",
+            "SETTINGS::MISC:PHPMYADMIN:URL" => "phpmyadmin-url",
+            "SETTINGS::SYSTEM:PTERODACTYL:URL" => "pterodactyl-url",
+            "SETTINGS::SYSTEM:PTERODACTYL:TOKEN" => "pterodactyl-api-key",
+        ];
+
+
+        foreach ($values as $key => $value) {
+            $param = $request->get($value);
+
+            Settings::where('key', $key)->updateOrCreate(['key' => $key], ['value' => $param]);
+            Cache::forget("setting" . ':' . $key);
+        }
+        return redirect(route('admin.settings.index') . '#system')->with('success', __('System settings updated!'));
+    }
+}

+ 0 - 123
app/Http/Controllers/Admin/ConfigurationController.php

@@ -1,123 +0,0 @@
-<?php
-
-namespace App\Http\Controllers\Admin;
-
-use App\Http\Controllers\Controller;
-use App\Models\Configuration;
-use Illuminate\Contracts\Foundation\Application;
-use Illuminate\Contracts\View\Factory;
-use Illuminate\Contracts\View\View;
-use Illuminate\Http\Request;
-use Illuminate\Http\Response;
-
-class ConfigurationController extends Controller
-{
-    /**
-     * Display a listing of the resource.
-     *
-     * @return Application|Factory|View|Response
-     */
-    public function index()
-    {
-        return view('admin.configurations.index');
-    }
-
-    /**
-     * Show the form for creating a new resource.
-     *
-     * @return Response
-     */
-    public function create()
-    {
-        //
-    }
-
-    /**
-     * Store a newly created resource in storage.
-     *
-     * @param Request $request
-     * @return Response
-     */
-    public function store(Request $request)
-    {
-        //
-    }
-
-    /**
-     * Display the specified resource.
-     *
-     * @param Configuration $configuration
-     * @return Response
-     */
-    public function show(Configuration $configuration)
-    {
-        //
-    }
-
-    /**
-     * Show the form for editing the specified resource.
-     *
-     * @param Configuration $configuration
-     * @return Response
-     */
-    public function edit(Configuration $configuration)
-    {
-        //
-    }
-
-    /**
-     * Update the specified resource in storage.
-     *
-     * @param Request $request
-     * @param Configuration $configuration
-     * @return Response
-     */
-    public function update(Request $request, Configuration $configuration)
-    {
-        //
-    }
-
-    /**
-     * @param Request $request
-     * @return \Illuminate\Http\RedirectResponse
-     */
-    public function updatevalue(Request $request)
-    {
-        $configuration = Configuration::findOrFail($request->input('key'));
-
-        $request->validate([
-            'key'   => 'required|string|max:191',
-            'value' => 'required|string|max:191',
-        ]);
-
-        $configuration->update($request->all());
-
-        return redirect()->route('admin.configurations.index')->with('success', __('configuration has been updated!'));
-    }
-
-    /**
-     * Remove the specified resource from storage.
-     *
-     * @param Configuration $configuration
-     * @return Response
-     */
-    public function destroy(Configuration $configuration)
-    {
-        //
-    }
-
-    public function datatable()
-    {
-        $query = Configuration::query();
-
-        return datatables($query)
-            ->addColumn('actions', function (Configuration $configuration) {
-                return '<button data-content="'.__("Edit").'" data-toggle="popover" data-trigger="hover" data-placement="top" onclick="configuration.parse(\'' . $configuration->key . '\',\'' . $configuration->value . '\',\'' . $configuration->type . '\')" data-content="Edit" data-trigger="hover" data-toggle="tooltip" class="btn btn-sm btn-info mr-1"><i class="fas fa-pen"></i></button> ';
-            })
-            ->editColumn('created_at', function (Configuration $configuration) {
-                return $configuration->created_at ? $configuration->created_at->diffForHumans() : '';
-            })
-            ->rawColumns(['actions'])
-            ->make();
-    }
-}

+ 3 - 2
app/Http/Controllers/Admin/CreditProductController.php

@@ -3,6 +3,7 @@
 namespace App\Http\Controllers\Admin;
 namespace App\Http\Controllers\Admin;
 
 
 use App\Models\CreditProduct;
 use App\Models\CreditProduct;
+use App\Models\Settings;
 use Illuminate\Contracts\Foundation\Application;
 use Illuminate\Contracts\Foundation\Application;
 use Illuminate\Contracts\View\Factory;
 use Illuminate\Contracts\View\Factory;
 use Illuminate\Contracts\View\View;
 use Illuminate\Contracts\View\View;
@@ -25,8 +26,8 @@ class CreditProductController extends Controller
 
 
         if (
         if (
             env('APP_ENV') == 'local' ||
             env('APP_ENV') == 'local' ||
-            env('PAYPAL_SECRET') && env('PAYPAL_CLIENT_ID') ||
-            env('STRIPE_SECRET') && env('STRIPE_ENDPOINT_SECRET') && env('STRIPE_METHODS')
+            Settings::getValueByKey("SETTINGS::PAYMENTS:PAYPAL:SECRET") && Settings::getValueByKey("SETTINGS::PAYMENTS:PAYPAL:CLIENT_ID") ||
+            Settings::getValueByKey("SETTINGS::PAYMENTS:STRIPE:SECRET") && Settings::getValueByKey("SETTINGS::PAYMENTS:STRIPE:ENDPOINT_SECRET") && Settings::getValueByKey("SETTINGS::PAYMENTS:STRIPE:METHODS")
         ) $isPaymentSetup = true;
         ) $isPaymentSetup = true;
 
 
         return view('admin.store.index', [
         return view('admin.store.index', [

+ 70 - 0
app/Http/Controllers/Admin/InvoiceController.php

@@ -0,0 +1,70 @@
+<?php
+
+namespace App\Http\Controllers\Admin;
+
+use App\Http\Controllers\Controller;
+use App\Models\Invoice;
+use Illuminate\Http\Request;
+use Throwable;
+use ZipArchive;
+
+class InvoiceController extends Controller
+{
+
+    public function downloadAllInvoices()
+    {
+        $zip = new ZipArchive;
+        $zip_safe_path = storage_path('invoices.zip');
+        $res = $zip->open($zip_safe_path, ZipArchive::CREATE | ZipArchive::OVERWRITE);
+        $result = $dthis::rglob(storage_path('app/invoice/*'));
+        if ($res === TRUE) {
+            $zip->addFromString("1. Info.txt", __("Created at") . " " . now()->format("d.m.Y"));
+            foreach ($result as $file) {
+                if (file_exists($file) && is_file($file)) {
+                    $zip->addFile($file, basename($file));
+                }
+            }
+            $zip->close();
+        }
+        return response()->download($zip_safe_path);
+    }
+
+    /**
+     * @param $pattern
+     * @param $flags
+     * @return array|false
+     */
+    public function rglob($pattern, $flags = 0)
+    {
+        $files = glob($pattern, $flags);
+        foreach (glob(dirname($pattern) . '/*', GLOB_ONLYDIR | GLOB_NOSORT) as $dir) {
+            $files = array_merge($files, $this::rglob($dir . '/' . basename($pattern), $flags));
+        }
+        return $files;
+    }
+
+    /**
+     * @param $paymentID
+     * @param $date
+     */
+    public function downloadSingleInvoice(Request $request)
+    {
+        $id = $request->id;
+        try {
+            $query = Invoice::where('payment_id', '=', $id)->firstOrFail();
+        } catch (Throwable $e) {
+            return redirect()->back()->with("error", __("Error!"));
+        }
+
+        $invoice_path = storage_path('app/invoice/' . $query->invoice_user . '/' . $query->created_at->format("Y") . '/' . $query->invoice_name . '.pdf');
+
+        if (!file_exists($invoice_path)) {
+            return redirect()->back()->with("error", __("Error!"));
+        }
+
+
+        return response()->download($invoice_path);
+
+    }
+
+}

+ 47 - 30
app/Http/Controllers/Admin/PaymentController.php

@@ -4,10 +4,10 @@ namespace App\Http\Controllers\Admin;
 
 
 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\InvoiceSettings;
 use App\Models\InvoiceSettings;
 use App\Models\Payment;
 use App\Models\Payment;
 use App\Models\CreditProduct;
 use App\Models\CreditProduct;
+use App\Models\Settings;
 use App\Models\User;
 use App\Models\User;
 use App\Notifications\InvoiceNotification;
 use App\Notifications\InvoiceNotification;
 use App\Notifications\ConfirmPaymentNotification;
 use App\Notifications\ConfirmPaymentNotification;
@@ -134,7 +134,7 @@ class PaymentController extends Controller
      */
      */
     protected function getPaypalClientId()
     protected function getPaypalClientId()
     {
     {
-        return env('APP_ENV') == 'local' ? env('PAYPAL_SANDBOX_CLIENT_ID') : env('PAYPAL_CLIENT_ID');
+        return env('APP_ENV') == 'local' ?  Settings::getValueByKey("SETTINGS::PAYMENTS:PAYPAL:SANDBOX_CLIENT_ID") : Settings::getValueByKey("SETTINGS::PAYMENTS:PAYPAL:CLIENT_ID");
     }
     }
 
 
     /**
     /**
@@ -142,7 +142,7 @@ class PaymentController extends Controller
      */
      */
     protected function getPaypalClientSecret()
     protected function getPaypalClientSecret()
     {
     {
-        return env('APP_ENV') == 'local' ? env('PAYPAL_SANDBOX_SECRET') : env('PAYPAL_SECRET');
+        return env('APP_ENV') == 'local' ? Settings::getValueByKey("SETTINGS::PAYMENTS:PAYPAL:SANDBOX_SECRET") : Settings::getValueByKey("SETTINGS::PAYMENTS:PAYPAL:SECRET");
     }
     }
 
 
     /**
     /**
@@ -167,9 +167,9 @@ class PaymentController extends Controller
                 $user->increment('credits', $creditProduct->quantity);
                 $user->increment('credits', $creditProduct->quantity);
 
 
                 //update server limit
                 //update server limit
-                if (Configuration::getValueByKey('SERVER_LIMIT_AFTER_IRL_PURCHASE') !== 0) {
-                    if ($user->server_limit < Configuration::getValueByKey('SERVER_LIMIT_AFTER_IRL_PURCHASE')) {
-                        $user->update(['server_limit' => Configuration::getValueByKey('SERVER_LIMIT_AFTER_IRL_PURCHASE')]);
+                if (Settings::getValueByKey('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE') !== 0) {
+                    if ($user->server_limit < Settings::getValueByKey('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE')) {
+                        $user->update(['server_limit' => Settings::getValueByKey('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE')]);
                     }
                     }
                 }
                 }
 
 
@@ -197,7 +197,11 @@ class PaymentController extends Controller
 
 
                 event(new UserUpdateCreditsEvent($user));
                 event(new UserUpdateCreditsEvent($user));
 
 
-                $this->createInvoice($user, $payment, 'paid');
+                //only create invoice if SETTINGS::INVOICE:ENABLED is true
+                if (config('SETTINGS::INVOICE:ENABLED') == 'true') {
+                    $this->createInvoice($user, $payment, 'paid');
+                }
+
 
 
                 //redirect back to home
                 //redirect back to home
                 return redirect()->route('home')->with('success', __('Your credit balance has been increased!'));
                 return redirect()->route('home')->with('success', __('Your credit balance has been increased!'));
@@ -266,7 +270,7 @@ class PaymentController extends Controller
             ],
             ],
 
 
             'mode' => 'payment',
             'mode' => 'payment',
-            "payment_method_types" => str_getcsv(str_replace(' ', '', env('STRIPE_METHODS'))),
+            "payment_method_types" => str_getcsv(config("SETTINGS::PAYMENTS:STRIPE:METHODS")),
             'success_url' => route('payment.StripeSuccess',  ['product' => $creditProduct->id]) . '&session_id={CHECKOUT_SESSION_ID}',
             'success_url' => route('payment.StripeSuccess',  ['product' => $creditProduct->id]) . '&session_id={CHECKOUT_SESSION_ID}',
             'cancel_url' => route('payment.Cancel'),
             'cancel_url' => route('payment.Cancel'),
         ]);
         ]);
@@ -304,9 +308,9 @@ class PaymentController extends Controller
                 $user->increment('credits', $creditProduct->quantity);
                 $user->increment('credits', $creditProduct->quantity);
 
 
                 //update server limit
                 //update server limit
-                if (Configuration::getValueByKey('SERVER_LIMIT_AFTER_IRL_PURCHASE') !== 0) {
-                    if ($user->server_limit < Configuration::getValueByKey('SERVER_LIMIT_AFTER_IRL_PURCHASE')) {
-                        $user->update(['server_limit' => Configuration::getValueByKey('SERVER_LIMIT_AFTER_IRL_PURCHASE')]);
+                if (Settings::getValueByKey('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE') !== 0) {
+                    if ($user->server_limit < Settings::getValueByKey('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE')) {
+                        $user->update(['server_limit' => Settings::getValueByKey('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE')]);
                     }
                     }
                 }
                 }
 
 
@@ -336,7 +340,10 @@ class PaymentController extends Controller
 
 
                 event(new UserUpdateCreditsEvent($user));
                 event(new UserUpdateCreditsEvent($user));
 
 
-                $this->createInvoice($user, $payment, 'paid');
+                //only create invoice if SETTINGS::INVOICE:ENABLED is true
+                if (config('SETTINGS::INVOICE:ENABLED') == 'true') {
+                    $this->createInvoice($user, $payment, 'paid');
+                }
 
 
                 //redirect back to home
                 //redirect back to home
                 return redirect()->route('home')->with('success', __('Your credit balance has been increased!'));
                 return redirect()->route('home')->with('success', __('Your credit balance has been increased!'));
@@ -359,7 +366,10 @@ class PaymentController extends Controller
                         'credit_product_id' => $creditProduct->id,
                         'credit_product_id' => $creditProduct->id,
                     ]);
                     ]);
 
 
-                    $this->createInvoice($user, $payment, 'processing');
+                    //only create invoice if SETTINGS::INVOICE:ENABLED is true
+                    if (config('SETTINGS::INVOICE:ENABLED') == 'true') {
+                        $this->createInvoice($user, $payment, 'paid');
+                    }
 
 
                     //redirect back to home
                     //redirect back to home
                     return redirect()->route('home')->with('success', __('Your payment is being processed!'));
                     return redirect()->route('home')->with('success', __('Your payment is being processed!'));
@@ -398,9 +408,9 @@ class PaymentController extends Controller
                 $user->increment('credits', $payment->amount);
                 $user->increment('credits', $payment->amount);
 
 
                 //update server limit
                 //update server limit
-                if (Configuration::getValueByKey('SERVER_LIMIT_AFTER_IRL_PURCHASE') !== 0) {
-                    if ($user->server_limit < Configuration::getValueByKey('SERVER_LIMIT_AFTER_IRL_PURCHASE')) {
-                        $user->update(['server_limit' => Configuration::getValueByKey('SERVER_LIMIT_AFTER_IRL_PURCHASE')]);
+                if (Settings::getValueByKey('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE') !== 0) {
+                    if ($user->server_limit < Settings::getValueByKey('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE')) {
+                        $user->update(['server_limit' => Settings::getValueByKey('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE')]);
                     }
                     }
                 }
                 }
 
 
@@ -416,7 +426,10 @@ class PaymentController extends Controller
                 $user->notify(new ConfirmPaymentNotification($payment));
                 $user->notify(new ConfirmPaymentNotification($payment));
                 event(new UserUpdateCreditsEvent($user));
                 event(new UserUpdateCreditsEvent($user));
 
 
-                $this->createInvoice($user, $payment, 'paid');
+                //only create invoice if SETTINGS::INVOICE:ENABLED is true
+                if (config('SETTINGS::INVOICE:ENABLED') == 'true') {
+                    $this->createInvoice($user, $payment, 'paid');
+                }
             }
             }
         } catch (HttpException $ex) {
         } catch (HttpException $ex) {
             abort(422);
             abort(422);
@@ -474,8 +487,8 @@ class PaymentController extends Controller
     protected function getStripeSecret()
     protected function getStripeSecret()
     {
     {
         return env('APP_ENV') == 'local'
         return env('APP_ENV') == 'local'
-            ?  env('STRIPE_TEST_SECRET')
-            :  env('STRIPE_SECRET');
+            ?  Settings::getValueByKey("SETTINGS::PAYMENTS:STRIPE:TEST_SECRET")
+            :  Settings::getValueByKey("SETTINGS::PAYMENTS:STRIPE:SECRET");
     }
     }
 
 
     /**
     /**
@@ -484,8 +497,8 @@ class PaymentController extends Controller
     protected function getStripeEndpointSecret()
     protected function getStripeEndpointSecret()
     {
     {
         return env('APP_ENV') == 'local'
         return env('APP_ENV') == 'local'
-            ?  env('STRIPE_ENDPOINT_TEST_SECRET')
-            :  env('STRIPE_ENDPOINT_SECRET');
+            ?  Settings::getValueByKey("SETTINGS::PAYMENTS:STRIPE:ENDPOINT_TEST_SECRET")
+            :  Settings::getValueByKey("SETTINGS::PAYMENTS:STRIPE:ENDPOINT_SECRET");
     }
     }
 
 
 
 
@@ -495,17 +508,16 @@ class PaymentController extends Controller
         //create invoice
         //create invoice
         $lastInvoiceID = \App\Models\Invoice::where("invoice_name", "like", "%" . now()->format('mY') . "%")->count("id");
         $lastInvoiceID = \App\Models\Invoice::where("invoice_name", "like", "%" . now()->format('mY') . "%")->count("id");
         $newInvoiceID = $lastInvoiceID + 1;
         $newInvoiceID = $lastInvoiceID + 1;
-        $InvoiceSettings = InvoiceSettings::query()->first();
         $logoPath = storage_path('app/public/logo.png');
         $logoPath = storage_path('app/public/logo.png');
 
 
         $seller = new Party([
         $seller = new Party([
-            'name' => $InvoiceSettings->company_name,
-            'phone' => $InvoiceSettings->company_phone,
-            'address' => $InvoiceSettings->company_adress,
-            'vat' => $InvoiceSettings->company_vat,
+            'name' => Settings::getValueByKey("SETTINGS::INVOICE:COMPANY_NAME"),
+            'phone' => Settings::getValueByKey("SETTINGS::INVOICE:COMPANY_PHONE"),
+            'address' => Settings::getValueByKey("SETTINGS::INVOICE:COMPANY_ADDRESS"),
+            'vat' => Settings::getValueByKey("SETTINGS::INVOICE:COMPANY_VAT"),
             'custom_fields' => [
             'custom_fields' => [
-                'E-Mail' => $InvoiceSettings->company_mail,
-                "Web" => $InvoiceSettings->company_web
+                'E-Mail' => Settings::getValueByKey("SETTINGS::INVOICE:COMPANY_MAIL"),
+                "Web" => Settings::getValueByKey("SETTINGS::INVOICE:COMPANY_WEBSITE")
             ],
             ],
         ]);
         ]);
 
 
@@ -540,7 +552,7 @@ class PaymentController extends Controller
             ->series(now()->format('mY'))
             ->series(now()->format('mY'))
             ->delimiter("-")
             ->delimiter("-")
             ->sequence($newInvoiceID)
             ->sequence($newInvoiceID)
-            ->serialNumberFormat($InvoiceSettings->invoice_prefix . '{DELIMITER}{SERIES}{SEQUENCE}')
+            ->serialNumberFormat(Settings::getValueByKey("SETTINGS::INVOICE:PREFIX") . '{DELIMITER}{SERIES}{SEQUENCE}')
             ->notes($notes);
             ->notes($notes);
 
 
         if (file_exists($logoPath)) {
         if (file_exists($logoPath)) {
@@ -591,6 +603,11 @@ class PaymentController extends Controller
             ->editColumn('created_at', function (Payment $payment) {
             ->editColumn('created_at', function (Payment $payment) {
                 return $payment->created_at ? $payment->created_at->diffForHumans() : '';
                 return $payment->created_at ? $payment->created_at->diffForHumans() : '';
             })
             })
-            ->make();
+            ->addColumn('actions', function (Payment $payment) {
+                return ' <a data-content="' . __("Download") . '" data-toggle="popover" data-trigger="hover" data-placement="top"  href="' . route('admin.invoices.downloadSingleInvoice', "id=" . $payment->payment_id) . '" class="btn btn-sm text-white btn-info mr-1"><i class="fas fa-file-download"></i></a>
+';
+            })
+            ->rawColumns(['actions'])
+            ->make(true);
     }
     }
 }
 }

+ 2 - 5
app/Http/Controllers/Admin/ProductController.php

@@ -3,12 +3,10 @@
 namespace App\Http\Controllers\Admin;
 namespace App\Http\Controllers\Admin;
 
 
 use App\Http\Controllers\Controller;
 use App\Http\Controllers\Controller;
-use App\Models\Egg;
 use App\Models\Location;
 use App\Models\Location;
 use App\Models\Nest;
 use App\Models\Nest;
-use App\Models\Node;
-use App\Models\Configuration;
 use App\Models\Product;
 use App\Models\Product;
+use App\Models\Settings;
 use Exception;
 use Exception;
 use Illuminate\Contracts\Foundation\Application;
 use Illuminate\Contracts\Foundation\Application;
 use Illuminate\Contracts\View\Factory;
 use Illuminate\Contracts\View\Factory;
@@ -16,7 +14,6 @@ use Illuminate\Contracts\View\View;
 use Illuminate\Http\JsonResponse;
 use Illuminate\Http\JsonResponse;
 use Illuminate\Http\RedirectResponse;
 use Illuminate\Http\RedirectResponse;
 use Illuminate\Http\Request;
 use Illuminate\Http\Request;
-use Illuminate\Http\Response;
 
 
 class ProductController extends Controller
 class ProductController extends Controller
 {
 {
@@ -97,7 +94,7 @@ class ProductController extends Controller
     {
     {
         return view('admin.products.show', [
         return view('admin.products.show', [
             'product' => $product,
             'product' => $product,
-            'minimum_credits' => Configuration::getValueByKey("MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER"),
+            'minimum_credits' => Settings::getValueByKey("SETTINGS::USER:MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER"),
         ]);
         ]);
     }
     }
 
 

+ 2 - 1
app/Http/Controllers/Admin/ServerController.php

@@ -6,6 +6,7 @@ use App\Classes\Pterodactyl;
 use App\Classes\PterodactylWrapper;
 use App\Classes\PterodactylWrapper;
 use App\Http\Controllers\Controller;
 use App\Http\Controllers\Controller;
 use App\Models\Server;
 use App\Models\Server;
+use App\Models\Settings;
 use Exception;
 use Exception;
 use Illuminate\Contracts\Foundation\Application;
 use Illuminate\Contracts\Foundation\Application;
 use Illuminate\Contracts\View\Factory;
 use Illuminate\Contracts\View\Factory;
@@ -161,7 +162,7 @@ class ServerController extends Controller
                 return $server->suspended ? $server->suspended->diffForHumans() : '';
                 return $server->suspended ? $server->suspended->diffForHumans() : '';
             })
             })
             ->editColumn('name', function (Server $server) {
             ->editColumn('name', function (Server $server) {
-                return '<a class="text-info" target="_blank" href="' . env('PTERODACTYL_URL', 'http://localhost') . '/admin/servers/view/' . $server->pterodactyl_id . '">' . $server->name . '</a>';
+                return '<a class="text-info" target="_blank" href="' . Settings::getValueByKey("SETTINGS::SYSTEM:PTERODACTYL:URL") . '/admin/servers/view/' . $server->pterodactyl_id . '">' . $server->name . '</a>';
             })
             })
             ->rawColumns(['user', 'actions', 'status', 'name'])
             ->rawColumns(['user', 'actions', 'status', 'name'])
             ->make();
             ->make();

+ 47 - 61
app/Http/Controllers/Admin/SettingsController.php

@@ -3,13 +3,12 @@
 namespace App\Http\Controllers\Admin;
 namespace App\Http\Controllers\Admin;
 
 
 use App\Http\Controllers\Controller;
 use App\Http\Controllers\Controller;
-use App\Models\InvoiceSettings;
+use App\Models\Settings;
 use Illuminate\Contracts\Foundation\Application;
 use Illuminate\Contracts\Foundation\Application;
 use Illuminate\Contracts\View\Factory;
 use Illuminate\Contracts\View\Factory;
 use Illuminate\Contracts\View\View;
 use Illuminate\Contracts\View\View;
 use Illuminate\Http\Request;
 use Illuminate\Http\Request;
 use Illuminate\Http\Response;
 use Illuminate\Http\Response;
-use ZipArchive;
 
 
 class SettingsController extends Controller
 class SettingsController extends Controller
 {
 {
@@ -20,81 +19,68 @@ class SettingsController extends Controller
      */
      */
     public function index()
     public function index()
     {
     {
-        /** @var InvoiceSettings $invoiceSettings */
-        $invoiceSettings = InvoiceSettings::first();
-
-        return view('admin.settings.index', $invoiceSettings->toArray());
-    }
-
-    public function updateIcons(Request $request)
-    {
-        $request->validate([
-            'icon' => 'nullable|max:10000|mimes:jpg,png,jpeg',
-            'favicon' => 'nullable|max:10000|mimes:ico',
-        ]);
-
-        if ($request->hasFile('icon')) {
-            $request->file('icon')->storeAs('public', 'icon.png');
+        //Get all tabs as laravel view paths
+        $tabs = [];
+        foreach (glob(resource_path('views/admin/settings/tabs/*.blade.php')) as $filename) {
+            $tabs[] = 'admin.settings.tabs.' . basename($filename, '.blade.php');
         }
         }
 
 
-        if ($request->hasFile('favicon')) {
-            $request->file('favicon')->storeAs('public', 'favicon.ico');
+        //Generate a html list item for each tab based on tabs file basename, set first tab as active
+        $tabListItems = [];
+        foreach ($tabs as $tab) {
+            $tabName = str_replace('admin.settings.tabs.', '', $tab);
+            $tabListItems[] = '<li class="nav-item">
+            <a class="nav-link ' . (empty($tabListItems) ? 'active' : '') . '" data-toggle="pill" href="#' . $tabName . '">
+            ' . __(ucfirst($tabName)) . '
+            </a></li>';
         }
         }
 
 
-        return redirect()->route('admin.settings.index')->with('success', __('Icons updated!'));
+        return view('admin.settings.index', [
+            'tabs' => $tabs,
+            'tabListItems' => $tabListItems,
+        ]);
     }
     }
 
 
-    public function updateInvoiceSettings(Request $request)
+
+    public function updatevalue(Request $request)
     {
     {
-        $request->validate([
-            'logo' => 'nullable|max:10000|mimes:jpg,png,jpeg',
-        ]);
+        $setting = Settings::findOrFail($request->input('key'));
 
 
-        InvoiceSettings::updateOrCreate([
-            'id' => "1"
-        ], [
-            'company_name' => $request->get('company-name'),
-            'company_adress' => $request->get('company-address'),
-            'company_phone' => $request->get('company-phone'),
-            'company_mail' => $request->get('company-mail'),
-            'company_vat' => $request->get('company-vat'),
-            'company_web' => $request->get('company-web'),
-            'invoice_prefix' => $request->get('invoice-prefix'),
+        $request->validate([
+            'key'   => 'required|string|max:191',
+            'value' => 'required|string|max:191',
         ]);
         ]);
 
 
-        if ($request->hasFile('logo')) {
-            $request->file('logo')->storeAs('public', 'logo.png');
-        }
+        $setting->update($request->all());
 
 
-
-        return redirect()->route('admin.settings.index')->with('success', 'Invoice settings updated!');
+        return redirect()->route('admin.settings.index')->with('success', __('configuration has been updated!'));
     }
     }
 
 
-    public function downloadAllInvoices()
+    /**
+     * Remove the specified resource from storage.
+     *
+     * @param Settings $setting
+     * @return Response
+     */
+    public function destroy(Settings $setting)
     {
     {
-        $zip = new ZipArchive;
-        $zip_safe_path = storage_path('invoices.zip');
-        $res = $zip->open($zip_safe_path, ZipArchive::CREATE | ZipArchive::OVERWRITE);
-        $result = $this::rglob(storage_path('app/invoice/*'));
-        if ($res === TRUE) {
-            $zip->addFromString("1. Info.txt", "This Archive contains all Invoices from all Users!\nIf there are no Invoices here, no Invoices have ever been created!");
-            foreach ($result as $file) {
-                if (file_exists($file) && is_file($file)) {
-                    $zip->addFile($file, basename($file));
-                }
-            }
-            $zip->close();
-        }
-        return response()->download($zip_safe_path);
+        //
     }
     }
 
 
-    public function rglob($pattern, $flags = 0)
+    public function datatable()
     {
     {
-        $files = glob($pattern, $flags);
-        foreach (glob(dirname($pattern) . '/*', GLOB_ONLYDIR | GLOB_NOSORT) as $dir) {
-            $files = array_merge($files, $this::rglob($dir . '/' . basename($pattern), $flags));
-        }
-        return $files;
+        $query = Settings::where('key', 'like', '%SYSTEM%')
+            ->orWhere('key', 'like', '%USER%')
+            ->orWhere('key', 'like', '%SERVER%');
+
+        return datatables($query)
+            ->addColumn('actions', function (Settings $setting) {
+                return '<button data-content="' . __("Edit") . '" data-toggle="popover" data-trigger="hover" data-placement="top" onclick="configuration.parse(\'' . $setting->key . '\',\'' . $setting->value . '\',\'' . $setting->type . '\')" data-content="Edit" data-trigger="hover" data-toggle="tooltip" class="btn btn-sm btn-info mr-1"><i class="fas fa-pen"></i></button> ';
+            })
+            ->editColumn('created_at', function (Settings $setting) {
+                return $setting->created_at ? $setting->created_at->diffForHumans() : '';
+            })
+            ->rawColumns(['actions'])
+            ->make();
     }
     }
-
 }
 }

+ 2 - 1
app/Http/Controllers/Admin/UserController.php

@@ -5,6 +5,7 @@ namespace App\Http\Controllers\Admin;
 use App\Classes\Pterodactyl;
 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\Settings;
 use App\Models\User;
 use App\Models\User;
 use App\Notifications\DynamicNotification;
 use App\Notifications\DynamicNotification;
 use Spatie\QueryBuilder\QueryBuilder;
 use Spatie\QueryBuilder\QueryBuilder;
@@ -300,7 +301,7 @@ class UserController extends Controller
                 return '<span class="badge ' . $badgeColor . '">' . $user->role . '</span>';
                 return '<span class="badge ' . $badgeColor . '">' . $user->role . '</span>';
             })
             })
             ->editColumn('name', function (User $user) {
             ->editColumn('name', function (User $user) {
-                return '<a class="text-info" target="_blank" href="' . env('PTERODACTYL_URL', 'http://localhost') . '/admin/users/view/' . $user->pterodactyl_id . '">' . $user->name . '</a>';
+                return '<a class="text-info" target="_blank" href="' . Settings::getValueByKey("SETTINGS::SYSTEM:PTERODACTYL:URL") . '/admin/users/view/' . $user->pterodactyl_id . '">' . $user->name . '</a>';
             })
             })
             ->orderColumn('last_seen', function ($query, $order) {
             ->orderColumn('last_seen', function ($query, $order) {
                 $query->orderBy('last_seen', $order);
                 $query->orderBy('last_seen', $order);

+ 3 - 3
app/Http/Controllers/Api/UserController.php

@@ -5,8 +5,8 @@ namespace App\Http\Controllers\Api;
 use App\Classes\Pterodactyl;
 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\Settings;
 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\Pagination\LengthAwarePaginator;
@@ -242,8 +242,8 @@ class UserController extends Controller
         $user = User::create([
         $user = User::create([
             'name' => $request->input('name'),
             'name' => $request->input('name'),
             'email' => $request->input('email'),
             'email' => $request->input('email'),
-            'credits' => Configuration::getValueByKey('INITIAL_CREDITS', 150),
-            'server_limit' => Configuration::getValueByKey('INITIAL_SERVER_LIMIT', 1),
+            'credits' => Settings::getValueByKey('SETTINGS::USER:INITIAL_CREDITS', 150),
+            'server_limit' => Settings::getValueByKey('SETTINGS::USER:INITIAL_SERVER_LIMIT', 1),
             'password' => Hash::make($request->input('password')),
             'password' => Hash::make($request->input('password')),
         ]);
         ]);
 
 

+ 13 - 5
app/Http/Controllers/Auth/LoginController.php

@@ -41,17 +41,25 @@ class LoginController extends Controller
 
 
     public function login(Request $request)
     public function login(Request $request)
     {
     {
-        $request->validate([
+
+        $validationRules = [
             $this->username()      => 'required|string',
             $this->username()      => 'required|string',
             'password'             => 'required|string',
             'password'             => 'required|string',
-            'g-recaptcha-response' => ['required','recaptcha'],
-        ]);
+        ];
+        if (config('SETTINGS::RECAPTCHA:ENABLED') == 'true') {
+            $validationRules['g-recaptcha-response'] = ['required', 'recaptcha'];
+        }
+        $request->validate($validationRules);
+
+
 
 
         // If the class is using the ThrottlesLogins trait, we can automatically throttle
         // If the class is using the ThrottlesLogins trait, we can automatically throttle
         // the login attempts for this application. We'll key this by the username and
         // the login attempts for this application. We'll key this by the username and
         // the IP address of the client making these requests into this application.
         // the IP address of the client making these requests into this application.
-        if (method_exists($this, 'hasTooManyLoginAttempts') &&
-            $this->hasTooManyLoginAttempts($request)) {
+        if (
+            method_exists($this, 'hasTooManyLoginAttempts') &&
+            $this->hasTooManyLoginAttempts($request)
+        ) {
             $this->fireLockoutEvent($request);
             $this->fireLockoutEvent($request);
 
 
             return $this->sendLockoutResponse($request);
             return $this->sendLockoutResponse($request);

+ 17 - 19
app/Http/Controllers/Auth/RegisterController.php

@@ -4,7 +4,7 @@ namespace App\Http\Controllers\Auth;
 
 
 use App\Classes\Pterodactyl;
 use App\Classes\Pterodactyl;
 use App\Http\Controllers\Controller;
 use App\Http\Controllers\Controller;
-use App\Models\Configuration;
+use App\Models\Settings;
 use App\Models\User;
 use App\Models\User;
 use App\Providers\RouteServiceProvider;
 use App\Providers\RouteServiceProvider;
 use Illuminate\Foundation\Auth\RegistersUsers;
 use Illuminate\Foundation\Auth\RegistersUsers;
@@ -54,30 +54,28 @@ class RegisterController extends Controller
      */
      */
     protected function validator(array $data)
     protected function validator(array $data)
     {
     {
-        if (Configuration::getValueByKey('REGISTER_IP_CHECK', 'true') == 'true') {
+        $validationRules = [
+            'name'                 => ['required', 'string', 'max:30', 'min:4', 'alpha_num', 'unique:users'],
+            'email'                => ['required', 'string', 'email', 'max:64', 'unique:users'],
+            'password'             => ['required', 'string', 'min:8', 'confirmed'],
+        ];
+        if (config('SETTINGS::RECAPTCHA:ENABLED') == 'true') {
+            $validationRules['g-recaptcha-response'] = ['required', 'recaptcha'];
+        }
+
+        if (config('SETTINGS::SYSTEM:REGISTER_IP_CHECK', 'true') == 'true') {
 
 
             //check if ip has already made an account
             //check if ip has already made an account
             $data['ip'] = session()->get('ip') ?? request()->ip();
             $data['ip'] = session()->get('ip') ?? request()->ip();
             if (User::where('ip', '=', request()->ip())->exists()) session()->put('ip', request()->ip());
             if (User::where('ip', '=', request()->ip())->exists()) session()->put('ip', request()->ip());
+            $validationRules['ip']  = ['unique:users'];
+            return Validator::make($data, $validationRules, [
+                'ip.unique' => "You have already made an account! Please contact support if you think this is incorrect."
 
 
-            return Validator::make($data, [
-                'name'                 => ['required', 'string', 'max:30', 'min:4', 'alpha_num', 'unique:users'],
-                'email'                => ['required', 'string', 'email', 'max:64', 'unique:users'],
-                'password'             => ['required', 'string', 'min:8', 'confirmed'],
-                'g-recaptcha-response' => ['recaptcha'],
-                'ip'                   => ['unique:users'],
-            ], [
-                'ip.unique' => __("You have already made an account with us! Please contact support if you think this is incorrect.")
             ]);
             ]);
         }
         }
 
 
-        return Validator::make($data, [
-            'name'                 => ['required', 'string', 'max:30', 'min:4', 'alpha_num', 'unique:users'],
-            'email'                => ['required', 'string', 'email', 'max:64', 'unique:users'],
-            'password'             => ['required', 'string', 'min:8', 'confirmed'],
-            'g-recaptcha-response' => ['recaptcha'],
-        ]);
-
+        return Validator::make($data, $validationRules);
     }
     }
 
 
     /**
     /**
@@ -91,8 +89,8 @@ class RegisterController extends Controller
         $user = User::create([
         $user = User::create([
             'name'         => $data['name'],
             'name'         => $data['name'],
             'email'        => $data['email'],
             'email'        => $data['email'],
-            'credits'      => Configuration::getValueByKey('INITIAL_CREDITS', 150),
-            'server_limit' => Configuration::getValueByKey('INITIAL_SERVER_LIMIT', 1),
+            'credits'      => config('SETTINGS::USER:INITIAL_CREDITS', 150),
+            'server_limit' => config('SETTINGS::USER:INITIAL_SERVER_LIMIT', 1),
             'password'     => Hash::make($data['password']),
             'password'     => Hash::make($data['password']),
         ]);
         ]);
 
 

+ 7 - 7
app/Http/Controllers/Auth/SocialiteController.php

@@ -3,8 +3,8 @@
 namespace App\Http\Controllers\Auth;
 namespace App\Http\Controllers\Auth;
 
 
 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\Settings;
 use App\Models\User;
 use App\Models\User;
 use App\Models\Voucher;
 use App\Models\Voucher;
 use Illuminate\Support\Facades\Auth;
 use Illuminate\Support\Facades\Auth;
@@ -15,7 +15,7 @@ class SocialiteController extends Controller
 {
 {
     public function redirect()
     public function redirect()
     {
     {
-        $scopes = !empty(env('DISCORD_BOT_TOKEN')) && !empty(env('DISCORD_GUILD_ID')) ? ['guilds.join'] : [];
+        $scopes = !empty(Settings::getValueByKey("SETTINGS::DISCORD:BOT_TOKEN")) && !empty(Settings::getValueByKey("SETTINGS::DISCORD:GUILD_ID")) ? ['guilds.join'] : [];
 
 
         return Socialite::driver('discord')
         return Socialite::driver('discord')
             ->scopes($scopes)
             ->scopes($scopes)
@@ -31,17 +31,17 @@ class SocialiteController extends Controller
         /** @var User $user */
         /** @var User $user */
         $user = Auth::user();
         $user = Auth::user();
         $discord = Socialite::driver('discord')->user();
         $discord = Socialite::driver('discord')->user();
-        $botToken = env('DISCORD_BOT_TOKEN');
-        $guildId = env('DISCORD_GUILD_ID');
-        $roleId = env('DISCORD_ROLE_ID');
+        $botToken = Settings::getValueByKey("SETTINGS::DISCORD:BOT_TOKEN");
+        $guildId = Settings::getValueByKey("SETTINGS::DISCORD:GUILD_ID");
+        $roleId = Settings::getValueByKey("SETTINGS::DISCORD:ROLE_ID");
 
 
         //save / update discord_users
         //save / update discord_users
         if (is_null($user->discordUser)) {
         if (is_null($user->discordUser)) {
             //create discord user in db
             //create discord user in db
             DiscordUser::create(array_merge($discord->user, ['user_id' => Auth::user()->id]));
             DiscordUser::create(array_merge($discord->user, ['user_id' => Auth::user()->id]));
             //update user
             //update user
-            Auth::user()->increment('credits', Configuration::getValueByKey('CREDITS_REWARD_AFTER_VERIFY_DISCORD'));
-            Auth::user()->increment('server_limit', Configuration::getValueByKey('SERVER_LIMIT_REWARD_AFTER_VERIFY_DISCORD'));
+            Auth::user()->increment('credits', Settings::getValueByKey('SETTINGS::USER:CREDITS_REWARD_AFTER_VERIFY_DISCORD'));
+            Auth::user()->increment('server_limit', Settings::getValueByKey('SETTINGS::USER:SERVER_LIMIT_REWARD_AFTER_VERIFY_DISCORD'));
             Auth::user()->update(['discord_verified_at' => now()]);
             Auth::user()->update(['discord_verified_at' => now()]);
         } else {
         } else {
             $user->discordUser->update($discord->user);
             $user->discordUser->update($discord->user);

+ 0 - 3
app/Http/Controllers/HomeController.php

@@ -2,10 +2,7 @@
 
 
 namespace App\Http\Controllers;
 namespace App\Http\Controllers;
 
 
-use App\Models\Egg;
-use App\Models\Product;
 use App\Models\UsefulLink;
 use App\Models\UsefulLink;
-use App\Models\Configuration;
 use Illuminate\Http\Request;
 use Illuminate\Http\Request;
 use Illuminate\Support\Facades\Auth;
 use Illuminate\Support\Facades\Auth;
 
 

+ 11 - 14
app/Http/Controllers/ProfileController.php

@@ -2,14 +2,11 @@
 
 
 namespace App\Http\Controllers;
 namespace App\Http\Controllers;
 
 
+
 use App\Classes\Pterodactyl;
 use App\Classes\Pterodactyl;
-use App\Models\Configuration;
 use App\Models\User;
 use App\Models\User;
-use Illuminate\Contracts\View\Factory;
-use Illuminate\Contracts\View\View;
 use Illuminate\Http\RedirectResponse;
 use Illuminate\Http\RedirectResponse;
 use Illuminate\Http\Request;
 use Illuminate\Http\Request;
-use Illuminate\Http\Response;
 use Illuminate\Support\Facades\Auth;
 use Illuminate\Support\Facades\Auth;
 use Illuminate\Support\Facades\Hash;
 use Illuminate\Support\Facades\Hash;
 use Illuminate\Validation\ValidationException;
 use Illuminate\Validation\ValidationException;
@@ -21,9 +18,9 @@ class ProfileController extends Controller
     {
     {
         return view('profile.index')->with([
         return view('profile.index')->with([
             'user' => Auth::user(),
             'user' => Auth::user(),
-            'credits_reward_after_verify_discord' => Configuration::getValueByKey('CREDITS_REWARD_AFTER_VERIFY_DISCORD'),
-            'force_email_verification' => Configuration::getValueByKey('FORCE_EMAIL_VERIFICATION'),
-            'force_discord_verification' => Configuration::getValueByKey('FORCE_DISCORD_VERIFICATION'),
+            'credits_reward_after_verify_discord' => config('SETTINGS::USER:CREDITS_REWARD_AFTER_VERIFY_DISCORD'),
+            'force_email_verification' => config('SETTINGS::USER:FORCE_EMAIL_VERIFICATION'),
+            'force_discord_verification' => config('SETTINGS::USER:FORCE_DISCORD_VERIFICATION'),
         ]);
         ]);
     }
     }
 
 
@@ -39,15 +36,15 @@ class ProfileController extends Controller
         $user = User::findOrFail($id);
         $user = User::findOrFail($id);
 
 
         //update password if necessary
         //update password if necessary
-        if (!is_null($request->input('new_password'))){
+        if (!is_null($request->input('new_password'))) {
 
 
             //validate password request
             //validate password request
             $request->validate([
             $request->validate([
                 'current_password' => [
                 'current_password' => [
-                    'required' ,
+                    'required',
                     function ($attribute, $value, $fail) use ($user) {
                     function ($attribute, $value, $fail) use ($user) {
                         if (!Hash::check($value, $user->password)) {
                         if (!Hash::check($value, $user->password)) {
-                            $fail('The '.$attribute.' is invalid.');
+                            $fail('The ' . $attribute . ' is invalid.');
                         }
                         }
                     },
                     },
                 ],
                 ],
@@ -80,13 +77,13 @@ class ProfileController extends Controller
 
 
         //validate request
         //validate request
         $request->validate([
         $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'
             'avatar' => 'nullable'
         ]);
         ]);
 
 
         //update avatar
         //update avatar
-        if(!is_null($request->input('avatar'))){
+        if (!is_null($request->input('avatar'))) {
             $avatar = json_decode($request->input('avatar'));
             $avatar = json_decode($request->input('avatar'));
             if ($avatar->input->size > 3000000) abort(500);
             if ($avatar->input->size > 3000000) abort(500);
 
 
@@ -121,6 +118,6 @@ class ProfileController extends Controller
         ]);
         ]);
         $user->sendEmailVerificationNotification();
         $user->sendEmailVerificationNotification();
 
 
-        return redirect()->route('profile.index')->with('success' , __('Profile updated'));
+        return redirect()->route('profile.index')->with('success', __('Profile updated'));
     }
     }
 }
 }

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

@@ -3,13 +3,13 @@
 namespace App\Http\Controllers;
 namespace App\Http\Controllers;
 
 
 use App\Classes\Pterodactyl;
 use App\Classes\Pterodactyl;
-use App\Models\Configuration;
 use App\Models\Egg;
 use App\Models\Egg;
 use App\Models\Location;
 use App\Models\Location;
 use App\Models\Nest;
 use App\Models\Nest;
 use App\Models\Node;
 use App\Models\Node;
 use App\Models\Product;
 use App\Models\Product;
 use App\Models\Server;
 use App\Models\Server;
+use App\Models\Settings;
 use App\Notifications\ServerCreationError;
 use App\Notifications\ServerCreationError;
 use Exception;
 use Exception;
 use Illuminate\Database\Eloquent\Builder;
 use Illuminate\Database\Eloquent\Builder;
@@ -107,7 +107,7 @@ class ServerController extends Controller
             if (
             if (
                 Auth::user()->credits <
                 Auth::user()->credits <
                 ($product->minimum_credits == -1
                 ($product->minimum_credits == -1
-                    ? Configuration::getValueByKey('MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER', 50)
+                    ? config('SETTINGS::USER:MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER', 50)
                     : $product->minimum_credits)
                     : $product->minimum_credits)
             ) {
             ) {
                 return redirect()->route('servers.index')->with('error', "You do not have the required amount of " . CREDITS_DISPLAY_NAME . " to use this product!");
                 return redirect()->route('servers.index')->with('error', "You do not have the required amount of " . CREDITS_DISPLAY_NAME . " to use this product!");
@@ -115,12 +115,12 @@ class ServerController extends Controller
         }
         }
 
 
         //Required Verification for creating an server
         //Required Verification for creating an server
-        if (Configuration::getValueByKey('FORCE_EMAIL_VERIFICATION', 'false') === 'true' && !Auth::user()->hasVerifiedEmail()) {
+        if (config('SETTINGS::USER:FORCE_EMAIL_VERIFICATION', 'false') === 'true' && !Auth::user()->hasVerifiedEmail()) {
             return redirect()->route('profile.index')->with('error', __("You are required to verify your email address before you can create a server."));
             return redirect()->route('profile.index')->with('error', __("You are required to verify your email address before you can create a server."));
         }
         }
 
 
         //Required Verification for creating an server
         //Required Verification for creating an server
-        if (Configuration::getValueByKey('FORCE_DISCORD_VERIFICATION', 'false') === 'true' && !Auth::user()->discordUser) {
+        if (config('SETTINGS::USER:FORCE_DISCORD_VERIFICATION', 'false') === 'true' && !Auth::user()->discordUser) {
             return redirect()->route('profile.index')->with('error', __("You are required to link your discord account before you can create a server."));
             return redirect()->route('profile.index')->with('error', __("You are required to link your discord account before you can create a server."));
         }
         }
 
 
@@ -168,7 +168,7 @@ class ServerController extends Controller
             'identifier'     => $serverAttributes['identifier']
             'identifier'     => $serverAttributes['identifier']
         ]);
         ]);
 
 
-        if (Configuration::getValueByKey('SERVER_CREATE_CHARGE_FIRST_HOUR', 'true') == 'true') {
+        if (config('SETTINGS::SYSTEM:SERVER_CREATE_CHARGE_FIRST_HOUR', 'true') == 'true') {
             if ($request->user()->credits >= $server->product->getHourlyPrice()) {
             if ($request->user()->credits >= $server->product->getHourlyPrice()) {
                 $request->user()->decrement('credits', $server->product->getHourlyPrice());
                 $request->user()->decrement('credits', $server->product->getHourlyPrice());
             }
             }

+ 5 - 5
app/Http/Controllers/StoreController.php

@@ -2,8 +2,8 @@
 
 
 namespace App\Http\Controllers;
 namespace App\Http\Controllers;
 
 
-use App\Models\Configuration;
 use App\Models\CreditProduct;
 use App\Models\CreditProduct;
+use App\Models\Settings;
 use Illuminate\Support\Facades\Auth;
 use Illuminate\Support\Facades\Auth;
 
 
 class StoreController extends Controller
 class StoreController extends Controller
@@ -15,17 +15,17 @@ class StoreController extends Controller
 
 
         if (
         if (
             env('APP_ENV') == 'local' ||
             env('APP_ENV') == 'local' ||
-            env('PAYPAL_SECRET') && env('PAYPAL_CLIENT_ID') ||
-            env('STRIPE_SECRET') && env('STRIPE_ENDPOINT_SECRET') && env('STRIPE_METHODS')
+            Settings::getValueByKey("SETTINGS::PAYMENTS:PAYPAL:SECRET") && Settings::getValueByKey("SETTINGS::PAYMENTS:PAYPAL:CLIENT_ID") ||
+            Settings::getValueByKey("SETTINGS::PAYMENTS:STRIPE:SECRET") && Settings::getValueByKey("SETTINGS::PAYMENTS:STRIPE:ENDPOINT_SECRET") && Settings::getValueByKey("SETTINGS::PAYMENTS:STRIPE:METHODS")
         ) $isPaymentSetup = true;
         ) $isPaymentSetup = true;
 
 
         //Required Verification for creating an server
         //Required Verification for creating an server
-        if (Configuration::getValueByKey('FORCE_EMAIL_VERIFICATION', false) === 'true' && !Auth::user()->hasVerifiedEmail()) {
+        if (Settings::getValueByKey('SETTINGS::USER:FORCE_EMAIL_VERIFICATION', false) === 'true' && !Auth::user()->hasVerifiedEmail()) {
             return redirect()->route('profile.index')->with('error', __("You are required to verify your email address before you can purchase credits."));
             return redirect()->route('profile.index')->with('error', __("You are required to verify your email address before you can purchase credits."));
         }
         }
 
 
         //Required Verification for creating an server
         //Required Verification for creating an server
-        if (Configuration::getValueByKey('FORCE_DISCORD_VERIFICATION', false) === 'true' && !Auth::user()->discordUser) {
+        if (Settings::getValueByKey('SETTINGS::USER:FORCE_DISCORD_VERIFICATION', false) === 'true' && !Auth::user()->discordUser) {
             return redirect()->route('profile.index')->with('error', __("You are required to link your discord account before you can purchase Credits"));
             return redirect()->route('profile.index')->with('error', __("You are required to link your discord account before you can purchase Credits"));
         }
         }
 
 

+ 2 - 0
app/Http/Controllers/TranslationController.php

@@ -18,4 +18,6 @@ class TranslationController extends Controller
         Session::put('locale', $request->inputLocale);
         Session::put('locale', $request->inputLocale);
         return redirect()->back();
         return redirect()->back();
     }
     }
+
+
 }
 }

+ 3 - 2
app/Http/Middleware/GlobalNames.php

@@ -3,6 +3,7 @@
 namespace App\Http\Middleware;
 namespace App\Http\Middleware;
 
 
 use App\Models\Configuration;
 use App\Models\Configuration;
+use App\Models\Settings;
 use Closure;
 use Closure;
 use Illuminate\Http\Request;
 use Illuminate\Http\Request;
 
 
@@ -17,10 +18,10 @@ class GlobalNames
      */
      */
     public function handle(Request $request, Closure $next)
     public function handle(Request $request, Closure $next)
     {
     {
-        define('CREDITS_DISPLAY_NAME' , Configuration::getValueByKey('CREDITS_DISPLAY_NAME' , 'Credits'));
+        define('CREDITS_DISPLAY_NAME', config('SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME', 'Credits'));
 
 
         $unsupported_lang_array = explode(',', config("app.unsupported_locales"));
         $unsupported_lang_array = explode(',', config("app.unsupported_locales"));
-        $unsupported_lang_array = array_map( 'strtolower', $unsupported_lang_array );
+        $unsupported_lang_array = array_map('strtolower', $unsupported_lang_array);
         define('UNSUPPORTED_LANGS', $unsupported_lang_array);
         define('UNSUPPORTED_LANGS', $unsupported_lang_array);
 
 
         return $next($request);
         return $next($request);

+ 10 - 200
app/Http/Middleware/SetLocale.php

@@ -2,6 +2,7 @@
 
 
 namespace App\Http\Middleware;
 namespace App\Http\Middleware;
 
 
+use App\Models\Settings;
 use Closure;
 use Closure;
 use Illuminate\Http\Request;
 use Illuminate\Http\Request;
 use Illuminate\Support\Facades\App;
 use Illuminate\Support\Facades\App;
@@ -9,194 +10,6 @@ use Illuminate\Support\Facades\Session;
 
 
 class SetLocale
 class SetLocale
 {
 {
-    function getLocaleCodeForDisplayLanguage($name){
-        $languageCodes = array(
-            "aa" => "Afar",
-            "ab" => "Abkhazian",
-            "ae" => "Avestan",
-            "af" => "Afrikaans",
-            "ak" => "Akan",
-            "am" => "Amharic",
-            "an" => "Aragonese",
-            "ar" => "Arabic",
-            "as" => "Assamese",
-            "av" => "Avaric",
-            "ay" => "Aymara",
-            "az" => "Azerbaijani",
-            "ba" => "Bashkir",
-            "be" => "Belarusian",
-            "bg" => "Bulgarian",
-            "bh" => "Bihari",
-            "bi" => "Bislama",
-            "bm" => "Bambara",
-            "bn" => "Bengali",
-            "bo" => "Tibetan",
-            "br" => "Breton",
-            "bs" => "Bosnian",
-            "ca" => "Catalan",
-            "ce" => "Chechen",
-            "ch" => "Chamorro",
-            "co" => "Corsican",
-            "cr" => "Cree",
-            "cs" => "Czech",
-            "cu" => "Church Slavic",
-            "cv" => "Chuvash",
-            "cy" => "Welsh",
-            "da" => "Danish",
-            "de" => "German",
-            "dv" => "Divehi",
-            "dz" => "Dzongkha",
-            "ee" => "Ewe",
-            "el" => "Greek",
-            "en" => "English",
-            "eo" => "Esperanto",
-            "es" => "Spanish",
-            "et" => "Estonian",
-            "eu" => "Basque",
-            "fa" => "Persian",
-            "ff" => "Fulah",
-            "fi" => "Finnish",
-            "fj" => "Fijian",
-            "fo" => "Faroese",
-            "fr" => "French",
-            "fy" => "Western Frisian",
-            "ga" => "Irish",
-            "gd" => "Scottish Gaelic",
-            "gl" => "Galician",
-            "gn" => "Guarani",
-            "gu" => "Gujarati",
-            "gv" => "Manx",
-            "ha" => "Hausa",
-            "he" => "Hebrew",
-            "hi" => "Hindi",
-            "ho" => "Hiri Motu",
-            "hr" => "Croatian",
-            "ht" => "Haitian",
-            "hu" => "Hungarian",
-            "hy" => "Armenian",
-            "hz" => "Herero",
-            "ia" => "Interlingua (International Auxiliary Language Association)",
-            "id" => "Indonesian",
-            "ie" => "Interlingue",
-            "ig" => "Igbo",
-            "ii" => "Sichuan Yi",
-            "ik" => "Inupiaq",
-            "io" => "Ido",
-            "is" => "Icelandic",
-            "it" => "Italian",
-            "iu" => "Inuktitut",
-            "ja" => "Japanese",
-            "jv" => "Javanese",
-            "ka" => "Georgian",
-            "kg" => "Kongo",
-            "ki" => "Kikuyu",
-            "kj" => "Kwanyama",
-            "kk" => "Kazakh",
-            "kl" => "Kalaallisut",
-            "km" => "Khmer",
-            "kn" => "Kannada",
-            "ko" => "Korean",
-            "kr" => "Kanuri",
-            "ks" => "Kashmiri",
-            "ku" => "Kurdish",
-            "kv" => "Komi",
-            "kw" => "Cornish",
-            "ky" => "Kirghiz",
-            "la" => "Latin",
-            "lb" => "Luxembourgish",
-            "lg" => "Ganda",
-            "li" => "Limburgish",
-            "ln" => "Lingala",
-            "lo" => "Lao",
-            "lt" => "Lithuanian",
-            "lu" => "Luba-Katanga",
-            "lv" => "Latvian",
-            "mg" => "Malagasy",
-            "mh" => "Marshallese",
-            "mi" => "Maori",
-            "mk" => "Macedonian",
-            "ml" => "Malayalam",
-            "mn" => "Mongolian",
-            "mr" => "Marathi",
-            "ms" => "Malay",
-            "mt" => "Maltese",
-            "my" => "Burmese",
-            "na" => "Nauru",
-            "nb" => "Norwegian Bokmal",
-            "nd" => "North Ndebele",
-            "ne" => "Nepali",
-            "ng" => "Ndonga",
-            "nl" => "Dutch",
-            "nn" => "Norwegian Nynorsk",
-            "no" => "Norwegian",
-            "nr" => "South Ndebele",
-            "nv" => "Navajo",
-            "ny" => "Chichewa",
-            "oc" => "Occitan",
-            "oj" => "Ojibwa",
-            "om" => "Oromo",
-            "or" => "Oriya",
-            "os" => "Ossetian",
-            "pa" => "Panjabi",
-            "pi" => "Pali",
-            "pl" => "Polish",
-            "ps" => "Pashto",
-            "pt" => "Portuguese",
-            "qu" => "Quechua",
-            "rm" => "Raeto-Romance",
-            "rn" => "Kirundi",
-            "ro" => "Romanian",
-            "ru" => "Russian",
-            "rw" => "Kinyarwanda",
-            "sa" => "Sanskrit",
-            "sc" => "Sardinian",
-            "sd" => "Sindhi",
-            "se" => "Northern Sami",
-            "sg" => "Sango",
-            "si" => "Sinhala",
-            "sk" => "Slovak",
-            "sl" => "Slovenian",
-            "sm" => "Samoan",
-            "so" => "Somali",
-            "sq" => "Albanian",
-            "sr" => "Serbian",
-            "ss" => "Swati",
-            "st" => "Southern Sotho",
-            "su" => "Sundanese",
-            "sv" => "Swedish",
-            "sw" => "Swahili",
-            "ta" => "Tamil",
-            "te" => "Telugu",
-            "tg" => "Tajik",
-            "th" => "Thai",
-            "ti" => "Tigrinya",
-            "tk" => "Turkmen",
-            "tl" => "Tagalog",
-            "tn" => "Tswana",
-            "to" => "Tonga",
-            "tr" => "Turkish",
-            "ts" => "Tsonga",
-            "tt" => "Tatar",
-            "tw" => "Twi",
-            "ty" => "Tahitian",
-            "ug" => "Uighur",
-            "uk" => "Ukrainian",
-            "ur" => "Urdu",
-            "uz" => "Uzbek",
-            "ve" => "Venda",
-            "vi" => "Vietnamese",
-            "vo" => "Volapuk",
-            "wa" => "Walloon",
-            "wo" => "Wolof",
-            "xh" => "Xhosa",
-            "yi" => "Yiddish",
-            "yo" => "Yoruba",
-            "za" => "Zhuang",
-            "zh" => "Chinese",
-            "zu" => "Zulu"
-        );
-        return array_search($name, array_flip($languageCodes));
-    }
 
 
     /**
     /**
      *
      *
@@ -208,22 +21,19 @@ class SetLocale
      */
      */
     public function handle($request, Closure $next)
     public function handle($request, Closure $next)
     {
     {
-
-            if (Session::has('locale')) {
-                $locale = Session::get('locale', config('app.locale'));
+        if (Session::has('locale')) {
+            $locale = Session::get('locale', config("SETTINGS::LOCALE:DEFAULT"));
+        } else {
+            if (config("SETTINGS::LOCALE:DYNAMIC") !== "true") {
+                $locale = config("SETTINGS::LOCALE:DEFAULT");
             } else {
             } else {
-                if (!config('app.dynamic_locale')) {
-                    $locale = config('app.locale');
-                }else{
-                    $locale = substr($request->server('HTTP_ACCEPT_LANGUAGE'), 0, 2);
-
-                    if (!in_array($locale, config('app.available_locales'))
-                        || in_array(strtolower($this->getLocaleCodeForDisplayLanguage($locale)), UNSUPPORTED_LANGS)) {
-                        $locale = config('app.locale');
-                    }
+                $locale = substr($request->server('HTTP_ACCEPT_LANGUAGE'), 0, 2);
 
 
+                if (!in_array($locale, explode(',', config("SETTINGS::LOCALE:AVAILABLE")))) {
+                    $locale = config("SETTINGS::LOCALE:DEFAULT");
                 }
                 }
             }
             }
+        }
         App::setLocale($locale);
         App::setLocale($locale);
 
 
         return $next($request);
         return $next($request);

+ 2 - 3
app/Listeners/UnsuspendServers.php

@@ -3,11 +3,10 @@
 namespace App\Listeners;
 namespace App\Listeners;
 
 
 use App\Events\UserUpdateCreditsEvent;
 use App\Events\UserUpdateCreditsEvent;
-use App\Models\Configuration;
 use App\Models\Server;
 use App\Models\Server;
+use App\Models\Settings;
 use Exception;
 use Exception;
 use Illuminate\Contracts\Queue\ShouldQueue;
 use Illuminate\Contracts\Queue\ShouldQueue;
-use Illuminate\Queue\InteractsWithQueue;
 
 
 class UnsuspendServers implements ShouldQueue
 class UnsuspendServers implements ShouldQueue
 {
 {
@@ -20,7 +19,7 @@ class UnsuspendServers implements ShouldQueue
      */
      */
     public function handle(UserUpdateCreditsEvent $event)
     public function handle(UserUpdateCreditsEvent $event)
     {
     {
-       if ($event->user->credits > Configuration::getValueByKey('MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER' , 50)){
+       if ($event->user->credits > Settings::getValueByKey('SETTINGS::USER:MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER' , 50)){
            /** @var Server $server */
            /** @var Server $server */
            foreach ($event->user->servers as $server){
            foreach ($event->user->servers as $server){
                if ($server->isSuspended()) $server->unSuspend();
                if ($server->isSuspended()) $server->unSuspend();

+ 3 - 5
app/Listeners/Verified.php

@@ -2,9 +2,7 @@
 
 
 namespace App\Listeners;
 namespace App\Listeners;
 
 
-use App\Models\Configuration;
-use Illuminate\Contracts\Queue\ShouldQueue;
-use Illuminate\Queue\InteractsWithQueue;
+use App\Models\Settings;
 
 
 class Verified
 class Verified
 {
 {
@@ -26,7 +24,7 @@ class Verified
      */
      */
     public function handle($event)
     public function handle($event)
     {
     {
-        $event->user->increment('server_limit' , Configuration::getValueByKey('SERVER_LIMIT_REWARD_AFTER_VERIFY_EMAIL'));
-        $event->user->increment('credits' , Configuration::getValueByKey('CREDITS_REWARD_AFTER_VERIFY_EMAIL'));
+        $event->user->increment('server_limit' , Settings::getValueByKey('SETTINGS::USER:SERVER_LIMIT_REWARD_AFTER_VERIFY_EMAIL'));
+        $event->user->increment('credits' , Settings::getValueByKey('SETTINGS::USER:CREDITS_REWARD_AFTER_VERIFY_EMAIL'));
     }
     }
 }
 }

+ 1 - 1
app/Models/CreditProduct.php

@@ -59,7 +59,7 @@ class CreditProduct extends Model
     */
     */
     public function getTaxPercent()
     public function getTaxPercent()
     {
     {
-        $tax = Configuration::getValueByKey("SALES_TAX");
+        $tax = Settings::getValueByKey("SETTINGS::PAYMENTS:SALES_TAX");
         return $tax < 0 ? 0 : $tax;
         return $tax < 0 ? 0 : $tax;
     }
     }
 
 

+ 0 - 23
app/Models/InvoiceSettings.php

@@ -1,23 +0,0 @@
-<?php
-
-namespace App\Models;
-
-use Illuminate\Database\Eloquent\Factories\HasFactory;
-use Illuminate\Database\Eloquent\Model;
-
-class InvoiceSettings extends Model
-{
-    use HasFactory;
-
-    protected $table = 'invoice_settings';
-
-    protected $fillable = [
-        'company_name',
-        'company_adress',
-        'company_phone',
-        'company_mail',
-        'company_vat',
-        'company_web',
-        'invoice_prefix'
-    ];
-}

+ 8 - 6
app/Models/Configuration.php → app/Models/Settings.php

@@ -6,11 +6,13 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
 use Illuminate\Database\Eloquent\Model;
 use Illuminate\Database\Eloquent\Model;
 use Illuminate\Support\Facades\Cache;
 use Illuminate\Support\Facades\Cache;
 
 
-class Configuration extends Model
+class Settings extends Model
 {
 {
     use HasFactory;
     use HasFactory;
 
 
-    public const CACHE_TAG = 'configuration';
+    protected $table = 'settings';
+
+    public const CACHE_TAG = 'setting';
 
 
     public $primaryKey = 'key';
     public $primaryKey = 'key';
 
 
@@ -28,8 +30,8 @@ class Configuration extends Model
     {
     {
         parent::boot();
         parent::boot();
 
 
-        static::updated(function (Configuration $configuration) {
-            Cache::forget(self::CACHE_TAG .':'. $configuration->key);
+        static::updated(function (Settings $settings) {
+            Cache::forget(self::CACHE_TAG .':'. $settings->key);
         });
         });
     }
     }
 
 
@@ -41,8 +43,8 @@ class Configuration extends Model
     public static function getValueByKey(string $key, $default = null)
     public static function getValueByKey(string $key, $default = null)
     {
     {
         return Cache::rememberForever(self::CACHE_TAG .':'. $key, function () use ($default, $key) {
         return Cache::rememberForever(self::CACHE_TAG .':'. $key, function () use ($default, $key) {
-            $configuration = self::find($key);
-            return $configuration ? $configuration->value : $default;
+            $settings = self::find($key);
+            return $settings ? $settings->value : $default;
         });
         });
     }
     }
 }
 }

+ 0 - 1
app/Notifications/ServersSuspendedNotification.php

@@ -2,7 +2,6 @@
 
 
 namespace App\Notifications;
 namespace App\Notifications;
 
 
-use App\Models\Configuration;
 use Illuminate\Bus\Queueable;
 use Illuminate\Bus\Queueable;
 use Illuminate\Contracts\Queue\ShouldQueue;
 use Illuminate\Contracts\Queue\ShouldQueue;
 use Illuminate\Notifications\Messages\MailMessage;
 use Illuminate\Notifications\Messages\MailMessage;

+ 19 - 19
app/Notifications/WelcomeMessage.php

@@ -2,7 +2,7 @@
 
 
 namespace App\Notifications;
 namespace App\Notifications;
 
 
-use App\Models\Configuration;
+use App\Models\Settings;
 use App\Models\User;
 use App\Models\User;
 use Illuminate\Bus\Queueable;
 use Illuminate\Bus\Queueable;
 use Illuminate\Contracts\Queue\ShouldQueue;
 use Illuminate\Contracts\Queue\ShouldQueue;
@@ -38,25 +38,25 @@ class WelcomeMessage extends Notification implements ShouldQueue
         return ['database'];
         return ['database'];
     }
     }
     public function AdditionalLines()
     public function AdditionalLines()
-        {
-
-            $AdditionalLine = "";
-            if(Configuration::getValueByKey('CREDITS_REWARD_AFTER_VERIFY_EMAIL') != 0) {
-                $AdditionalLine .= "Verifying your e-mail address will grant you ".Configuration::getValueByKey('CREDITS_REWARD_AFTER_VERIFY_EMAIL')." additional " . Configuration::getValueByKey('CREDITS_DISPLAY_NAME') . ". <br />";
-            }
-            if(Configuration::getValueByKey('SERVER_LIMIT_REWARD_AFTER_VERIFY_EMAIL') != 0) {
-                $AdditionalLine .= "Verifying your e-mail will also increase your Server Limit by " . Configuration::getValueByKey('SERVER_LIMIT_REWARD_AFTER_VERIFY_EMAIL') . ". <br />";
-            }
-            $AdditionalLine .="<br />";
-            if(Configuration::getValueByKey('CREDITS_REWARD_AFTER_VERIFY_DISCORD') != 0) {
-                $AdditionalLine .=  "You can also verify your discord account to get another " . Configuration::getValueByKey('CREDITS_REWARD_AFTER_VERIFY_DISCORD') . " " . Configuration::getValueByKey('CREDITS_DISPLAY_NAME') . ". <br />";
-            }
-            if(Configuration::getValueByKey('SERVER_LIMIT_REWARD_AFTER_VERIFY_DISCORD') != 0) {
-                $AdditionalLine .=  "Verifying your Discord account will also increase your Server Limit by " . Configuration::getValueByKey('SERVER_LIMIT_REWARD_AFTER_VERIFY_DISCORD') . ". <br />";
-            }
+    {
 
 
-            return $AdditionalLine;
+        $AdditionalLine = "";
+        if (config('SETTINGS::USER:CREDITS_REWARD_AFTER_VERIFY_EMAIL') != 0) {
+            $AdditionalLine .= "Verifying your e-mail address will grant you " . config('SETTINGS::USER:CREDITS_REWARD_AFTER_VERIFY_EMAIL') . " additional " . config('SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME') . ". <br />";
+        }
+        if (config('SETTINGS::USER:SERVER_LIMIT_REWARD_AFTER_VERIFY_EMAIL') != 0) {
+            $AdditionalLine .= "Verifying your e-mail will also increase your Server Limit by " . config('SETTINGS::USER:SERVER_LIMIT_REWARD_AFTER_VERIFY_EMAIL') . ". <br />";
+        }
+        $AdditionalLine .= "<br />";
+        if (config('SETTINGS::USER:CREDITS_REWARD_AFTER_VERIFY_DISCORD') != 0) {
+            $AdditionalLine .=  "You can also verify your discord account to get another " . config('SETTINGS::USER:CREDITS_REWARD_AFTER_VERIFY_DISCORD') . " " . config('SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME') . ". <br />";
         }
         }
+        if (config('SETTINGS::USER:SERVER_LIMIT_REWARD_AFTER_VERIFY_DISCORD') != 0) {
+            $AdditionalLine .=  "Verifying your Discord account will also increase your Server Limit by " . config('SETTINGS::USER:SERVER_LIMIT_REWARD_AFTER_VERIFY_DISCORD') . ". <br />";
+        }
+
+        return $AdditionalLine;
+    }
     /**
     /**
      * Get the array representation of the notification.
      * Get the array representation of the notification.
      *
      *
@@ -72,7 +72,7 @@ class WelcomeMessage extends Notification implements ShouldQueue
                 <h5>Verification</h5>
                 <h5>Verification</h5>
                 <p>You can verify your e-mail address and link/verify your Discord account.</p>
                 <p>You can verify your e-mail address and link/verify your Discord account.</p>
                 <p>
                 <p>
-                  ".$this->AdditionalLines()."
+                  " . $this->AdditionalLines() . "
                 </p>
                 </p>
                 <h5>Information</h5>
                 <h5>Information</h5>
                 <p>This dashboard can be used to create and delete servers.<br /> These servers can be used and managed on our pterodactyl panel.<br /> If you have any questions, please join our Discord server and #create-a-ticket.</p>
                 <p>This dashboard can be used to create and delete servers.<br /> These servers can be used and managed on our pterodactyl panel.<br /> If you have any questions, please join our Discord server and #create-a-ticket.</p>

+ 57 - 4
app/Providers/AppServiceProvider.php

@@ -2,11 +2,13 @@
 
 
 namespace App\Providers;
 namespace App\Providers;
 
 
+use App\Models\Settings;
 use Illuminate\Pagination\Paginator;
 use Illuminate\Pagination\Paginator;
+use Illuminate\Support\Facades\Artisan;
 use Illuminate\Support\Facades\Schema;
 use Illuminate\Support\Facades\Schema;
 use Illuminate\Support\Facades\Validator;
 use Illuminate\Support\Facades\Validator;
 use Illuminate\Support\ServiceProvider;
 use Illuminate\Support\ServiceProvider;
-use Spatie\QueryBuilder\QueryBuilderRequest;
+
 
 
 class AppServiceProvider extends ServiceProvider
 class AppServiceProvider extends ServiceProvider
 {
 {
@@ -31,14 +33,11 @@ class AppServiceProvider extends ServiceProvider
         Schema::defaultStringLength(191);
         Schema::defaultStringLength(191);
 
 
         Validator::extend('multiple_date_format', function ($attribute, $value, $parameters, $validator) {
         Validator::extend('multiple_date_format', function ($attribute, $value, $parameters, $validator) {
-
             $ok = true;
             $ok = true;
-
             $result = [];
             $result = [];
 
 
             // iterate through all formats
             // iterate through all formats
             foreach ($parameters as $parameter) {
             foreach ($parameters as $parameter) {
-
                 //validate with laravels standard date format validation
                 //validate with laravels standard date format validation
                 $result[] = $validator->validateDateFormat($attribute, $value, [$parameter]);
                 $result[] = $validator->validateDateFormat($attribute, $value, [$parameter]);
             }
             }
@@ -51,5 +50,59 @@ class AppServiceProvider extends ServiceProvider
 
 
             return $ok;
             return $ok;
         });
         });
+
+
+        // TODO: Check if Installer Lockfile exists instead of "running in console"
+        $settings = Settings::all();
+        // Set all configs from database
+        foreach ($settings as $setting) {
+            config([$setting->key => $setting->value]);
+        }
+
+        // Set Mail Config
+        //only update config if mail settings have changed in DB
+        if (
+            config('mail.default') != config('SETTINGS:MAIL:MAILER') ||
+            config('mail.mailers.smtp.host') != config('SETTINGS:MAIL:HOST') ||
+            config('mail.mailers.smtp.port') != config('SETTINGS:MAIL:PORT') ||
+            config('mail.mailers.smtp.username') != config('SETTINGS:MAIL:USERNAME') ||
+            config('mail.mailers.smtp.password') != config('SETTINGS:MAIL:PASSWORD') ||
+            config('mail.mailers.smtp.encryption') != config('SETTINGS:MAIL:ENCRYPTION') ||
+            config('mail.from.address') != config('SETTINGS:MAIL:FROM_ADDRESS') ||
+            config('mail.from.name') != config('SETTINGS:MAIL:FROM_NAME')
+        ) {
+            config(['mail.default' => config('SETTINGS::MAIL:MAILER')]);
+            config(['mail.mailers.smtp' => [
+                'transport' => 'smtp',
+                'host' => config('SETTINGS::MAIL:HOST'),
+                'port' => config('SETTINGS::MAIL:PORT'),
+                'encryption' => config('SETTINGS::MAIL:ENCRYPTION'),
+                'username' => config('SETTINGS::MAIL:USERNAME'),
+                'password' => config('SETTINGS::MAIL:PASSWORD'),
+                'timeout' => null,
+                'auth_mode' => null,
+            ]]);
+            config(['mail.from' => ['address' => config('SETTINGS::MAIL:FROM_ADDRESS'), 'name' => config('SETTINGS::MAIL:FROM_NAME')]]);
+
+            Artisan::call('queue:restart');
+        }
+
+
+        // Set Recaptcha API Config
+        //only update config if recaptcha settings have changed in DB
+        if (
+            config('recaptcha.api_site_key') != config('SETTINGS::RECAPTCHA:SITE_KEY') ||
+            config('recaptcha.api_secret_key') != config('SETTINGS::RECAPTCHA:SECRET_KEY')
+        ) {
+            config(['recaptcha.api_site_key' => config('SETTINGS::RECAPTCHA:SITE_KEY')]);
+            config(['recaptcha.api_secret_key' => config('SETTINGS::RECAPTCHA:SECRET_KEY')]);
+
+            Artisan::call('config:clear');
+            Artisan::call('cache:clear');
+        }
+
+        // Set Discord-API Config
+        config(['services.discord.client_id' => config('SETTINGS::DISCORD:CLIENT_ID')]);
+        config(['services.discord.client_secret' => config('SETTINGS::DISCORD:CLIENT_SECRET')]);
     }
     }
 }
 }

+ 8 - 43
config/app.php

@@ -1,5 +1,7 @@
 <?php
 <?php
 
 
+use App\Models\Settings;
+
 return [
 return [
 
 
     'version' => '0.6.2',
     'version' => '0.6.2',
@@ -70,16 +72,6 @@ return [
 
 
     'timezone' => env('APP_TIMEZONE', 'UTC'),
     'timezone' => env('APP_TIMEZONE', 'UTC'),
 
 
-    /*
-    |--------------------------------------------------------------------------
-    | Dyamic Locales
-    |--------------------------------------------------------------------------
-    |
-    | Change the Locale depending on the Users Browserlanguage
-    | Can either be true or false
-    |
-    */
-    'dynamic_locale' => env('DYNAMIC_LOCALE', false),
 
 
     /*
     /*
     |--------------------------------------------------------------------------
     |--------------------------------------------------------------------------
@@ -92,47 +84,20 @@ return [
     |
     |
     */
     */
 
 
-    'locale' => env('LOCALE', 'en'),
-
-
-    /*
-    |--------------------------------------------------------------------------
-    | Available Locales
-    |--------------------------------------------------------------------------
-    |
-    | You should not change this
-    | If the dashboard is 100% translated in a certain language, it will be added here
-    |
-    */
-    'available_locales' => array('English'=>'en','German'=>'de','Italian'=>'it','Chinese'=>'zh', 'Czech'=>'cs', 'Spanish'=>'es', 'Polish'=>'pl'),
-
+    'locale' =>"en",
 
 
     /*
     /*
     |--------------------------------------------------------------------------
     |--------------------------------------------------------------------------
-    | Unsupported Locales
+    | Available Languages
     |--------------------------------------------------------------------------
     |--------------------------------------------------------------------------
     |
     |
-    | Locales the Owner of the Dashboard does not want to support
-    |
-    |
-    */
-
-    'unsupported_locales' => env("UNSUPPORTED_LOCALES", ""),
-
-
-    /*
-    |--------------------------------------------------------------------------
-    | Datatable Language Setting
-    |--------------------------------------------------------------------------
-    |
-    | This is the Language-Code used on the Datatables.
-    | You can grab the Language-Codes from this Website
-    | https://datatables.net/plug-ins/i18n/
+    | The application locale determines the default locale that will be used
+    | by the translation service provider. You are free to set this value
+    | to any of the locales which will be supported by the application.
     |
     |
     */
     */
 
 
-    'datatable_locale' => env('DATATABLE_LOCALE', 'en-gb'),
-
+    'available_locales' =>["en","cs","de","es","fr","hi","it","pl","zh"],
 
 
     /*
     /*
     |--------------------------------------------------------------------------
     |--------------------------------------------------------------------------

+ 16 - 25
config/mail.php

@@ -45,31 +45,22 @@ return [
             'auth_mode' => null,
             'auth_mode' => null,
         ],
         ],
 
 
-        'ses' => [
-            'transport' => 'ses',
-        ],
-
-        'mailgun' => [
-            'transport' => 'mailgun',
-        ],
-
-        'postmark' => [
-            'transport' => 'postmark',
-        ],
-
-        'sendmail' => [
-            'transport' => 'sendmail',
-            'path' => '/usr/sbin/sendmail -bs',
-        ],
-
-        'log' => [
-            'transport' => 'log',
-            'channel' => env('MAIL_LOG_CHANNEL'),
-        ],
-
-        'array' => [
-            'transport' => 'array',
-        ],
+        // 'ses' => [
+        // 'transport' => 'ses',
+        // ],
+        //
+        // 'mailgun' => [
+        // 'transport' => 'mailgun',
+        // ],
+        //
+        // 'postmark' => [
+        // 'transport' => 'postmark',
+        // ],
+        //
+        // 'sendmail' => [
+        // 'transport' => 'sendmail',
+        // 'path' => '/usr/sbin/sendmail -bs',
+        // ],
     ],
     ],
 
 
     /*
     /*

+ 0 - 34
database/migrations/2021_05_08_164658_create_configurations_table.php

@@ -1,34 +0,0 @@
-<?php
-
-use Illuminate\Database\Migrations\Migration;
-use Illuminate\Database\Schema\Blueprint;
-use Illuminate\Support\Facades\Schema;
-
-class CreateConfigurationsTable extends Migration
-{
-    /**
-     * Run the migrations.
-     *
-     * @return void
-     */
-    public function up()
-    {
-        Schema::create('configurations', function (Blueprint $table) {
-            $table->string('key')->primary();
-            $table->string('value');
-            $table->string('type')->default('string');
-            $table->text('description')->nullable();
-            $table->timestamps();
-        });
-    }
-
-    /**
-     * Reverse the migrations.
-     *
-     * @return void
-     */
-    public function down()
-    {
-        Schema::dropIfExists('configurations');
-    }
-}

+ 0 - 48
database/migrations/2021_12_1_174440_invoice-settings.php

@@ -1,48 +0,0 @@
-<?php
-
-use Illuminate\Database\Migrations\Migration;
-use Illuminate\Database\Schema\Blueprint;
-use Illuminate\Support\Facades\DB;
-use Illuminate\Support\Facades\Schema;
-
-class InvoiceSettings extends Migration
-{
-    /**
-     * Run the migrations.
-     *
-     * @return void
-     */
-    public function up()
-    {
-        Schema::create('invoice_settings', function (Blueprint $table) {
-            $table->id();
-            $table->string('company_name')->nullable();
-            $table->string('company_adress')->nullable();
-            $table->string('company_phone')->nullable();
-            $table->string('company_vat')->nullable();
-            $table->string('company_mail')->nullable();
-            $table->string('company_web')->nullable()->default(env("APP_URL",""));
-            $table->string('invoice_prefix')->nullable();
-            $table->timestamps();
-        });
-
-        DB::table('invoice_settings')->insert(
-            array(
-                'company_name' => env("APP_NAME","MyCompany"),
-                'company_web' => env("APP_URL",""),
-                'invoice_prefix' => "INV"
-
-            )
-        );
-    }
-
-    /**
-     * Reverse the migrations.
-     *
-     * @return void
-     */
-    public function down()
-    {
-        Schema::dropIfExists('invoice_settings');
-    }
-}

+ 61 - 0
database/migrations/2022_01_05_144858_rename_configurations_table.php

@@ -0,0 +1,61 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Support\Facades\Schema;
+use Illuminate\Support\Facades\DB;
+
+
+class RenameConfigurationsTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::rename('configurations', 'settings');
+
+        DB::table('settings')->where('key', 'INITIAL_CREDITS')->update(['key' => 'SETTINGS::USER:INITIAL_CREDITS']);
+        DB::table('settings')->where('key', 'INITIAL_SERVER_LIMIT')->update(['key' => 'SETTINGS::USER:INITIAL_SERVER_LIMIT']);
+        DB::table('settings')->where('key', 'CREDITS_REWARD_AFTER_VERIFY_EMAIL')->update(['key' => 'SETTINGS::USER:CREDITS_REWARD_AFTER_VERIFY_EMAIL']);
+        DB::table('settings')->where('key', 'SERVER_LIMIT_REWARD_AFTER_VERIFY_EMAIL')->update(['key' => 'SETTINGS::USER:SERVER_LIMIT_REWARD_AFTER_VERIFY_EMAIL']);
+        DB::table('settings')->where('key', 'CREDITS_REWARD_AFTER_VERIFY_DISCORD')->update(['key' => 'SETTINGS::USER:CREDITS_REWARD_AFTER_VERIFY_DISCORD']);
+        DB::table('settings')->where('key', 'SERVER_LIMIT_REWARD_AFTER_VERIFY_DISCORD')->update(['key' => 'SETTINGS::USER:SERVER_LIMIT_REWARD_AFTER_VERIFY_DISCORD']);
+        DB::table('settings')->where('key', 'MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER')->update(['key' => 'SETTINGS::USER:MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER']);
+        DB::table('settings')->where('key', 'SERVER_LIMIT_AFTER_IRL_PURCHASE')->update(['key' => 'SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE']);
+        DB::table('settings')->where('key', 'FORCE_EMAIL_VERIFICATION')->update(['key' => 'SETTINGS::USER:FORCE_EMAIL_VERIFICATION']);
+        DB::table('settings')->where('key', 'FORCE_DISCORD_VERIFICATION')->update(['key' => 'SETTINGS::USER:FORCE_DISCORD_VERIFICATION']);
+        DB::table('settings')->where('key', 'REGISTER_IP_CHECK')->update(['key' => 'SETTINGS::SYSTEM:REGISTER_IP_CHECK']);
+        DB::table('settings')->where('key', 'CREDITS_DISPLAY_NAME')->update(['key' => 'SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME']);
+        DB::table('settings')->where('key', 'ALLOCATION_LIMIT')->update(['key' => 'SETTINGS::SERVER:ALLOCATION_LIMIT']);
+        DB::table('settings')->where('key', 'SERVER_CREATE_CHARGE_FIRST_HOUR')->update(['key' => 'SETTINGS::SYSTEM:SERVER_CREATE_CHARGE_FIRST_HOUR']);
+        DB::table('settings')->where('key', 'SALES_TAX')->update(['key' => 'SETTINGS::PAYMENTS:SALES_TAX']);
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::rename('settings', 'configurations');
+
+        DB::table('configurations')->where('key', 'SETTINGS::USER:INITIAL_CREDITS')->update(['key' => 'INITIAL_CREDITS']);
+        DB::table('configurations')->where('key', 'SETTINGS::USER:INITIAL_SERVER_LIMIT')->update(['key' => 'INITIAL_SERVER_LIMIT']);
+        DB::table('configurations')->where('key', 'SETTINGS::USER:CREDITS_REWARD_AFTER_VERIFY_EMAIL')->update(['key' => 'CREDITS_REWARD_AFTER_VERIFY_EMAIL']);
+        DB::table('configurations')->where('key', 'SETTINGS::USER:SERVER_LIMIT_REWARD_AFTER_VERIFY_EMAIL')->update(['key' => 'SERVER_LIMIT_REWARD_AFTER_VERIFY_EMAIL']);
+        DB::table('configurations')->where('key', 'SETTINGS::USER:CREDITS_REWARD_AFTER_VERIFY_DISCORD')->update(['key' => 'CREDITS_REWARD_AFTER_VERIFY_DISCORD']);
+        DB::table('configurations')->where('key', 'SETTINGS::USER:SERVER_LIMIT_REWARD_AFTER_VERIFY_DISCORD')->update(['key' => 'SERVER_LIMIT_REWARD_AFTER_VERIFY_DISCORD']);
+        DB::table('configurations')->where('key', 'SETTINGS::USER:MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER')->update(['key' => 'MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER']);
+        DB::table('configurations')->where('key', 'SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE')->update(['key' => 'SERVER_LIMIT_AFTER_IRL_PURCHASE']);
+        DB::table('configurations')->where('key', 'SETTINGS::USER:FORCE_EMAIL_VERIFICATION')->update(['key' => 'FORCE_EMAIL_VERIFICATION']);
+        DB::table('configurations')->where('key', 'SETTINGS::USER:FORCE_DISCORD_VERIFICATION')->update(['key' => 'FORCE_DISCORD_VERIFICATION']);
+        DB::table('configurations')->where('key', 'SETTINGS::SYSTEM:REGISTER_IP_CHECK')->update(['key' => 'REGISTER_IP_CHECK']);
+        DB::table('configurations')->where('key', 'SETTINGS::SYSTEM:SERVER_CREATE_CHARGE_FIRST_HOUR')->update(['key' => 'SERVER_CREATE_CHARGE_FIRST_HOUR']);
+        DB::table('configurations')->where('key', 'SETTINGS::SERVER:ALLOCATION_LIMIT')->update(['key' => 'ALLOCATION_LIMIT']);
+        DB::table('configurations')->where('key', 'SETTINGS::SERVER:CREDITS_DISPLAY_NAME')->update(['key' => 'SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME']);
+        DB::table('configurations')->where('key', 'SETTINGS::PAYMENTS:SALES_TAX')->update(['key' => 'SALES_TAX']);
+    }
+}

+ 34 - 0
database/migrations/2022_01_14_234418_update_settings_table_allow_nullable.php

@@ -0,0 +1,34 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class UpdateSettingsTableAllowNullable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        //allow value column in settings table to be nullable
+        Schema::table('settings', function (Blueprint $table) {
+            $table->string('value')->nullable()->change();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        //disallow value column in settings table to be nullable
+        Schema::table('settings', function (Blueprint $table) {
+            $table->string('value')->nullable(false)->change();
+        });
+    }
+}

+ 2 - 3
database/seeders/DatabaseSeeder.php

@@ -2,8 +2,7 @@
 
 
 namespace Database\Seeders;
 namespace Database\Seeders;
 
 
-use Database\Seeders\Seeds\ConfigurationSeeder;
-use Database\Seeders\Seeds\InvoiceSettingsSeeder;
+use Database\Seeders\Seeds\SettingsSeeder;
 use Illuminate\Database\Seeder;
 use Illuminate\Database\Seeder;
 
 
 class DatabaseSeeder extends Seeder
 class DatabaseSeeder extends Seeder
@@ -16,7 +15,7 @@ class DatabaseSeeder extends Seeder
     public function run()
     public function run()
     {
     {
         $this->call([
         $this->call([
-            ConfigurationSeeder::class,
+            SettingsSeeder::class,
         ]);
         ]);
 
 
     }
     }

+ 0 - 149
database/seeders/Seeds/ConfigurationSeeder.php

@@ -1,149 +0,0 @@
-<?php
-
-namespace Database\Seeders\Seeds;
-
-use App\Models\Configuration;
-use Illuminate\Database\Seeder;
-
-class ConfigurationSeeder extends Seeder
-{
-    /**
-     * Run the database seeds.
-     *
-     * @return void
-     */
-    public function run()
-    {
-        //initials
-        Configuration::firstOrCreate([
-            'key' => 'INITIAL_CREDITS',
-        ], [
-            'value'       => '250',
-            'type'        => 'integer',
-            'description' => 'The initial amount of credits the user starts with.'
-        ]);
-
-        Configuration::firstOrCreate([
-            'key' => 'INITIAL_SERVER_LIMIT',
-        ], [
-            'value'       => '1',
-            'type'        => 'integer',
-            'description' => 'The initial server limit the user starts with.'
-        ]);
-
-        //verify email event
-        Configuration::firstOrCreate([
-            'key' => 'CREDITS_REWARD_AFTER_VERIFY_EMAIL',
-        ], [
-            'value'       => '250',
-            'type'        => 'integer',
-            'description' => 'Increase in credits after the user has verified their email account.'
-        ]);
-
-        Configuration::firstOrCreate([
-            'key' => 'SERVER_LIMIT_REWARD_AFTER_VERIFY_EMAIL',
-        ], [
-            'value'       => '2',
-            'type'        => 'integer',
-            'description' => 'Increase in server limit after the user has verified their email account.'
-        ]);
-
-        //verify discord event
-        Configuration::firstOrCreate([
-            'key' => 'CREDITS_REWARD_AFTER_VERIFY_DISCORD',
-        ], [
-            'value'       => '375',
-            'type'        => 'integer',
-            'description' => 'Increase in credits after the user has verified their discord account.'
-        ]);
-
-        Configuration::firstOrCreate([
-            'key' => 'SERVER_LIMIT_REWARD_AFTER_VERIFY_DISCORD',
-        ], [
-            'value'       => '2',
-            'type'        => 'integer',
-            'description' => 'Increase in server limit after the user has verified their discord account.'
-        ]);
-
-        //other
-        Configuration::firstOrCreate([
-            'key' => 'MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER',
-        ], [
-            'value'       => '50',
-            'type'        => 'integer',
-            'description' => 'The minimum amount of credits the user would need to make a server.'
-        ]);
-
-        //purchasing
-        Configuration::firstOrCreate([
-            'key' => 'SERVER_LIMIT_AFTER_IRL_PURCHASE',
-        ], [
-            'value'       => '10',
-            'type'        => 'integer',
-            'description' => 'updates the users server limit to this amount (unless the user already has a higher server limit) after making a purchase with real money, set to 0 to ignore this.',
-        ]);
-
-
-        //force email and discord verification
-        Configuration::firstOrCreate([
-            'key' => 'FORCE_EMAIL_VERIFICATION',
-        ], [
-            'value'       => 'false',
-            'type'        => 'boolean',
-            'description' => 'Force an user to verify the email adress before creating a server / buying credits.'
-        ]);
-
-        Configuration::firstOrCreate([
-            'key' => 'FORCE_DISCORD_VERIFICATION',
-        ], [
-            'value'       => 'false',
-            'type'        => 'boolean',
-            'description' => 'Force an user to link an Discord Account before creating a server / buying credits.'
-        ]);
-
-        //disable ip check on register
-        Configuration::firstOrCreate([
-            'key' => 'REGISTER_IP_CHECK',
-        ], [
-            'value'       => 'true',
-            'type'        => 'boolean',
-            'description' => 'Prevent users from making multiple accounts using the same IP address'
-        ]);
-
-        //per_page on allocations request
-        Configuration::firstOrCreate([
-            'key' => 'ALLOCATION_LIMIT',
-        ], [
-            'value'       => '200',
-            'type'        => 'integer',
-            'description' => 'The maximum amount of allocations to pull per node for automatic deployment, if more allocations are being used than this limit is set to, no new servers can be created!'
-        ]);
-
-        //credits display name
-        Configuration::firstOrCreate([
-            'key' => 'CREDITS_DISPLAY_NAME',
-        ], [
-            'value'       => 'Credits',
-            'type'        => 'string',
-            'description' => 'Set the display name of your currency :)'
-        ]);
-
-        //credits display name
-        Configuration::firstOrCreate([
-            'key' => 'SERVER_CREATE_CHARGE_FIRST_HOUR',
-        ], [
-            'value'       => 'true',
-            'type'        => 'boolean',
-            'description' => 'Charges the first hour worth of credits upon creating a server.'
-        ]);
-        //sales tax
-        Configuration::firstOrCreate([
-            'key'   => 'SALES_TAX',
-        ], [
-            'value' => '0',
-            'type'  => 'integer',
-            'description'  => 'The %-value of tax that will be added to the product price on checkout'
-        ]);
-
-    }
-}

+ 468 - 0
database/seeders/Seeds/SettingsSeeder.php

@@ -0,0 +1,468 @@
+<?php
+
+namespace Database\Seeders\Seeds;
+
+use App\Models\Settings;
+use Illuminate\Database\Seeder;
+
+class SettingsSeeder extends Seeder
+{
+    /**
+     * Run the database seeds.
+     *
+     * @return void
+     */
+    public function run()
+    {
+        //initials
+        Settings::firstOrCreate([
+            'key' => 'SETTINGS::USER:INITIAL_CREDITS',
+        ], [
+            'value'       => '250',
+            'type'        => 'integer',
+            'description' => 'The initial amount of credits the user starts with.'
+        ]);
+
+        Settings::firstOrCreate([
+            'key' => 'SETTINGS::USER:NITIAL_SERVER_LIMIT',
+        ], [
+            'value'       => '1',
+            'type'        => 'integer',
+            'description' => 'The initial server limit the user starts with.'
+        ]);
+
+        //verify email event
+        Settings::firstOrCreate([
+            'key' => 'SETTINGS::USER:CREDITS_REWARD_AFTER_VERIFY_EMAIL',
+        ], [
+            'value'       => '250',
+            'type'        => 'integer',
+            'description' => 'Increase in credits after the user has verified their email account.'
+        ]);
+
+        Settings::firstOrCreate([
+            'key' => 'SETTINGS::USER:SERVER_LIMIT_REWARD_AFTER_VERIFY_EMAIL',
+        ], [
+            'value'       => '2',
+            'type'        => 'integer',
+            'description' => 'Increase in server limit after the user has verified their email account.'
+        ]);
+
+        //verify discord event
+        Settings::firstOrCreate([
+            'key' => 'SETTINGS::USER:CREDITS_REWARD_AFTER_VERIFY_DISCORD',
+        ], [
+            'value'       => '375',
+            'type'        => 'integer',
+            'description' => 'Increase in credits after the user has verified their discord account.'
+        ]);
+
+        Settings::firstOrCreate([
+            'key' => 'SETTINGS::USER:SERVER_LIMIT_REWARD_AFTER_VERIFY_DISCORD',
+        ], [
+            'value'       => '2',
+            'type'        => 'integer',
+            'description' => 'Increase in server limit after the user has verified their discord account.'
+        ]);
+
+        //other
+        Settings::firstOrCreate([
+            'key' => 'SETTINGS::USER:MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER',
+        ], [
+            'value'       => '50',
+            'type'        => 'integer',
+            'description' => 'The minimum amount of credits the user would need to make a server.'
+        ]);
+
+        //purchasing
+        Settings::firstOrCreate([
+            'key' => 'SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE',
+        ], [
+            'value'       => '10',
+            'type'        => 'integer',
+            'description' => 'updates the users server limit to this amount (unless the user already has a higher server limit) after making a purchase with real money, set to 0 to ignore this.',
+        ]);
+
+
+        //force email and discord verification
+        Settings::firstOrCreate([
+            'key' => 'SETTINGS::USER:FORCE_EMAIL_VERIFICATION',
+        ], [
+            'value'       => 'false',
+            'type'        => 'boolean',
+            'description' => 'Force an user to verify the email adress before creating a server / buying credits.'
+        ]);
+
+        Settings::firstOrCreate([
+            'key' => 'SETTINGS::USER:FORCE_DISCORD_VERIFICATION',
+        ], [
+            'value'       => 'false',
+            'type'        => 'boolean',
+            'description' => 'Force an user to link an Discord Account before creating a server / buying credits.'
+        ]);
+
+        //disable ip check on register
+        Settings::firstOrCreate([
+            'key' => 'SETTINGS::SYSTEM:REGISTER_IP_CHECK',
+        ], [
+            'value'       => 'true',
+            'type'        => 'boolean',
+            'description' => 'Prevent users from making multiple accounts using the same IP address'
+        ]);
+
+        //per_page on allocations request
+        Settings::firstOrCreate([
+            'key' => 'SETTINGS::SERVER:ALLOCATION_LIMIT',
+        ], [
+            'value'       => '200',
+            'type'        => 'integer',
+            'description' => 'The maximum amount of allocations to pull per node for automatic deployment, if more allocations are being used than this limit is set to, no new servers can be created!'
+        ]);
+
+        //credits display name
+        Settings::firstOrCreate([
+            'key' => 'SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME',
+        ], [
+            'value'       => 'Credits',
+            'type'        => 'string',
+            'description' => 'Set the display name of your currency :)'
+        ]);
+
+        //credits display name
+        Settings::firstOrCreate([
+            'key' => 'SETTINGS::SYSTEM:SERVER_CREATE_CHARGE_FIRST_HOUR',
+        ], [
+            'value'       => 'true',
+            'type'        => 'boolean',
+            'description' => 'Charges the first hour worth of credits upon creating a server.'
+        ]);
+        //sales tax
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::PAYMENTS:SALES_TAX',
+        ], [
+            'value' => '0',
+            'type'  => 'integer',
+            'description'  => 'The %-value of tax that will be added to the product price on checkout'
+        ]);
+        //Invoices enabled
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::INVOICE:ENABLED',
+        ], [
+            'value' => 'false',
+            'type'  => 'boolean',
+        ]);
+        //Invoice company name
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::INVOICE:COMPANY_NAME',
+        ], [
+            'value' => '',
+            'type'  => 'string',
+            'description'  => 'The name of the Company on the Invoices'
+        ]);
+        //Invoice company address
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::INVOICE:COMPANY_ADDRESS',
+        ], [
+            'value' => '',
+            'type'  => 'string',
+            'description'  => 'The address of the Company on the Invoices'
+        ]);
+        //Invoice company phone
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::INVOICE:COMPANY_PHONE',
+        ], [
+            'value' => '',
+            'type'  => 'string',
+            'description'  => 'The phone number of the Company on the Invoices'
+        ]);
+
+        //Invoice company mail
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::INVOICE:COMPANY_MAIL',
+        ], [
+            'value' => '',
+            'type'  => 'string',
+            'description'  => 'The email address of the Company on the Invoices'
+        ]);
+
+        //Invoice VAT
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::INVOICE:COMPANY_VAT',
+        ], [
+            'value' => '',
+            'type'  => 'string',
+            'description'  => 'The VAT-Number of the Company on the Invoices'
+        ]);
+
+        //Invoice Website
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::INVOICE:COMPANY_WEBSITE',
+        ], [
+            'value' => '',
+            'type'  => 'string',
+            'description'  => 'The Website of the Company on the Invoices'
+        ]);
+
+        //Invoice Website
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::INVOICE:PREFIX',
+        ], [
+            'value' => 'INV',
+            'type'  => 'string',
+            'description'  => 'The invoice prefix'
+        ]);
+
+        //Locale
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::LOCALE:DEFAULT',
+        ], [
+            'value' => 'en',
+            'type'  => 'string',
+            'description'  => 'The default Language the dashboard will be shown in'
+        ]);
+        //Dynamic locale
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::LOCALE:DYNAMIC',
+        ], [
+            'value' => 'false',
+            'type'  => 'boolean',
+            'description'  => 'If this is true, the Language will change to the Clients browserlanguage or default.'
+        ]);
+        //User can change Locale
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::LOCALE:CLIENTS_CAN_CHANGE',
+        ], [
+            'value' => 'false',
+            'type'  => 'boolean',
+            'description'  => 'If this is true, the clients will be able to change their Locale.'
+        ]);
+        //Locale
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::LOCALE:AVAILABLE',
+        ], [
+            'value' => '',
+            'type'  => 'string',
+            'description'  => 'The available languages'
+        ]);
+        //Locale
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::LOCALE:DATATABLES',
+        ], [
+            'value' => 'en-gb',
+            'type'  => 'string',
+            'description'  => 'The Language of the Datatables. Grab the Language-Codes from here https://datatables.net/plug-ins/i18n/'
+        ]);
+
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::PAYMENTS:PAYPAL:SECRET',
+        ], [
+            'value' => '',
+            'type'  => 'string',
+            'description'  => 'Your PayPal Secret-Key ( https://developer.paypal.com/docs/integration/direct/rest/)'
+        ]);
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::PAYMENTS:PAYPAL:CLIENT_ID',
+        ], [
+            'value' => '',
+            'type'  => 'string',
+            'description'  => 'Your PayPal Client_ID'
+        ]);
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::PAYMENTS:PAYPAL:SANDBOX_SECRET',
+        ], [
+            'value' => '',
+            'type'  => 'string',
+            'description'  => 'Your PayPal SANDBOX Secret-Key used for testing '
+        ]);
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::PAYMENTS:PAYPAL:SANDBOX_CLIENT_ID',
+        ], [
+            'value' => '',
+            'type'  => 'string',
+            'description'  => 'Your PayPal SANDBOX Client-ID used for testing '
+        ]);
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::PAYMENTS:STRIPE:SECRET',
+        ], [
+            'value' => '',
+            'type'  => 'string',
+            'description'  => 'Your Stripe  Secret-Key  ( https://dashboard.stripe.com/account/apikeys )'
+        ]);
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::PAYMENTS:STRIPE:ENDPOINT_SECRET',
+        ], [
+            'value' => '',
+            'type'  => 'string',
+            'description'  => 'Your Stripe endpoint secret-key'
+        ]);
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::PAYMENTS:STRIPE:TEST_SECRET',
+        ], [
+            'value' => '',
+            'type'  => 'string',
+            'description'  => 'Your Stripe test secret-key'
+        ]);
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::PAYMENTS:STRIPE:ENDPOINT_TEST_SECRET',
+        ], [
+            'value' => '',
+            'type'  => 'string',
+            'description'  => 'Your Stripe endpoint test secret-key'
+        ]);
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::PAYMENTS:STRIPE:METHODS',
+        ], [
+            'value' => '',
+            'type'  => 'string',
+            'description'  => 'Comma seperated list of payment methods that are enabled (https://stripe.com/docs/payments/payment-methods/integration-options)'
+        ]);
+
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::DISCORD:CLIENT_ID',
+        ], [
+            'value' => '',
+            'type'  => 'string',
+            'description'  => 'Discord API Credentials - https://discordapp.com/developers/applications/'
+        ]);
+
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::DISCORD:CLIENT_SECRET',
+        ], [
+            'value' => '',
+            'type'  => 'string',
+            'description'  => 'Discord API Credentials - https://discordapp.com/developers/applications/'
+        ]);
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::DISCORD:BOT_TOKEN',
+        ], [
+            'value' => '',
+            'type'  => 'string',
+            'description'  => 'Discord API Credentials - https://discordapp.com/developers/applications/'
+        ]);
+
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::DISCORD:GUILD_ID',
+        ], [
+            'value' => '',
+            'type'  => 'string',
+            'description'  => 'Discord API Credentials - https://discordapp.com/developers/applications/'
+        ]);
+
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::DISCORD:ROLE_ID',
+        ], [
+            'value' => '',
+            'type'  => 'string',
+            'description'  => 'Discord role that will be assigned to users when they register'
+        ]);
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::DISCORD:INVITE_URL',
+        ], [
+            'value' => '',
+            'type'  => 'string',
+            'description'  => 'The invite URL to your Discord Server'
+        ]);
+
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::SYSTEM:PTERODACTYL:TOKEN',
+        ], [
+            'value' => '',
+            'type'  => 'string',
+            'description'  => 'Admin API Token from Pterodactyl Panel - necessary for the Panel to work. The Key needs all read&write permissions!'
+        ]);
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::SYSTEM:PTERODACTYL:URL',
+        ], [
+            'value' => '',
+            'type'  => 'string',
+            'description'  => 'The URL to your Pterodactyl Panel. Must not end with a / '
+        ]);
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::MISC:PHPMYADMIN:URL',
+        ], [
+            'value' => '',
+            'type'  => 'string',
+            'description'  => 'The URL to your PHPMYADMIN Panel. Must not end with a /, remove to remove database button'
+        ]);
+
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::RECAPTCHA:SITE_KEY',
+        ], [
+            'value' => '6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI',
+            'type'  => 'string',
+            'description'  => 'Google Recaptcha API Credentials - https://www.google.com/recaptcha/admin - reCaptcha V2 (not v3)'
+        ]);
+
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::RECAPTCHA:SECRET_KEY',
+        ], [
+            'value' => '6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe',
+            'type'  => 'string',
+            'description'  => 'Google Recaptcha API Credentials - https://www.google.com/recaptcha/admin - reCaptcha V2 (not v3)'
+        ]);
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::RECAPTCHA:ENABLED',
+        ], [
+            'value' => 'true',
+            'type'  => 'boolean',
+            'description'  => 'Enables or disables the ReCaptcha feature on the registration/login page'
+
+        ]);
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::MAIL:MAILER',
+        ], [
+            'value' => 'smtp',
+            'type'  => 'string',
+            'description'  => 'Selected Mailer (smtp, mailgun, sendgrid, mailtrap)'
+        ]);
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::MAIL:HOST',
+        ], [
+            'value' => 'localhost',
+            'type'  => 'string',
+            'description'  => 'Mailer Host Adress'
+        ]);
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::MAIL:PORT',
+        ], [
+            'value' => '1025',
+            'type'  => 'string',
+            'description'  => 'Mailer Server Port'
+        ]);
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::MAIL:USERNAME',
+        ], [
+            'value' => '',
+            'type'  => 'string',
+            'description'  => 'Mailer Username'
+        ]);
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::MAIL:PASSWORD',
+        ], [
+            'value' => '',
+            'type'  => 'string',
+            'description'  => 'Mailer Password'
+        ]);
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::MAIL:ENCRYPTION',
+        ], [
+            'value' => 'tls',
+            'type'  => 'string',
+            'description'  => 'Mailer Encryption (tls, ssl)'
+        ]);
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::MAIL:FROM_ADDRESS',
+        ], [
+            'value' => '',
+            'type'  => 'string',
+            'description'  => 'Mailer From Address'
+        ]);
+        Settings::firstOrCreate([
+            'key'   => 'SETTINGS::MAIL:FROM_NAME',
+        ], [
+            'value' => env('APP_NAME', 'Controlpanel'),
+            'type'  => 'string',
+            'description'  => 'Mailer From Name'
+        ]);
+    }
+}

+ 1 - 1
package-lock.json

@@ -1,5 +1,5 @@
 {
 {
-    "name": "bitsec-dashboard",
+    "name": "controllpanelgg",
     "lockfileVersion": 2,
     "lockfileVersion": 2,
     "requires": true,
     "requires": true,
     "packages": {
     "packages": {

BIN
public/images/discord_logo.png


+ 14 - 5
resources/lang/de.json

@@ -68,7 +68,7 @@
     "User ID": "User-ID",
     "User ID": "User-ID",
     "Server Creation Error": "Fehler beim erstellen des Servers",
     "Server Creation Error": "Fehler beim erstellen des Servers",
     "Your servers have been suspended!": "Deine Server wurden pausiert",
     "Your servers have been suspended!": "Deine Server wurden pausiert",
-    "To automatically re-enable your server\/s, you need to purchase more credits.": "Um deine Server zu reaktivieren, musst du mehr Credits kaufen!",
+    "To automatically re-enable your server/s, you need to purchase more credits.": "Um deine Server zu reaktivieren, musst du mehr Credits kaufen!",
     "Purchase credits": "Credits kaufen",
     "Purchase credits": "Credits kaufen",
     "If you have any questions please let us know.": "Solltest du weiter fragen haben, melde dich gerne beim Support!",
     "If you have any questions please let us know.": "Solltest du weiter fragen haben, melde dich gerne beim Support!",
     "Regards": "mit freundlichen Grüßen",
     "Regards": "mit freundlichen Grüßen",
@@ -217,7 +217,7 @@
     "A voucher can only be used one time per user. Uses specifies the number of different users that can use this voucher.": "Ein Gutschein kann von einem User nur einmal eingelöst werden. \"Benutzungen\" setzt die Anzahl an Usern die diesen Gutschein einlösen können.",
     "A voucher can only be used one time per user. Uses specifies the number of different users that can use this voucher.": "Ein Gutschein kann von einem User nur einmal eingelöst werden. \"Benutzungen\" setzt die Anzahl an Usern die diesen Gutschein einlösen können.",
     "Max": "Max",
     "Max": "Max",
     "Expires at": "Läuft ab am",
     "Expires at": "Läuft ab am",
-    "Used \/ Uses": "Benutzungen",
+    "Used / Uses": "Benutzungen",
     "Expires": "Ablauf",
     "Expires": "Ablauf",
     "Sign in to start your session": "Melde dich an um das Dashboard zu benutzen",
     "Sign in to start your session": "Melde dich an um das Dashboard zu benutzen",
     "Password": "Passwort",
     "Password": "Passwort",
@@ -287,7 +287,7 @@
     "No nodes have been linked!": "Es wurde keine Nodes verknüpft",
     "No nodes have been linked!": "Es wurde keine Nodes verknüpft",
     "No nests available!": "Keine Nests verfügbar",
     "No nests available!": "Keine Nests verfügbar",
     "No eggs have been linked!": "Es wurde keine Eggs verknüpft",
     "No eggs have been linked!": "Es wurde keine Eggs verknüpft",
-    "Software \/ Games": "Software \/ Spiele",
+    "Software / Games": "Software / Spiele",
     "Please select software ...": "Bitte Software auswählen",
     "Please select software ...": "Bitte Software auswählen",
     "---": "---",
     "---": "---",
     "Specification ": "Spezifikation",
     "Specification ": "Spezifikation",
@@ -350,5 +350,14 @@
     "Notes": "Notizen",
     "Notes": "Notizen",
     "Amount in words": "Betrag in Worten",
     "Amount in words": "Betrag in Worten",
     "Please pay until": "Zahlbar bis",
     "Please pay until": "Zahlbar bis",
-    "Account already exists on Pterodactyl. Please contact the Support!": "Der Account existiert bereits bei Pterodactyl. Kontaktiere den Support!"
-}
+    "Account already exists on Pterodactyl. Please contact the Support!": "Der Account existiert bereits bei Pterodactyl. Kontaktiere den Support!",
+    "de": "Deutsch",
+    "en": "Englisch",
+    "fr": "Französisch",
+    "cs": "Tschechisch",
+    "es": "Spanisch",
+    "hi": "Hindi",
+    "it": "Italienisch",
+    "pl": "Polnisch",
+    "zh": "Chinesisch"
+}

+ 32 - 19
resources/lang/en.json

@@ -4,11 +4,12 @@
     "api key has been removed!": "api key has been removed!",
     "api key has been removed!": "api key has been removed!",
     "Edit": "Edit",
     "Edit": "Edit",
     "Delete": "Delete",
     "Delete": "Delete",
-    "configuration has been updated!": "configuration has been updated!",
     "Store item has been created!": "Store item has been created!",
     "Store item has been created!": "Store item has been created!",
     "Store item has been updated!": "Store item has been updated!",
     "Store item has been updated!": "Store item has been updated!",
     "Product has been updated!": "Product has been updated!",
     "Product has been updated!": "Product has been updated!",
     "Store item has been removed!": "Store item has been removed!",
     "Store item has been removed!": "Store item has been removed!",
+    "Created at": "Created at",
+    "Error!": "Error!",
     "unknown": "unknown",
     "unknown": "unknown",
     "Pterodactyl synced": "Pterodactyl synced",
     "Pterodactyl synced": "Pterodactyl synced",
     "Your credit balance has been increased!": "Your credit balance has been increased!",
     "Your credit balance has been increased!": "Your credit balance has been increased!",
@@ -16,6 +17,7 @@
     "Your payment has been canceled!": "Your payment has been canceled!",
     "Your payment has been canceled!": "Your payment has been canceled!",
     "Payment method": "Payment method",
     "Payment method": "Payment method",
     "Invoice": "Invoice",
     "Invoice": "Invoice",
+    "Download": "Download",
     "Product has been created!": "Product has been created!",
     "Product has been created!": "Product has been created!",
     "Product has been removed!": "Product has been removed!",
     "Product has been removed!": "Product has been removed!",
     "Show": "Show",
     "Show": "Show",
@@ -26,6 +28,7 @@
     "Unsuspend": "Unsuspend",
     "Unsuspend": "Unsuspend",
     "Suspend": "Suspend",
     "Suspend": "Suspend",
     "Icons updated!": "Icons updated!",
     "Icons updated!": "Icons updated!",
+    "configuration has been updated!": "configuration has been updated!",
     "link has been created!": "link has been created!",
     "link has been created!": "link has been created!",
     "link has been updated!": "link has been updated!",
     "link has been updated!": "link has been updated!",
     "product has been removed!": "product has been removed!",
     "product has been removed!": "product has been removed!",
@@ -80,7 +83,6 @@
     "Check the docs for it here": "Check the docs for it here",
     "Check the docs for it here": "Check the docs for it here",
     "Causer": "Causer",
     "Causer": "Causer",
     "Description": "Description",
     "Description": "Description",
-    "Created at": "Created at",
     "Application API": "Application API",
     "Application API": "Application API",
     "Create": "Create",
     "Create": "Create",
     "Memo": "Memo",
     "Memo": "Memo",
@@ -89,13 +91,6 @@
     "Token": "Token",
     "Token": "Token",
     "Last used": "Last used",
     "Last used": "Last used",
     "Are you sure you wish to delete?": "Are you sure you wish to delete?",
     "Are you sure you wish to delete?": "Are you sure you wish to delete?",
-    "Edit Configuration": "Edit Configuration",
-    "Text Field": "Text Field",
-    "Cancel": "Cancel",
-    "Save": "Save",
-    "Configurations": "Configurations",
-    "Key": "Key",
-    "Value": "Value",
     "Nests": "Nests",
     "Nests": "Nests",
     "Sync": "Sync",
     "Sync": "Sync",
     "Active": "Active",
     "Active": "Active",
@@ -118,6 +113,7 @@
     "Locations": "Locations",
     "Locations": "Locations",
     "Eggs": "Eggs",
     "Eggs": "Eggs",
     "Last updated :date": "Last updated :date",
     "Last updated :date": "Last updated :date",
+    "Download all Invoices": "Download all Invoices",
     "Product Price": "Product Price",
     "Product Price": "Product Price",
     "Tax Value": "Tax Value",
     "Tax Value": "Tax Value",
     "Tax Percentage": "Tax Percentage",
     "Tax Percentage": "Tax Percentage",
@@ -151,11 +147,15 @@
     "Config": "Config",
     "Config": "Config",
     "Suspended at": "Suspended at",
     "Suspended at": "Suspended at",
     "Settings": "Settings",
     "Settings": "Settings",
-    "Dashboard icons": "Dashboard icons",
-    "Invoice Settings": "Invoice Settings",
+    "Key": "Key",
+    "Value": "Value",
+    "Edit Configuration": "Edit Configuration",
+    "Text Field": "Text Field",
+    "Cancel": "Cancel",
+    "Save": "Save",
     "Select panel icon": "Select panel icon",
     "Select panel icon": "Select panel icon",
     "Select panel favicon": "Select panel favicon",
     "Select panel favicon": "Select panel favicon",
-    "Download all Invoices": "Download all Invoices",
+    "Images and Icons may be cached, reload without cache to see your changes appear": "Images and Icons may be cached, reload without cache to see your changes appear",
     "Enter your companys name": "Enter your companys name",
     "Enter your companys name": "Enter your companys name",
     "Enter your companys address": "Enter your companys address",
     "Enter your companys address": "Enter your companys address",
     "Enter your companys phone number": "Enter your companys phone number",
     "Enter your companys phone number": "Enter your companys phone number",
@@ -165,6 +165,15 @@
     "Enter your custom invoice prefix": "Enter your custom invoice prefix",
     "Enter your custom invoice prefix": "Enter your custom invoice prefix",
     "Logo": "Logo",
     "Logo": "Logo",
     "Select Invoice Logo": "Select Invoice Logo",
     "Select Invoice Logo": "Select Invoice Logo",
+    "Available languages": "Available languages",
+    "Default language": "Default language",
+    "The fallback Language, if something goes wrong": "The fallback Language, if something goes wrong",
+    "Datable language": "Datable language",
+    "The Language of the Datatables. Grab the Language-Codes from here": "The Language of the Datatables. Grab the Language-Codes from here",
+    "Auto-translate": "Auto-translate",
+    "If this is checked, the Dashboard will translate itself to the Clients language, if available": "If this is checked, the Dashboard will translate itself to the Clients language, if available",
+    "Let the Client change the Language": "Let the Client change the Language",
+    "If this is checked, Clients will have the ability to manually change their Dashboard language": "If this is checked, Clients will have the ability to manually change their Dashboard language",
     "Store": "Store",
     "Store": "Store",
     "Currency code": "Currency code",
     "Currency code": "Currency code",
     "Checkout the paypal docs to select the appropriate code": "Checkout the paypal docs to select the appropriate code",
     "Checkout the paypal docs to select the appropriate code": "Checkout the paypal docs to select the appropriate code",
@@ -242,7 +251,7 @@
     "per month": "per month",
     "per month": "per month",
     "Out of Credits in": "Out of Credits in",
     "Out of Credits in": "Out of Credits in",
     "Home": "Home",
     "Home": "Home",
-    "Languages": "Languages",
+    "Language": "Language",
     "See all Notifications": "See all Notifications",
     "See all Notifications": "See all Notifications",
     "Redeem code": "Redeem code",
     "Redeem code": "Redeem code",
     "Profile": "Profile",
     "Profile": "Profile",
@@ -280,7 +289,6 @@
     "Re-Sync Discord": "Re-Sync Discord",
     "Re-Sync Discord": "Re-Sync Discord",
     "Save Changes": "Save Changes",
     "Save Changes": "Save Changes",
     "Server configuration": "Server configuration",
     "Server configuration": "Server configuration",
-    "Error!": "Error!",
     "Make sure to link your products to nodes and eggs.": "Make sure to link your products to nodes and eggs.",
     "Make sure to link your products to nodes and eggs.": "Make sure to link your products to nodes and eggs.",
     "There has to be at least 1 valid product for server creation": "There has to be at least 1 valid product for server creation",
     "There has to be at least 1 valid product for server creation": "There has to be at least 1 valid product for server creation",
     "No products available!": "No products available!",
     "No products available!": "No products available!",
@@ -321,9 +329,6 @@
     "Canceled ...": "Canceled ...",
     "Canceled ...": "Canceled ...",
     "Deletion has been canceled.": "Deletion has been canceled.",
     "Deletion has been canceled.": "Deletion has been canceled.",
     "Date": "Date",
     "Date": "Date",
-    "To": "To",
-    "From": "From",
-    "Pending": "Pending",
     "Subtotal": "Subtotal",
     "Subtotal": "Subtotal",
     "Payment Methods": "Payment Methods",
     "Payment Methods": "Payment Methods",
     "Amount Due": "Amount Due",
     "Amount Due": "Amount Due",
@@ -350,5 +355,13 @@
     "Notes": "Notes",
     "Notes": "Notes",
     "Amount in words": "Amount in words",
     "Amount in words": "Amount in words",
     "Please pay until": "Please pay until",
     "Please pay until": "Please pay until",
-    "Account already exists on Pterodactyl. Please contact the Support!": "Account already exists on Pterodactyl. Please contact the Support!"
-}
+    "fr": "French",
+    "cs": "Czech",
+    "en": "English",
+    "es": "Spanish",
+    "de": "German",
+    "hi": "Hindi",
+    "it": "Italian",
+    "pl": "Polish",
+    "zh": "Chinese"
+}

+ 0 - 63
resources/views/admin/configurations/editModel.blade.php

@@ -1,63 +0,0 @@
-<!-- The Modal -->
-<div class="modal fade" id="editConfigurationModel">
-    <div class="modal-dialog">
-        <div class="modal-content ">
-
-            <form method="post" action="{{route('admin.configurations.updatevalue')}}">
-                @csrf
-                    @method('PATCH')
-                <!-- Modal Header -->
-                <div class="modal-header">
-                    <h4 class="modal-title">{{__('Edit Configuration')}}</h4>
-                    <button type="button" class="close" data-dismiss="modal">&times;</button>
-                </div>
-
-                <!-- Modal body -->
-                <div class="modal-body">
-                    <div class="form-group">
-                        <label id="keyLabel" for="value">{{__('Text Field')}}</label>
-                        <div class="input-group">
-                            <div class="input-group-prepend">
-                                <div class="input-group-text">
-                                    <i class="fa fa-cog"></i>
-                                </div>
-                            </div>
-                        </div>
-                    </div>
-
-                    <div class="form-group">
-                        <input hidden id="key" name="key" type="text" class="form-control" required="required">
-                    </div>
-                </div>
-
-                <!-- Modal footer -->
-                <div class="modal-footer">
-                    <button type="button" class="btn btn-danger" data-dismiss="modal">{{__('Cancel')}}</button>
-                    <button type="submit" class="btn btn-primary">{{__('Save')}}</button>
-                </div>
-            </form>
-        </div>
-    </div>
-</div>
-
-<script>
-    window.configuration = {
-        parse(key, value, type) {
-            $('#keyLabel').html(key)
-            $('#key').val(key)
-            $('#value').remove();
-            if (type === 'integer') {
-                $('.input-group').append('<input id="value" name="value" type="number" class="form-control" required="required">')
-            } else if (type === 'boolean') {
-                $('.input-group').append('<select id="value" name="value" class="form-control" required=required>' +
-                    '<option value="true">true</option>' +
-                    '<option value="false">false</option>' +
-                    '</select>')
-            } else if (type === 'string') {
-                $('.input-group').append('<input id="value" name="value" type="text" class="form-control" required="required">')
-            }
-            $('#value').val(value)
-            $('#editConfigurationModel').modal('show')
-        }
-    }
-</script>

+ 0 - 91
resources/views/admin/configurations/index.blade.php

@@ -1,91 +0,0 @@
-@extends('layouts.main')
-
-@section('content')
-    <!-- CONTENT HEADER -->
-    <section class="content-header">
-        <div class="container-fluid">
-            <div class="row mb-2">
-                <div class="col-sm-6">
-                    <h1>{{__('Configurations')}}</h1>
-                </div>
-                <div class="col-sm-6">
-                    <ol class="breadcrumb float-sm-right">
-                        <li class="breadcrumb-item"><a href="{{route('home')}}"{{__('Dashboard')}}</a></li>
-                        <li class="breadcrumb-item"><a class="text-muted"
-                                                       href="{{route('admin.configurations.index')}}">{{__('Configurations')}}</a></li>
-                    </ol>
-                </div>
-            </div>
-        </div>
-    </section>
-    <!-- END CONTENT HEADER -->
-
-    <!-- MAIN CONTENT -->
-    <section class="content">
-        <div class="container-fluid">
-
-            <div class="card">
-
-                <div class="card-header">
-                    <div class="d-flex justify-content-between">
-                        <h5 class="card-title"><i class="fas fa-cog mr-2"></i>{{__('Configurations')}}</h5>
-                    </div>
-                </div>
-
-                <div class="card-body table-responsive">
-
-                    <table id="datatable" class="table table-striped">
-                        <thead>
-                        <tr>
-                            <th>{{__('Key')}}</th>
-                            <th>{{__('Value')}}</th>
-                            <th>{{__('Type')}}</th>
-                            <th width="600">{{__('Description')}}</th>
-                            <th>{{__('Created at')}}</th>
-                            <th></th>
-                        </tr>
-                        </thead>
-                        <tbody>
-                        </tbody>
-                    </table>
-
-                </div>
-            </div>
-
-
-        </div>
-        <!-- END CUSTOM CONTENT -->
-
-    </section>
-    <!-- END CONTENT -->
-
-    @include('admin.configurations.editModel')
-
-    <script>
-        document.addEventListener("DOMContentLoaded", function () {
-            $('#datatable').DataTable({
-                language: {
-                    url: '//cdn.datatables.net/plug-ins/1.11.3/i18n/{{config("app.datatable_locale")}}.json'
-                },
-                processing: true,
-                serverSide: true,
-                stateSave: true,
-                ajax: "{{route('admin.configurations.datatable')}}",
-                columns: [
-                    {data: 'key'},
-                    {data: 'value'},
-                    {data: 'type'},
-                    {data: 'description'},
-                    {data: 'created_at'},
-                    {data: 'actions', sortable: false},
-                ],
-                fnDrawCallback: function( oSettings ) {
-                    $('[data-toggle="popover"]').popover();
-                }
-            });
-        });
-    </script>
-
-
-
-@endsection

+ 6 - 0
resources/views/admin/payments/index.blade.php

@@ -27,6 +27,10 @@
             <div class="card">
             <div class="card">
                 <div class="card-header">
                 <div class="card-header">
                     <h5 class="card-title"><i class="fas fa-money-bill-wave mr-2"></i>{{ __('Payments') }}</h5>
                     <h5 class="card-title"><i class="fas fa-money-bill-wave mr-2"></i>{{ __('Payments') }}</h5>
+                    <div class="float-right">
+                        <a href="{{ route('admin.invoices.downloadAllInvoices') }}"><button
+                                class="btn btn-info">{{ __('Download all Invoices') }}</button></a>
+                    </div>
                 </div>
                 </div>
 
 
                 <div class="card-body table-responsive">
                 <div class="card-body table-responsive">
@@ -43,6 +47,7 @@
                                 <th>{{ __('Payment ID') }}</th>
                                 <th>{{ __('Payment ID') }}</th>
                                 <th>{{ __('Payment Method') }}</th>
                                 <th>{{ __('Payment Method') }}</th>
                                 <th>{{ __('Created at') }}</th>
                                 <th>{{ __('Created at') }}</th>
+                                <th></th>
                             </tr>
                             </tr>
                         </thead>
                         </thead>
                         <tbody>
                         <tbody>
@@ -78,6 +83,7 @@
                     {data: 'payment_id'},
                     {data: 'payment_id'},
                     {data: 'payment_method'},
                     {data: 'payment_method'},
                     {data: 'created_at'},
                     {data: 'created_at'},
+                    {data: 'actions' , sortable : false},
                 ],
                 ],
                 fnDrawCallback: function(oSettings) {
                 fnDrawCallback: function(oSettings) {
                     $('[data-toggle="popover"]').popover();
                     $('[data-toggle="popover"]').popover();

+ 26 - 164
resources/views/admin/settings/index.blade.php

@@ -6,13 +6,13 @@
         <div class="container-fluid">
         <div class="container-fluid">
             <div class="row mb-2">
             <div class="row mb-2">
                 <div class="col-sm-6">
                 <div class="col-sm-6">
-                    <h1>{{__('Settings')}}</h1>
+                    <h1>{{ __('Settings') }}</h1>
                 </div>
                 </div>
                 <div class="col-sm-6">
                 <div class="col-sm-6">
                     <ol class="breadcrumb float-sm-right">
                     <ol class="breadcrumb float-sm-right">
-                        <li class="breadcrumb-item"><a href="{{route('home')}}">{{__('Dashboard')}}</a></li>
+                        <li class="breadcrumb-item"><a href="{{ route('home') }}">{{ __('Dashboard') }}</a></li>
                         <li class="breadcrumb-item"><a class="text-muted"
                         <li class="breadcrumb-item"><a class="text-muted"
-                                                       href="{{route('admin.settings.index')}}">{{__('Settings')}}</a></li>
+                                href="{{ route('admin.settings.index') }}">{{ __('Settings') }}</a></li>
                     </ol>
                     </ol>
                 </div>
                 </div>
             </div>
             </div>
@@ -28,7 +28,7 @@
 
 
                 <div class="card-header">
                 <div class="card-header">
                     <div class="d-flex justify-content-between">
                     <div class="d-flex justify-content-between">
-                        <h5 class="card-title"><i class="fas fa-tools mr-2"></i>{{__('Settings')}}</h5>
+                        <h5 class="card-title"><i class="fas fa-tools mr-2"></i>{{ __('Settings') }}</h5>
                     </div>
                     </div>
                 </div>
                 </div>
 
 
@@ -36,169 +36,18 @@
 
 
                     <!-- Nav pills -->
                     <!-- Nav pills -->
                     <ul class="nav nav-tabs">
                     <ul class="nav nav-tabs">
-                        <li class="nav-item">
-                            <a class="nav-link active" data-toggle="pill" href="#dashboard-icons">{{__('Dashboard icons')}}</a>
-                        </li>
-                        <li class="nav-item">
-                            <a class="nav-link" data-toggle="pill" href="#invoice-settings">{{__('Invoice Settings')}}</a>
-                        </li>
+
+                        @foreach ($tabListItems as $tabListItem)
+                            {!! $tabListItem !!}
+                        @endforeach
                     </ul>
                     </ul>
 
 
                     <!-- Tab panes -->
                     <!-- Tab panes -->
                     <div class="tab-content">
                     <div class="tab-content">
-                        <div class="tab-pane mt-3 active" id="dashboard-icons">
-
-                            <form method="POST" enctype="multipart/form-data" class="mb-3"
-                                  action="{{route('admin.settings.update.icons')}}">
-                                @csrf
-                                @method('PATCH')
-
-                                <div class="row">
-                                    <div class="col-md-6 col-lg-4 col-12">
-                                        <div class="form-group">
-                                            <div class="custom-file mb-3 mt-3">
-                                                <input type="file" accept="image/png,image/jpeg,image/jpg"
-                                                       class="custom-file-input" name="icon" id="icon">
-                                                <label class="custom-file-label selected"
-                                                       for="icon">{{__('Select panel icon')}}</label>
-                                            </div>
-                                            @error('icon')
-                                            <span class="text-danger">
-                                                   {{$message}}
-                                               </span>
-                                            @enderror
-                                        </div>
-                                        <div class="form-group">
-                                            <div class="custom-file mb-3">
-                                                <input type="file" accept="image/x-icon" class="custom-file-input"
-                                                       name="favicon" id="favicon">
-                                                <label class="custom-file-label selected"
-                                                       for="favicon">{{__('Select panel favicon')}}</label>
-                                            </div>
-                                            @error('favicon')
-                                            <span class="text-danger">
-                                                   {{$message}}
-                                               </span>
-                                            @enderror
-                                        </div>
-                                    </div>
-                                </div>
-
-                                <button class="btn btn-primary">{{__('Submit')}}</button>
-                            </form>
-
-                            <p class="text-muted">Images and Icons may be cached, use <code>CNTRL + F5</code><sup>(google
-                                    chrome hotkey)</sup> to reload without cache to see your changes appear :)</p>
-
-                        </div>
-
-                        <div class="tab-pane mt-3" id="invoice-settings">
-                            <div class="float-right">
-                                <a href="{{route('admin.settings.downloadAllInvoices')}}"><button class="btn btn-success">{{__('Download all Invoices')}}</button></a>
-                            </div>
-
-                            <form method="POST" enctype="multipart/form-data" class="mb-3"
-                                  action="{{route('admin.settings.update.invoicesettings')}}">
-                                @csrf
-                                @method('PATCH')
-
-                                <div class="row">
-                                    <div class="col-md-6 col-lg-4 col-12">
-                                        <!-- Name -->
-                                        <div class="form-group">
-                                            <div class="custom-control mb-3">
-                                                <label for="company-name">{{__('Enter your companys name' )}}</label>
-                                                <input x-model="company-name" id="company-name" name="company-name"
-                                                       type="text" value="{{$company_name}}"
-                                                       class="form-control @error('company-name') is-invalid @enderror">
-                                            </div>
-                                        </div>
-                                        <!-- address -->
-                                        <div class="form-group">
-                                            <div class="custom-control mb-3">
-                                                <label
-                                                    for="company-address">{{__('Enter your companys address' )}}</label>
-                                                <input x-model="company-address" id="company-address"
-                                                       name="company-address" type="text" value="{{$company_adress}}"
-                                                       class="form-control @error('company-address') is-invalid @enderror">
-                                            </div>
-                                        </div>
-                                        <!-- Phone -->
-                                        <div class="form-group">
-                                            <div class="custom-control mb-3">
-                                                <label
-                                                    for="company-phone">{{__('Enter your companys phone number' )}}</label>
-                                                <input x-model="company-phone" id="company-phone" name="company-phone"
-                                                       type="text" value="{{$company_phone}}"
-                                                       class="form-control @error('company-phone') is-invalid @enderror">
-                                            </div>
-                                        </div>
-
-                                        <!-- VAT -->
-                                        <div class="form-group">
-                                            <div class="custom-control mb-3">
-                                                <label for="company-vat">{{__('Enter your companys VAT id' )}}</label>
-                                                <input x-model="company-vat" id="company-vat" name="company-vat"
-                                                       type="text" value="{{$company_vat}}"
-                                                       class="form-control @error('company-vat') is-invalid @enderror">
-                                            </div>
-                                        </div>
-
-                                        <!-- email -->
-                                        <div class="form-group">
-                                            <div class="custom-control mb-3">
-                                                <label
-                                                    for="company-mail">{{__('Enter your companys email address' )}}</label>
-                                                <input x-model="company-mail" id="company-mail" name="company-mail"
-                                                       type="text" value="{{$company_mail}}"
-                                                       class="form-control @error('company-mail') is-invalid @enderror">
-                                            </div>
-                                        </div>
-                                        <!-- website -->
-                                        <div class="form-group">
-                                            <div class="custom-control mb-3">
-                                                <label
-                                                    for="company-web">{{__('Enter your companys website' )}}</label>
-                                                <input x-model="company-web" id="company-web" name="company-web"
-                                                       type="text" value="{{$company_web}}"
-                                                       class="form-control @error('company-web') is-invalid @enderror">
-                                            </div>
-                                        </div>
-
-                                        <!-- website -->
-                                        <div class="form-group">
-                                            <div class="custom-control mb-3">
-                                                <label
-                                                    for="invoice-prefix">{{__('Enter your custom invoice prefix' )}}</label>
-                                                <input x-model="invoice-prefix" id="invoice-prefix" name="invoice-prefix"
-                                                       type="text" value="{{$invoice_prefix}}"
-                                                       class="form-control @error('invoice-prefix') is-invalid @enderror">
-                                            </div>
-                                        </div>
-
-                                        <!-- logo -->
-                                        <div class="form-group">
-                                            <div class="custom-control mb-3">
-                                                <label for="logo">{{__('Logo')}}</label>
-                                            <div class="custom-file mb-3">
-                                                <input type="file" accept="image/png,image/jpeg,image/jpg" class="custom-file-input"
-                                                       name="logo" id="logo">
-                                                <label class="custom-file-label selected"
-                                                       for="favicon">{{__('Select Invoice Logo')}}</label>
-                                            </div>
-                                            </div>
-                                            @error('logo')
-                                            <span class="text-danger">
-                                                   {{$message}}
-                                               </span>
-                                            @enderror
-                                        </div>
-                                    </div>
-                                </div>
-                                <button class="btn btn-primary">{{__('Submit')}}</button>
-                                <!-- end -->
-
-                        </div>
+
+                        @foreach ($tabs as $tab)
+                            @include($tab)
+                        @endforeach
                     </div>
                     </div>
 
 
 
 
@@ -218,12 +67,25 @@
 
 
     <script>
     <script>
         // Add the following code if you want the name of the file appear on select
         // Add the following code if you want the name of the file appear on select
+
         document.addEventListener('DOMContentLoaded', () => {
         document.addEventListener('DOMContentLoaded', () => {
-            $(".custom-file-input").on("change", function () {
+            $(".custom-file-input").on("change", function() {
                 var fileName = $(this).val().split("\\").pop();
                 var fileName = $(this).val().split("\\").pop();
                 $(this).siblings(".custom-file-label").addClass("selected").html(fileName);
                 $(this).siblings(".custom-file-label").addClass("selected").html(fileName);
             });
             });
         })
         })
+
+        const tabPaneHash = window.location.hash;
+        if (tabPaneHash) {
+            $('.nav-tabs a[href="' + tabPaneHash + '"]').tab('show');
+        }
+
+        $('.nav-tabs a').click(function(e) {
+            $(this).tab('show');
+            const scrollmem = $('body').scrollTop();
+            window.location.hash = this.hash;
+            $('html,body').scrollTop(scrollmem);
+        });
     </script>
     </script>
 
 
 
 

+ 111 - 0
resources/views/admin/settings/tabs/invoices.blade.php

@@ -0,0 +1,111 @@
+<div class="tab-pane mt-3 active" id="invoices">
+    <form method="POST" enctype="multipart/form-data" class="mb-3"
+        action="{{ route('admin.settings.update.invoicesettings') }}">
+        @csrf
+        @method('PATCH')
+
+        <div class="row">
+            <div class="col-md-3 p-3">
+                <!-- Name -->
+                <div class="form-group mb-3">
+                    <div class="custom-control p-0">
+                        <label for="company-name">{{ __('Company Name') }}:</label>
+                        <input x-model="company-name" id="company-name" name="company-name" type="text" required
+                            value="{{ config('SETTINGS::INVOICE:COMPANY_NAME') }}"
+                            class="form-control @error('company-name') is-invalid @enderror">
+                    </div>
+                </div>
+                <!-- address -->
+                <div class="form-group mb-3">
+                    <div class="custom-control  p-0">
+                        <label for="company-address">{{ __('Company Adress') }}:</label>
+                        <input x-model="company-address" id="company-address" name="company-address" type="text"
+                            value="{{ config('SETTINGS::INVOICE:COMPANY_ADDRESS') }}"
+                            class="form-control @error('company-address') is-invalid @enderror">
+                    </div>
+                </div>
+                <!-- Phone -->
+                <div class="form-group mb-3">
+                    <div class="custom-control p-0">
+                        <label for="company-phone">{{ __('Company Phonenumber') }}:</label>
+                        <input x-model="company-phone" id="company-phone" name="company-phone" type="text"
+                            value="{{ config('SETTINGS::INVOICE:COMPANY_PHONE') }}"
+                            class="form-control @error('company-phone') is-invalid @enderror">
+                    </div>
+                </div>
+
+                <!-- VAT -->
+                <div class="form-group mb-3">
+                    <div class="custom-control p-0">
+                        <label for="company-vat">{{ __('VAT ID') }}:</label>
+                        <input x-model="company-vat" id="company-vat" name="company-vat" type="text"
+                            value="{{ config('SETTINGS::INVOICE:COMPANY_VAT') }}"
+                            class="form-control @error('company-vat') is-invalid @enderror">
+                    </div>
+                </div>
+            </div>
+
+            <div class="col-md-3 p-3">
+                <!-- email -->
+                <div class="form-group mb-3">
+                    <div class="custom-control p-0">
+                        <label for="company-mail">{{ __('Company E-Mail Adress') }}:</label>
+                        <input x-model="company-mail" id="company-mail" name="company-mail" type="text"
+                            value="{{ config('SETTINGS::INVOICE:COMPANY_MAIL') }}"
+                            class="form-control @error('company-mail') is-invalid @enderror">
+                    </div>
+                </div>
+                <!-- website -->
+                <div class="form-group mb-3">
+                    <div class="custom-control p-0">
+                        <label for="company-web">{{ __('Company Website') }}:</label>
+                        <input x-model="company-web" id="company-web" name="company-web" type="text"
+                            value="{{ config('SETTINGS::INVOICE:COMPANY_WEBSITE') }}"
+                            class="form-control @error('company-web') is-invalid @enderror">
+                    </div>
+                </div>
+
+                <!-- prefix -->
+                <div class="form-group mb-3">
+                    <div class="custom-control p-0">
+                        <label for="invoice-prefix">{{ __('Invoice Prefix') }}:</label>
+                        <input x-model="invoice-prefix" id="invoice-prefix" name="invoice-prefix" type="text" required
+                            value="{{ config('SETTINGS::INVOICE:PREFIX') }}"
+                            class="form-control @error('invoice-prefix') is-invalid @enderror">
+                    </div>
+                </div>
+            </div>
+            <div class="col-md-3 p-3">
+                <div class="custom-control mb-3 p-0">
+                    <div class="col m-0 p-0 d-flex justify-content-between align-items-center">
+                        <div>
+                            <input value="true" id="enable-invoices" name="enable-invoices"
+                                {{ config('SETTINGS::INVOICE:ENABLED') == 'true' ? 'checked' : '' }} type="checkbox">
+                            <label for="enable-invoices">{{ __('Enable Invoices') }} </label>
+                        </div>
+                    </div>
+                </div>
+                <!-- logo -->
+                <div class="form-group mb-3">
+                    <div class="custom-control p-0">
+                        <label for="logo">{{ __('Logo') }}:</label>
+                        <div class="custom-file mb-3">
+                            <input type="file" accept="image/png,image/jpeg,image/jpg" class="custom-file-input"
+                                name="logo" id="logo">
+                            <label class="custom-file-label selected"
+                                for="favicon">{{ __('Select Invoice Logo') }}</label>
+                        </div>
+                    </div>
+                    @error('logo')
+                        <span class="text-danger">
+                        </span>
+                    @enderror
+                </div>
+            </div>
+        </div>
+
+        <div class="row">
+            <button class="btn btn-primary mt-3 ml-3">{{ __('Submit') }}</button>
+        </div>
+    </form>
+</div>

+ 91 - 0
resources/views/admin/settings/tabs/language.blade.php

@@ -0,0 +1,91 @@
+<div class="tab-pane mt-3" id="language">
+    <form method="POST" enctype="multipart/form-data" class="mb-3"
+        action="{{ route('admin.settings.update.languagesettings') }}">
+        @csrf
+        @method('PATCH')
+
+        <div class="row">
+            <div class="col-md-3 p-3">
+                <div class="form-group">
+                    <!-- AVAILABLE LANGUAGES -->
+                    <div class="custom-control mb-3 p-0">
+                        <label for="languages">{{ __('Available languages') }}:</label>
+                        <select id="languages" style="width:100%" class="custom-select" name="languages[]" required
+                            multiple="multiple" autocomplete="off" @error('defaultLanguage') is-invalid @enderror>
+
+                            @foreach (config('app.available_locales') as $lang)
+                                <option value="{{ $lang }}" @if (str_contains(config('SETTINGS::LOCALE:AVAILABLE'), $lang))  selected @endif>
+                                    {{ __($lang) }}
+                                </option>
+                            @endforeach
+                        </select>
+                    </div>
+
+                    <!-- DEFAULT LANGUAGE -->
+
+                    <div class="custom-control mb-3 p-0">
+                        <label for="defaultLanguage">{{ __('Default language') }}:
+                            <i data-toggle="popover" data-trigger="hover"
+                                data-content="{{ __('The fallback Language, if something goes wrong') }}"
+                                class="fas fa-info-circle"></i>
+                        </label>
+
+                        <select id="defaultLanguage" style="width:100%" class="custom-select" name="defaultLanguage"
+                            required autocomplete="off" @error('defaultLanguage') is-invalid @enderror>
+                            @foreach (config('app.available_locales') as $lang)
+                                <option value="{{ $lang }}" @if (config('SETTINGS::LOCALE:DEFAULT') == $lang) selected
+                            @endif>{{ __($lang) }}</option>
+                            @endforeach
+                        </select>
+                    </div>
+
+                    <div class="custom-control mb-3 p-0">
+                        <!--DATATABLE LANGUAGE -->
+                        <label for="datatable-language">{{ __('Datable language') }} <i data-toggle="popover"
+                                data-trigger="hover" data-html="true"
+                                data-content="{{ __('The datatables lang-code. <br><strong>Example:</strong> en-gb, fr_fr, de_de<br>More Information: ') }} https://datatables.net/plug-ins/i18n/"
+                                class="fas fa-info-circle"></i></label>
+                        <input x-model="datatable-language" id="datatable-language" name="datatable-language"
+                            type="text" required value="{{ config('SETTINGS::LOCALE:DATATABLES') }}"
+                            class="form-control @error('datatable-language') is-invalid @enderror">
+                    </div>
+                </div>
+            </div>
+
+
+            <div class="col-md-3 p-3">
+
+                <!-- AUTO TRANSLATE -->
+                <div class="form-group">
+                    <input value="true" id="autotranslate" name="autotranslate"
+                        {{ config('SETTINGS::LOCALE:DYNAMIC') == 'true' ? 'checked' : '' }} type="checkbox">
+                    <label for="autotranslate">{{ __('Auto-translate') }} <i data-toggle="popover"
+                            data-trigger="hover"
+                            data-content="{{ __('If this is checked, the Dashboard will translate itself to the Clients language, if available') }}"
+                            class="fas fa-info-circle"></i></label>
+
+                    <br />
+
+                    <!-- CLIENTS CAN CHANGE -->
+                    <input value="true" id="canClientChangeLanguage" name="canClientChangeLanguage"
+                        {{ config('SETTINGS::LOCALE:CLIENTS_CAN_CHANGE') == 'true' ? 'checked' : '' }}
+                        type="checkbox">
+                    <label for="canClientChangeLanguage">{{ __('Client Language-Switch') }} <i data-toggle="popover"
+                            data-trigger="hover"
+                            data-content="{{ __('If this is checked, Clients will have the ability to manually change their Dashboard language') }}"
+                            class="fas fa-info-circle"></i></label>
+
+                </div>
+            </div>
+        </div>
+        <div class="row">
+            <button class="btn btn-primary mt-3 ml-3">{{ __('Submit') }}</button>
+        </div>
+    </form>
+</div>
+
+<script>
+    document.addEventListener('DOMContentLoaded', (event) => {
+        $('.custom-select').select2();
+    })
+</script>

+ 194 - 0
resources/views/admin/settings/tabs/misc.blade.php

@@ -0,0 +1,194 @@
+<div class="tab-pane mt-3" id="misc">
+    <form method="POST" enctype="multipart/form-data" class="mb-3"
+        action="{{ route('admin.settings.update.miscsettings') }}">
+        @csrf
+        @method('PATCH')
+
+        <div class="row">
+
+            {{-- E-Mail --}}
+            <div class="col-md-3 px-3">
+                <div class="row mb-2">
+                    <div class="col text-center">
+                        <h1>E-Mail</h1>
+                    </div>
+                </div>
+
+                <div class="custom-control mb-3 p-0">
+                    <label for="mailservice">{{ __('Mail Service') }}:
+                        <i data-toggle="popover" data-trigger="hover"
+                            data-content="{{ __('The Mailer to send e-mails with') }}" class="fas fa-info-circle"></i>
+                    </label>
+                    <select id="mailservice" style="width:100%" class="custom-select" name="mailservice" required
+                        autocomplete="off" @error('mailservice') is-invalid @enderror>
+                        @foreach (array_keys(config('mail.mailers')) as $mailer)
+                            <option value="{{ $mailer }}" @if (config('SETTINGS::MAIL:MAILER') == $mailer) selected
+                        @endif>{{ __($mailer) }}</option>
+                        @endforeach
+                    </select>
+                </div>
+                <div class="form-group mb-3">
+                    <div class="custom-control p-0">
+                        <label for="mailhost">{{ __('Mail Host') }}:</label>
+                        <input x-model="mailhost" id="mailhost" name="mailhost" type="text"
+                            value="{{ config('SETTINGS::MAIL:HOST') }}"
+                            class="form-control @error('mailhost') is-invalid @enderror">
+                    </div>
+                </div>
+                <div class="form-group mb-3">
+                    <div class="custom-control p-0">
+                        <label for="mailport">{{ __('Mail Port') }}:</label>
+                        <input x-model="mailhost" id="mailport" name="mailport" type="text"
+                            value="{{ config('SETTINGS::MAIL:PORT') }}"
+                            class="form-control @error('mailport') is-invalid @enderror">
+                    </div>
+                </div>
+                <div class="form-group mb-3">
+                    <div class="custom-control p-0">
+                        <label for="mailusername">{{ __('Mail Username') }}:</label>
+                        <input x-model="mailusername" id="mailusername" name="mailusername" type="text"
+                            value="{{ config('SETTINGS::MAIL:USERNAME') }}"
+                            class="form-control @error('mailusername') is-invalid @enderror">
+                    </div>
+                </div>
+                <div class="form-group mb-3">
+                    <div class="custom-control p-0">
+                        <label for="mailpassword">{{ __('Mail Password') }}:</label>
+                        <input x-model="mailpassword" id="mailpassword" name="mailpassword" type="text"
+                            value="{{ config('SETTINGS::MAIL:PASSWORD') }}"
+                            class="form-control @error('mailpassword') is-invalid @enderror">
+                    </div>
+                </div>
+                <div class="form-group mb-3">
+                    <div class="custom-control p-0">
+                        <label for="mailencryption">{{ __('Mail Encryption') }}:</label>
+                        <input x-model="mailencryption" id="mailencryption" name="mailencryption" type="text"
+                            value="{{ config('SETTINGS::MAIL:ENCRYPTION') }}"
+                            class="form-control @error('mailencryption') is-invalid @enderror">
+                    </div>
+                </div>
+                <div class="form-group mb-3">
+                    <div class="custom-control p-0">
+                        <label for="mailfromadress">{{ __('Mail From Adress') }}:</label>
+                        <input x-model="mailfromadress" id="mailfromadress" name="mailfromadress" type="text"
+                            value="{{ config('SETTINGS::MAIL:FROM_ADDRESS') }}"
+                            class="form-control @error('mailfromadress') is-invalid @enderror">
+                    </div>
+                </div>
+                <div class="form-group mb-3">
+                    <div class="custom-control p-0">
+                        <label for="mailfromname">{{ __('Mail From Name') }}:</label>
+                        <input x-model="mailfromname" id="mailfromname" name="mailfromname" type="text"
+                            value="{{ config('SETTINGS::MAIL:FROM_NAME') }}"
+                            class="form-control @error('mailfromname') is-invalid @enderror">
+                    </div>
+                </div>
+            </div>
+
+            <!-- DISCORD -->
+            <div class="col-md-3 px-3">
+                <div class="row mb-2">
+                    <div class="col text-center">
+                        <h1>Discord</h1>
+                    </div>
+                </div>
+
+                <div class="form-group mb-3">
+                    <div class="custom-control p-0">
+                        <label for="discord-client-id">{{ __('Discord Client-ID') }}:</label>
+                        <input x-model="discord-client-id" id="discord-client-id" name="discord-client-id" type="text"
+                            value="{{ config('SETTINGS::DISCORD:CLIENT_ID') }}"
+                            class="form-control @error('discord-client-id') is-invalid @enderror">
+                    </div>
+                </div>
+
+                <div class="form-group mb-3">
+                    <div class="custom-control p-0">
+                        <label for="discord-client-secret">{{ __('Discord Client-Secret') }}:</label>
+                        <input x-model="discord-client-secret" id="discord-client-secret" name="discord-client-secret"
+                            type="text" value="{{ config('SETTINGS::DISCORD:CLIENT_SECRET') }}"
+                            class="form-control @error('discord-client-secret') is-invalid @enderror">
+                    </div>
+                </div>
+
+                <div class="form-group mb-3">
+                    <div class="custom-control p-0">
+                        <label for="discord-client-secret">{{ __('Discord Bot-Token') }}:</label>
+                        <input x-model="discord-bot-token" id="discord-bot-token" name="discord-bot-token" type="text"
+                            value="{{ config('SETTINGS::DISCORD:BOT_TOKEN') }}"
+                            class="form-control @error('discord-bot-token') is-invalid @enderror">
+                    </div>
+                </div>
+
+                <div class="form-group mb-3">
+                    <div class="custom-control p-0">
+                        <label for="discord-client-secret">{{ __('Discord Guild-ID') }}:</label>
+                        <input x-model="discord-guild-id" id="discord-guild-id" name="discord-guild-id" type="number"
+                            value="{{ config('SETTINGS::DISCORD:GUILD_ID') }}"
+                            class="form-control @error('discord-guild-id') is-invalid @enderror">
+                    </div>
+                </div>
+
+                <div class="form-group mb-3">
+                    <div class="custom-control p-0">
+                        <label for="discord-invite-url">{{ __('Discord Invite-URL') }}:</label>
+                        <input x-model="discord-invite-url" id="discord-invite-url" name="discord-invite-url"
+                            type="text" value="{{ config('SETTINGS::DISCORD:INVITE_URL') }}"
+                            class="form-control @error('discord-invite-url') is-invalid @enderror">
+                    </div>
+                </div>
+
+                <div class="form-group mb-3">
+                    <div class="custom-control p-0">
+                        <label for="discord-role-id">{{ __('Discord Role-ID') }}:</label>
+                        <input x-model="discord-role-id" id="discord-role-id" name="discord-role-id" type="number"
+                            value="{{ config('SETTINGS::DISCORD:ROLE_ID') }}"
+                            class="form-control @error('discord-role-id') is-invalid @enderror">
+                    </div>
+                </div>
+
+            </div>
+            <div class="col-md-3 px-3">
+                <div class="row mb-2">
+                    <div class="col text-center">
+                        <h1>ReCaptcha</h1>
+                    </div>
+                </div>
+
+                <div class="custom-control mb-3 p-0">
+                    <div class="col m-0 p-0 d-flex justify-content-between align-items-center">
+                        <div>
+                            <input value="true" id="enable-recaptcha" name="enable-recaptcha"
+                                {{ config('SETTINGS::RECAPTCHA:ENABLED') == 'true' ? 'checked' : '' }}
+                                type="checkbox">
+                            <label for="enable-recaptcha">{{ __('Enable ReCaptcha') }} </label>
+                        </div>
+                    </div>
+                </div>
+
+                <div class="form-group mb-3">
+                    <div class="custom-control p-0">
+                        <label for="recaptcha-site-key">{{ __('ReCaptcha Site-Key') }}:</label>
+                        <input x-model="recaptcha-site-key" id="recaptcha-site-key" name="recaptcha-site-key"
+                            type="text" value="{{ config('SETTINGS::RECAPTCHA:SITE_KEY') }}"
+                            class="form-control @error('recaptcha-site-key') is-invalid @enderror">
+                    </div>
+                </div>
+
+                <div class="form-group mb-3">
+                    <div class="custom-control p-0">
+                        <label for="recaptcha-secret-key">{{ __('ReCaptcha Secret-Key') }}:</label>
+                        <input x-model="recaptcha-secret-key" id="recaptcha-secret-key" name="recaptcha-secret-key"
+                            type="text" value="{{ config('SETTINGS::RECAPTCHA:SECRET_KEY') }}"
+                            class="form-control @error('recaptcha-secret-key') is-invalid @enderror">
+                    </div>
+                </div>
+            </div>
+
+
+        </div>
+        <div class="row">
+            <button class="btn btn-primary mt-3 ml-3">{{ __('Submit') }}</button>
+        </div>
+    </form>
+</div>

+ 144 - 0
resources/views/admin/settings/tabs/payment.blade.php

@@ -0,0 +1,144 @@
+<div class="tab-pane mt-3" id="payment">
+    <form method="POST" enctype="multipart/form-data" class="mb-3"
+        action="{{ route('admin.settings.update.paymentsettings') }}">
+        @csrf
+        @method('PATCH')
+
+        <div class="row">
+            {{-- PayPal --}}
+            <div class="col-md-3 px-3">
+                <div class="row mb-2">
+                    <div class="col text-center">
+                        <h1>PayPal</h1>
+                    </div>
+                </div>
+
+                <div class="form-group mb-3">
+                    <div class="custom-control p-0">
+                        <label for="paypal-client-id">{{ __('PayPal Client-ID') }}:</label>
+                        <input x-model="paypal-client-id" id="paypal-client-id" name="paypal-client-id" type="text"
+                            value="{{ config('SETTINGS::PAYMENTS:PAYPAL:CLIENT_ID') }}"
+                            class="form-control @error('paypal-client-id') is-invalid @enderror">
+                    </div>
+                </div>
+
+                <div class="form-group mb-3">
+                    <div class="custom-control p-0">
+                        <label for="paypal-client-secret">{{ __('PayPal Secret-Key') }}:</label>
+                        <input x-model="paypal-client-secret" id="paypal-client-secret" name="paypal-client-secret"
+                            type="text" value="{{ config('SETTINGS::PAYMENTS:PAYPAL:SECRET') }}"
+                            class="form-control @error('paypal-client-secret') is-invalid @enderror">
+                    </div>
+                </div>
+
+
+                <div class="form-group mb-3">
+                    <div class="custom-control p-0">
+                        <label for="paypal-sandbox-id">{{ __('PayPal Sandbox Client-ID') }}:</label>
+                        <small class="text-muted">({{ __('optional') }})</small>
+                        <input x-model="paypal-sandbox-id" id="paypal-sandbox-id" name="paypal-sandbox-id" type="text"
+                            value="{{ config('SETTINGS::PAYMENTS:PAYPAL:SANDBOX_CLIENT_ID') }}"
+                            class="form-control @error('paypal-sandbox-id') is-invalid @enderror">
+                    </div>
+                </div>
+
+                <div class="form-group mb-3">
+                    <div class="custom-control p-0">
+                        <label for="paypal-sandbox-secret">{{ __('PayPal Sandbox Secret-Key') }}:</label>
+                        <small class="text-muted">({{ __('optional') }})</small>
+                        <input x-model="paypal-sandbox-secret" id="paypal-sandbox-secret" name="paypal-sandbox-secret"
+                            type="text" value="{{ config('SETTINGS::PAYMENTS:PAYPAL:SANDBOX_SECRET') }}"
+                            class="form-control @error('paypal-sandbox-secret') is-invalid @enderror">
+                    </div>
+                </div>
+            </div>
+
+            {{-- Stripe --}}
+            <div class="col-md-3 px-3">
+
+                <div class="row mb-2">
+                    <div class="col text-center">
+                        <h1>Stripe</h1>
+                    </div>
+                </div>
+                <div class="form-group mb-3">
+                    <div class="custom-control p-0">
+                        <label for="stripe-secret">{{ __('Stripe Secret-Key') }}:</label>
+                        <input x-model="stripe-secret" id="stripe-secret" name="stripe-secret" type="text"
+                            value="{{ config('SETTINGS::PAYMENTS:STRIPE:SECRET') }}"
+                            class="form-control @error('stripe-secret') is-invalid @enderror">
+                    </div>
+                </div>
+                <div class="form-group mb-3">
+                    <div class="custom-control p-0">
+                        <label for="stripe-endpoint-secret">{{ __('Stripe Endpoint-Secret-Key') }}:</label>
+                        <input x-model="stripe-endpoint-secret" id="stripe-endpoint-secret"
+                            name="stripe-endpoint-secret" type="text"
+                            value="{{ config('SETTINGS::PAYMENTS:STRIPE:ENDPOINT_SECRET') }}"
+                            class="form-control @error('stripe-endpoint-secret') is-invalid @enderror">
+                    </div>
+                </div>
+
+                <div class="form-group mb-3">
+                    <div class="custom-control p-0">
+                        <label for="stripe-test-secret">{{ __('Stripe Test Secret-Key') }}:</label>
+                        <small class="text-muted">({{ __('optional') }})</small>
+                        <input x-model="stripe-test-secret" id="stripe-test-secret" name="stripe-test-secret"
+                            type="text" value="{{ config('SETTINGS::PAYMENTS:STRIPE:TEST_SECRET') }}"
+                            class="form-control @error('stripe-test-secret') is-invalid @enderror">
+                    </div>
+                </div>
+
+                <div class="form-group mb-3">
+                    <div class="custom-control p-0">
+                        <label for="stripe-endpoint-test-secret">{{ __('Stripe Test Endpoint-Secret-Key') }}:</label>
+                        <small class="text-muted">({{ __('optional') }})</small>
+                        <input x-model="stripe-endpoint-test-secret" id="stripe-endpoint-test-secret"
+                            name="stripe-endpoint-test-secret" type="text"
+                            value="{{ config('SETTINGS::PAYMENTS:STRIPE:ENDPOINT_TEST_SECRET') }}"
+                            class="form-control @error('stripe-endpoint-test-secret') is-invalid @enderror">
+                    </div>
+                </div>
+                <div class="form-group mb-3">
+                    <div class="custom-control p-0">
+                        <div class="col m-0 p-0 d-flex justify-content-between align-items-center">
+                            <label for="stripe-methods">{{ __('Payment Methods') }}:</label>
+                            <i data-toggle="popover" data-trigger="hover" data-html="true"
+                                data-content="Comma separated list of payment methods without whitespaces. <br><br> Example: card,klarna,sepa"
+                                class="fas fa-info-circle"></i>
+                        </div>
+                        <input x-model="stripe-methods" id="stripe-methods" name="stripe-methods" type="text"
+                            value="{{ config('SETTINGS::PAYMENTS:STRIPE:METHODS') }}"
+                            class="form-control @error('stripe-methods') is-invalid @enderror">
+                    </div>
+                </div>
+            </div>
+
+            {{-- Other --}}
+            <div class="col-md-3 px-3">
+                <div class="row mb-2">
+                    <div class="col text-center">
+                        <h1>Other</h1>
+                    </div>
+                </div>
+                <!-- Tax -->
+                <div class="form-group mb-3">
+                    <div class="custom-control p-0">
+                        <div class="col m-0 p-0 d-flex justify-content-between align-items-center">
+                            <label for="sales-tax">{{ __('Tax Value in %') }}:</label>
+                            <i data-toggle="popover" data-trigger="hover" data-html="true"
+                                data-content="Tax Value that will be added to the total price of the order. <br><br> Example: 19 results in (19%)"
+                                class="fas fa-info-circle"></i>
+                        </div>
+                        <input x-model="sales-tax" id="sales-tax" name="sales-tax" type="number"
+                            value="{{ config('SETTINGS::PAYMENTS:SALES_TAX') }}"
+                            class="form-control @error('sales-tax') is-invalid @enderror">
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div class="row">
+            <button class="btn btn-primary ml-3 mt-3">{{ __('Submit') }}</button>
+        </div>
+    </form>
+</div>

+ 208 - 0
resources/views/admin/settings/tabs/system.blade.php

@@ -0,0 +1,208 @@
+<div class="tab-pane mt-3" id="system">
+    <form method="POST" enctype="multipart/form-data" class="mb-3"
+        action="{{ route('admin.settings.update.systemsettings') }}">
+        @csrf
+        @method('PATCH')
+
+        <div class="row">
+            {{-- System --}}
+            <div class="col-md-3 px-3">
+                <div class="row mb-2">
+                    <div class="col text-center">
+                        <h1>{{ __('System') }}</h1>
+                    </div>
+                </div>
+                <div class="form-group">
+                    <div class="custom-control mb-1 p-0">
+                        <div class="col m-0 p-0 d-flex justify-content-between align-items-center">
+                            <div>
+                                <input value="true" id="register-ip-check" name="register-ip-check"
+                                    {{ config('SETTINGS::SYSTEM:REGISTER_IP_CHECK') == 'true' ? 'checked' : '' }}
+                                    type="checkbox">
+                                <label for="register-ip-check">{{ __('Register IP Check') }} </label>
+                            </div>
+                            <i data-toggle="popover" data-trigger="hover" data-html="true"
+                                data-content="{{ __('Prevent users from making multiple accounts using the same IP address.') }}"
+                                class="fas fa-info-circle"></i>
+                        </div>
+                    </div>
+                    <div class="custom-control mb-3 p-0">
+                        <div class="col m-0 p-0 d-flex justify-content-between align-items-center">
+                            <div>
+                                <input value="true" id="server-create-charge-first" name="server-create-charge-first"
+                                    {{ config('SETTINGS::SYSTEM:SERVER_CREATE_CHARGE_FIRST_HOUR') == 'true' ? 'checked' : '' }}
+                                    type="checkbox">
+                                <label for="server-create-charge-first">{{ __('Charge first hour at creation') }}
+                                </label>
+                            </div>
+                            <i data-toggle="popover" data-trigger="hover" data-html="true"
+                                data-content="{{ __('Charges the first hour worth of credits upon creating a server.') }}"
+                                class="fas fa-info-circle"></i>
+                        </div>
+                    </div>
+
+                    <div class="custom-control mb-3 p-0">
+                        <label for="credits-display-name">{{ __('Credits Display Name') }}</label>
+                        <input x-model="credits-display-name" id="credits-display-name" name="credits-display-name"
+                            type="text" value="{{ config('SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME', 'Credits') }}"
+                            class="form-control @error('credits-display-name') is-invalid @enderror" required>
+                    </div>
+                    <div class="custom-control p-0 mb-3">
+                        <div class="col m-0 p-0 d-flex justify-content-between align-items-center">
+                            <label for="phpmyadmin-url">{{ __('PHPMyAdmin URL') }}</label>
+                            <i data-toggle="popover" data-trigger="hover" data-html="true"
+                                data-content="{{ __('Enter the URL to your PHPMyAdmin installation. <strong>Without a trailing slash!</strong>') }}"
+                                class="fas fa-info-circle"></i>
+                        </div>
+                        <input x-model="phpmyadmin-url" id="phpmyadmin-url" name="phpmyadmin-url" type="text"
+                            value="{{ config('SETTINGS::MISC:PHPMYADMIN:URL') }}"
+                            class="form-control @error('phpmyadmin-url') is-invalid @enderror">
+                    </div>
+                    <div class="custom-control p-0 mb-3">
+                        <div class="col m-0 p-0 d-flex justify-content-between align-items-center">
+                            <label for="pterodactyl-url">{{ __('Pterodactyl URL') }}</label>
+                            <i data-toggle="popover" data-trigger="hover" data-html="true"
+                                data-content="{{ __('Enter the URL to your Pterodactyl installation. <strong>Without a trailing slash!</strong>') }}"
+                                class="fas fa-info-circle"></i>
+                        </div>
+                        <input x-model="pterodactyl-url" id="pterodactyl-url" name="pterodactyl-url" type="text"
+                            value="{{ config('SETTINGS::SYSTEM:PTERODACTYL:URL') }}"
+                            class="form-control @error('pterodactyl-url') is-invalid @enderror" required>
+                    </div>
+                    <div class="custom-control p-0 mb-3">
+                        <div class="col m-0 p-0 d-flex justify-content-between align-items-center">
+                            <label for="pterodactyl-api-key">{{ __('Pterodactyl API Key') }}</label>
+                            <i data-toggle="popover" data-trigger="hover" data-html="true"
+                                data-content="{{ __('Enter the API Key to your Pterodactyl installation.') }}"
+                                class="fas fa-info-circle"></i>
+                        </div>
+                        <input x-model="pterodactyl-api-key" id="pterodactyl-api-key" name="pterodactyl-api-key"
+                            type="text" value="{{ config('SETTINGS::SYSTEM:PTERODACTYL:TOKEN') }}"
+                            class="form-control @error('pterodactyl-api-key') is-invalid @enderror" required>
+                    </div>
+
+                </div>
+
+            </div>
+
+            {{-- User --}}
+            <div class="col-md-3 px-3">
+                <div class="row mb-2">
+                    <div class="col text-center">
+                        <h1>{{ __('User') }}</h1>
+                    </div>
+                </div>
+                <div class="form-group">
+                    <div class="custom-control mb-1 p-0">
+                        <input value="true" id="force-discord-verification" name="force-discord-verification"
+                            {{ config('SETTINGS::USER:FORCE_DISCORD_VERIFICATION') == 'true' ? 'checked' : '' }}
+                            type="checkbox">
+                        <label for="force-discord-verification">{{ __('Force Discord verification') }}
+                        </label>
+                    </div>
+                    <div class="custom-control mb-3 p-0">
+                        <input value="true" id="force-email-verification" name="force-email-verification"
+                            {{ config('SETTINGS::USER:FORCE_EMAIL_VERIFICATION') == 'true' ? 'checked' : '' }}
+                            type="checkbox">
+                        <label for="force-email-verification">{{ __('Force E-Mail verification') }} </label>
+                    </div>
+
+                    <div class="custom-control mb-3 p-0">
+                        <label for="initial-credits">{{ __('Initial Credits') }}</label>
+                        <input x-model="initial-credits" id="initial-credits" name="initial-credits" type="number"
+                            value="{{ config('SETTINGS::USER:INITIAL_CREDITS') }}"
+                            class="form-control @error('initial-credits') is-invalid @enderror" required>
+                    </div>
+                    <div class="custom-control mb-3 p-0">
+                        <label for="initial-server-limit">{{ __('Initial Server Limit') }}</label>
+                        <input x-model="initial-server-limit" id="initial-server-limit" name="initial-server-limit"
+                            type="number" value="{{ config('SETTINGS::USER:INITIAL_SERVER_LIMIT') }}"
+                            class="form-control @error('initial-server-limit') is-invalid @enderror" required>
+                    </div>
+                    <div class="custom-control mb-3 p-0">
+                        <label
+                            for="credits-reward-amount-discord">{{ __('Credits Reward Amount - Discord') }}</label>
+                        <input x-model="credits-reward-amount-discord" id="credits-reward-amount-discord"
+                            name="credits-reward-amount-discord" type="number"
+                            value="{{ config('SETTINGS::USER:CREDITS_REWARD_AFTER_VERIFY_DISCORD') }}"
+                            class="form-control @error('credits-reward-amount-discord') is-invalid @enderror" required>
+                    </div>
+
+                    <div class="custom-control mb-3 p-0">
+                        <label for="credits-reward-amount-email">{{ __('Credits Reward Amount - E-Mail') }}</label>
+                        <input x-model="credits-reward-amount-email" id="credits-reward-amount-email"
+                            name="credits-reward-amount-email" type="number"
+                            value="{{ config('SETTINGS::USER:CREDITS_REWARD_AFTER_VERIFY_EMAIL') }}"
+                            class="form-control @error('credits-reward-amount-email') is-invalid @enderror" required>
+                    </div>
+                    <div class="custom-control mb-3 p-0">
+                        <label for="server-limit-discord">{{ __('Server Limit Increase - Discord') }}</label>
+                        <input x-model="server-limit-discord" id="server-limit-discord" name="server-limit-discord"
+                            type="number"
+                            value="{{ config('SETTINGS::USER:SERVER_LIMIT_REWARD_AFTER_VERIFY_DISCORD') }}"
+                            class="form-control @error('server-limit-discord') is-invalid @enderror" required>
+                    </div>
+                    <div class="custom-control mb-3 p-0">
+                        <label for="server-limit-email">{{ __('Server Limit Increase - E-Mail') }}</label>
+                        <input x-model="server-limit-email" id="server-limit-email" name="server-limit-email"
+                            type="number"
+                            value="{{ config('SETTINGS::USER:SERVER_LIMIT_REWARD_AFTER_VERIFY_EMAIL') }}"
+                            class="form-control @error('server-limit-email') is-invalid @enderror" required>
+                    </div>
+                </div>
+            </div>
+
+            {{-- Server --}}
+            <div class="col-md-3 px-3">
+                <div class="row mb-2">
+                    <div class="col text-center">
+                        <h1>{{ __('Server') }}</h1>
+                    </div>
+                </div>
+                <div class="form-group">
+                    <div class="custom-control mb-3 p-0">
+                        <div class="col m-0 p-0 d-flex justify-content-between align-items-center">
+                            <label for="initial-credits">{{ __('Server Allocation Limit') }}</label>
+                            <i data-toggle="popover" data-trigger="hover" data-html="true"
+                                data-content="{{ __('The maximum amount of allocations to pull per node for automatic deployment, if more allocations are being used than this limit is set to, no new servers can be created!') }}"
+                                class="fas fa-info-circle"></i>
+                        </div>
+                        <input x-model="allocation-limit" id="allocation-limit" name="allocation-limit" type="number"
+                            value="{{ config('SETTINGS::SERVER:ALLOCATION_LIMIT') }}"
+                            class="form-control @error('allocation-limit') is-invalid @enderror" required>
+                    </div>
+                </div>
+                <div class="form-group">
+                    <div class="custom-file mb-3 mt-3">
+                        <input type="file" accept="image/png,image/jpeg,image/jpg" class="custom-file-input" name="icon"
+                            id="icon">
+                        <label class="custom-file-label selected" for="icon">{{ __('Select panel icon') }}</label>
+                    </div>
+                    @error('icon')
+                        <span class="text-danger">
+                            {{ $message }}
+                        </span>
+                    @enderror
+
+
+                    <div class="form-group">
+                        <div class="custom-file mb-3">
+                            <input type="file" accept="image/x-icon" class="custom-file-input" name="favicon"
+                                id="favicon">
+                            <label class="custom-file-label selected"
+                                for="favicon">{{ __('Select panel favicon') }}</label>
+                        </div>
+                        @error('favicon')
+                            <span class="text-danger">
+                                {{ $message }}
+                            </span>
+                        @enderror
+                    </div>
+                </div>
+            </div>
+        </div>
+        <div class="row">
+            <button class="btn btn-primary ml-3 mt-3">{{ __('Submit') }}</button>
+        </div>
+    </form>
+</div>

+ 24 - 15
resources/views/layouts/app.blade.php

@@ -1,5 +1,6 @@
 <!doctype html>
 <!doctype html>
 <html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
 <html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
+
 <head>
 <head>
     <meta charset="utf-8">
     <meta charset="utf-8">
     <meta name="viewport" content="width=device-width, initial-scale=1">
     <meta name="viewport" content="width=device-width, initial-scale=1">
@@ -8,7 +9,9 @@
     <meta name="csrf-token" content="{{ csrf_token() }}">
     <meta name="csrf-token" content="{{ csrf_token() }}">
 
 
     <title>{{ config('app.name', 'Laravel') }}</title>
     <title>{{ config('app.name', 'Laravel') }}</title>
-    <link rel="icon" href="{{\Illuminate\Support\Facades\Storage::disk('public')->exists('favicon.ico') ? \Illuminate\Support\Facades\Storage::disk('public')->url('favicon.ico') : asset('favicon.ico')}}" type="image/x-icon">
+    <link rel="icon"
+        href="{{ \Illuminate\Support\Facades\Storage::disk('public')->exists('favicon.ico') ? \Illuminate\Support\Facades\Storage::disk('public')->url('favicon.ico') : asset('favicon.ico') }}"
+        type="image/x-icon">
 
 
     <!-- Scripts -->
     <!-- Scripts -->
     <script src="{{ asset('js/app.js') }}" defer></script>
     <script src="{{ asset('js/app.js') }}" defer></script>
@@ -17,27 +20,32 @@
     <link rel="dns-prefetch" href="//fonts.gstatic.com">
     <link rel="dns-prefetch" href="//fonts.gstatic.com">
     <link href="https://fonts.googleapis.com/css?family=Nunito" rel="stylesheet">
     <link href="https://fonts.googleapis.com/css?family=Nunito" rel="stylesheet">
 
 
-    <link rel="stylesheet" href="{{asset('css/app.css')}}">
-    <link rel="preload" href="{{asset('plugins/fontawesome-free/css/all.min.css')}}" as="style" onload="this.onload=null;this.rel='stylesheet'">
-    <noscript><link rel="stylesheet" href="{{asset('plugins/fontawesome-free/css/all.min.css')}}"></noscript>
-    {!! htmlScriptTagJsApi() !!}
+    <link rel="stylesheet" href="{{ asset('css/app.css') }}">
+    <link rel="preload" href="{{ asset('plugins/fontawesome-free/css/all.min.css') }}" as="style"
+        onload="this.onload=null;this.rel='stylesheet'">
+    <noscript>
+        <link rel="stylesheet" href="{{ asset('plugins/fontawesome-free/css/all.min.css') }}">
+    </noscript>
+    @if (config('SETTINGS::RECAPTCHA:ENABLED') == 'true')
+        {!! htmlScriptTagJsApi() !!}
+    @endif
 </head>
 </head>
 @yield('content')
 @yield('content')
 
 
 <script src="https://cdn.jsdelivr.net/npm/sweetalert2@10.14.1/dist/sweetalert2.all.min.js"></script>
 <script src="https://cdn.jsdelivr.net/npm/sweetalert2@10.14.1/dist/sweetalert2.all.min.js"></script>
 <script>
 <script>
-    @if(Session::has('error'))
-    Swal.fire({
+    @if (Session::has('error'))
+        Swal.fire({
         icon: 'error',
         icon: 'error',
         title: 'Oops...',
         title: 'Oops...',
-        html: '{{Session::get('error')}}',
-    })
+        html: '{{ Session::get('error') }}',
+        })
     @endif
     @endif
 
 
-    @if(Session::has('success'))
-    Swal.fire({
+    @if (Session::has('success'))
+        Swal.fire({
         icon: 'success',
         icon: 'success',
-        title: '{{Session::get('success')}}',
+        title: '{{ Session::get('success') }}',
         position: 'top-end',
         position: 'top-end',
         showConfirmButton: false,
         showConfirmButton: false,
         background : '#343a40',
         background : '#343a40',
@@ -45,10 +53,11 @@
         timer: 3000,
         timer: 3000,
         timerProgressBar: true,
         timerProgressBar: true,
         didOpen: (toast) => {
         didOpen: (toast) => {
-            toast.addEventListener('mouseenter', Swal.stopTimer)
-            toast.addEventListener('mouseleave', Swal.resumeTimer)
+        toast.addEventListener('mouseenter', Swal.stopTimer)
+        toast.addEventListener('mouseleave', Swal.resumeTimer)
         }
         }
-    })
+        })
     @endif
     @endif
 </script>
 </script>
+
 </html>
 </html>

+ 46 - 34
resources/views/layouts/main.blade.php

@@ -32,6 +32,7 @@
     <noscript>
     <noscript>
         <link rel="stylesheet" href="{{ asset('plugins/fontawesome-free/css/all.min.css') }}">
         <link rel="stylesheet" href="{{ asset('plugins/fontawesome-free/css/all.min.css') }}">
     </noscript>
     </noscript>
+    <script src="{{ asset('js/app.js') }}"></script>
 </head>
 </head>
 
 
 <body class="sidebar-mini layout-fixed dark-mode" style="height: auto;">
 <body class="sidebar-mini layout-fixed dark-mode" style="height: auto;">
@@ -53,7 +54,6 @@
 
 
     <!-- Select2 -->
     <!-- Select2 -->
     <script src={{ asset('plugins/select2/js/select2.min.js') }}></script>
     <script src={{ asset('plugins/select2/js/select2.min.js') }}></script>
-
     <div class="wrapper">
     <div class="wrapper">
         <!-- Navbar -->
         <!-- Navbar -->
         <nav class="main-header sticky-top navbar navbar-expand navbar-dark navbar-light">
         <nav class="main-header sticky-top navbar navbar-expand navbar-dark navbar-light">
@@ -68,34 +68,34 @@
                             class="fas fa-home mr-2"></i>{{ __('Home') }}</a>
                             class="fas fa-home mr-2"></i>{{ __('Home') }}</a>
                 </li>
                 </li>
                 <li class="nav-item d-none d-sm-inline-block">
                 <li class="nav-item d-none d-sm-inline-block">
-                    <a href="{{ env('DISCORD_INVITE_URL') }}" class="nav-link" target="__blank"><i
+                    <a href="{{ config('SETTINGS::DISCORD:INVITE_URL') }}" class="nav-link" target="__blank"><i
                             class="fab fa-discord mr-2"></i>{{ __('Discord') }}</a>
                             class="fab fa-discord mr-2"></i>{{ __('Discord') }}</a>
                 </li>
                 </li>
                 <!-- Language Selection -->
                 <!-- Language Selection -->
-                <li class="nav-item dropdown">
-                    <a class="nav-link" href="#" id="languageDropdown" role="button" data-toggle="dropdown"
-                        aria-haspopup="true" aria-expanded="false">
-                        <span class="mr-1 d-lg-inline text-gray-600">
-                            <small><i class="fa fa-language mr-2"></i></small>{{ __('Languages') }}
-                        </span>
-                    </a>
-                    <div class="dropdown-menu dropdown-menu-right shadow animated--grow-in"
-                        aria-labelledby="changeLocale">
-                        <form method="post" action="{{ route('changeLocale') }}" class="nav-item text-center">
-                            @csrf
-                            @foreach (config('app.available_locales') as $key => $value)
-                                @if (!in_array(strtolower($key), UNSUPPORTED_LANGS))
-                                    <button class="dropdown-item" name="inputLocale" value="{{ $value }}">
-                                        {{ $key }}
+                @if (config('SETTINGS::LOCALE:CLIENTS_CAN_CHANGE') == 'true')
+                    <li class="nav-item dropdown">
+                        <a class="nav-link" href="#" id="languageDropdown" role="button" data-toggle="dropdown"
+                            aria-haspopup="true" aria-expanded="false">
+                            <span class="mr-1 d-lg-inline text-gray-600">
+                                <small><i class="fa fa-language mr-2"></i></small>{{ __('Language') }}
+                            </span>
+                        </a>
+                        <div class="dropdown-menu dropdown-menu-right shadow animated--grow-in"
+                            aria-labelledby="changeLocale">
+                            <form method="post" action="{{ route('changeLocale') }}" class="nav-item text-center">
+                                @csrf
+                                @foreach (explode(',', config('SETTINGS::LOCALE:AVAILABLE')) as $key)
+                                    <button class="dropdown-item" name="inputLocale" value="{{ $key }}">
+                                        {{ __($key) }}
                                     </button>
                                     </button>
-                                @endif
 
 
-                            @endforeach
+                                @endforeach
 
 
-                        </form>
-                    </div>
-                </li>
-                <!-- End Language Selection -->
+                            </form>
+                        </div>
+                    </li>
+                    <!-- End Language Selection -->
+                @endif
             </ul>
             </ul>
 
 
             <!-- Right navbar links -->
             <!-- Right navbar links -->
@@ -230,7 +230,7 @@
                             </a>
                             </a>
                         </li>
                         </li>
 
 
-                        @if ((env('PAYPAL_SECRET') && env('PAYPAL_CLIENT_ID')) || env('APP_ENV', 'local') == 'local')
+                        @if ((config('SETTINGS::PAYMENTS:PAYPAL:SECRET') && config('SETTINGS::PAYMENTS:PAYPAL:CLIENT_ID')) || env('APP_ENV', 'local') == 'local')
                             <li class="nav-item">
                             <li class="nav-item">
                                 <a href="{{ route('store.index') }}" class="nav-link @if (Request::routeIs('store.*') || Request::routeIs('checkout')) active @endif">
                                 <a href="{{ route('store.index') }}" class="nav-link @if (Request::routeIs('store.*') || Request::routeIs('checkout')) active @endif">
                                     <i class="nav-icon fa fa-coins"></i>
                                     <i class="nav-icon fa fa-coins"></i>
@@ -251,13 +251,6 @@
                                 </a>
                                 </a>
                             </li>
                             </li>
 
 
-                            <li class="nav-item">
-                                <a href="{{ route('admin.configurations.index') }}"
-                                    class="nav-link @if (Request::routeIs('admin.configurations.*')) active @endif">
-                                    <i class="nav-icon fas fa-cogs"></i>
-                                    <p>{{ __('Configurations') }}</p>
-                                </a>
-                            </li>
 
 
                             <li class="nav-item">
                             <li class="nav-item">
                                 <a href="{{ route('admin.settings.index') }}"
                                 <a href="{{ route('admin.settings.index') }}"
@@ -300,8 +293,7 @@
                             </li>
                             </li>
 
 
                             <li class="nav-item">
                             <li class="nav-item">
-                                <a href="{{ route('admin.store.index') }}"
-                                    class="nav-link @if (Request::routeIs('admin.store.*')) active @endif">
+                                <a href="{{ route('admin.store.index') }}" class="nav-link @if (Request::routeIs('admin.store.*')) active @endif">
                                     <i class="nav-icon fas fa-shopping-basket"></i>
                                     <i class="nav-icon fas fa-shopping-basket"></i>
                                     <p>{{ __('Store') }}</p>
                                     <p>{{ __('Store') }}</p>
                                 </a>
                                 </a>
@@ -411,6 +403,27 @@
     </div>
     </div>
     <!-- ./wrapper -->
     <!-- ./wrapper -->
 
 
+    <!-- Scripts -->
+    {{-- <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script> --}}
+    {{-- <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script> --}}
+    {{-- <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script> --}}
+    {{-- <script src="{{ asset('js/adminlte.min.js') }}"></script> --}}
+    <script src="https://cdn.jsdelivr.net/npm/sweetalert2@10.14.1/dist/sweetalert2.all.min.js"></script>
+
+    <script type="text/javascript" src="https://cdn.datatables.net/v/bs4/dt-1.10.24/datatables.min.js"></script>
+    <!-- Summernote -->
+    <script src="{{ asset('plugins/summernote/summernote-bs4.min.js') }}"></script>
+    <!-- select2 -->
+    <script src="{{ asset('plugins/select2/js/select2.min.js') }}"></script>
+
+    <!-- Moment.js -->
+    <script src="{{ asset('plugins/moment/moment.min.js') }}"></script>
+
+    <!-- Datetimepicker -->
+    <script src="{{ asset('plugins/tempusdominus-bootstrap-4/js/tempusdominus-bootstrap-4.min.js') }}"></script>
+
+    <!-- Select2 -->
+    <script src={{ asset('plugins/select2/js/select2.min.js') }}></script>
     <script>
     <script>
         $(document).ready(function() {
         $(document).ready(function() {
             $('[data-toggle="popover"]').popover();
             $('[data-toggle="popover"]').popover();
@@ -430,7 +443,6 @@
             html: '{{ Session::get('error') }}',
             html: '{{ Session::get('error') }}',
             })
             })
         @endif
         @endif
-
         @if (Session::has('success'))
         @if (Session::has('success'))
             Swal.fire({
             Swal.fire({
             icon: 'success',
             icon: 'success',

+ 83 - 83
resources/views/profile/index.blade.php

@@ -6,13 +6,13 @@
         <div class="container-fluid">
         <div class="container-fluid">
             <div class="row mb-2">
             <div class="row mb-2">
                 <div class="col-sm-6">
                 <div class="col-sm-6">
-                    <h1>{{__('Profile')}}</h1>
+                    <h1>{{ __('Profile') }}</h1>
                 </div>
                 </div>
                 <div class="col-sm-6">
                 <div class="col-sm-6">
                     <ol class="breadcrumb float-sm-right">
                     <ol class="breadcrumb float-sm-right">
-                        <li class="breadcrumb-item"><a href="{{route('home')}}">{{__('Dashboard')}}</a></li>
+                        <li class="breadcrumb-item"><a href="{{ route('home') }}">{{ __('Dashboard') }}</a></li>
                         <li class="breadcrumb-item"><a class="text-muted"
                         <li class="breadcrumb-item"><a class="text-muted"
-                                                       href="{{route('profile.index')}}">{{__('Profile')}}</a>
+                                href="{{ route('profile.index') }}">{{ __('Profile') }}</a>
                         </li>
                         </li>
                     </ol>
                     </ol>
                 </div>
                 </div>
@@ -27,36 +27,35 @@
 
 
             <div class="row">
             <div class="row">
                 <div class="col-lg-12 px-0">
                 <div class="col-lg-12 px-0">
-                    @if(!Auth::user()->hasVerifiedEmail() && strtolower($force_email_verification) == 'true')
+                    @if (!Auth::user()->hasVerifiedEmail() && strtolower($force_email_verification) == 'true')
                         <div class="alert alert-warning p-2 m-2">
                         <div class="alert alert-warning p-2 m-2">
-                            <h5><i class="icon fas fa-exclamation-circle"></i>{{__('Required Email verification!')}}
+                            <h5><i class="icon fas fa-exclamation-circle"></i>{{ __('Required Email verification!') }}
                             </h5>
                             </h5>
-                            {{__('You have not yet verified your email address')}}
+                            {{ __('You have not yet verified your email address') }}
                             <a class="text-primary"
                             <a class="text-primary"
-                               href="{{route('verification.send')}}">{{__('Click here to resend verification email')}}</a>
+                                href="{{ route('verification.send') }}">{{ __('Click here to resend verification email') }}</a>
                             <br>
                             <br>
-                            {{__('Please contact support If you didnt receive your verification email.')}}
+                            {{ __('Please contact support If you didnt receive your verification email.') }}
+
                         </div>
                         </div>
                     @endif
                     @endif
 
 
-                    @if(is_null(Auth::user()->discordUser) && strtolower($force_discord_verification) == 'true')
-                        @if(!empty(env('DISCORD_CLIENT_ID')) && !empty(env('DISCORD_CLIENT_SECRET')))
+                    @if (is_null(Auth::user()->discordUser) && strtolower($force_discord_verification) == 'true')
+                        @if (!empty(config('SETTINGS::DISCORD:CLIENT_ID')) && !empty(config('SETTINGS::DISCORD:CLIENT_SECRET')))
                             <div class="alert alert-warning p-2 m-2">
                             <div class="alert alert-warning p-2 m-2">
-                                <h5>
-                                    <i class="icon fas fa-exclamation-circle"></i>{{__('Required Discord verification!')}}
+                                <h5><i class="icon fas fa-exclamation-circle"></i>{{ __('Required Discord verification!') }}
                                 </h5>
                                 </h5>
-                                {{__('You have not yet verified your discord account')}}
+                                {{ __('You have not yet verified your discord account') }}
                                 <a class="text-primary"
                                 <a class="text-primary"
-                                   href="{{route('auth.redirect')}}">{{__('Login with discord')}}</a> <br>
-                                {{__('Please contact support If you face any issues.')}}
+                                    href="{{ route('auth.redirect') }}">{{ __('Login with discord') }}</a> <br>
+                                {{ __('Please contact support If you face any issues.') }}
                             </div>
                             </div>
                         @else
                         @else
                             <div class="alert alert-danger p-2 m-2">
                             <div class="alert alert-danger p-2 m-2">
-                                <h5>
-                                    <i class="icon fas fa-exclamation-circle"></i>{{__('Required Discord verification!')}}
+                                <h5><i class="icon fas fa-exclamation-circle"></i>{{ __('Required Discord verification!') }}
                                 </h5>
                                 </h5>
-                                {{__('Due to system settings you are required to verify your discord account!')}} <br>
-                                {{__('It looks like this hasnt been set-up correctly! Please contact support.')}}'
+                                {{ __('Due to system settings you are required to verify your discord account!') }} <br>
+                                {{ __('It looks like this hasnt been set-up correctly! Please contact support.') }}'
                             </div>
                             </div>
                         @endif
                         @endif
                     @endif
                     @endif
@@ -64,7 +63,7 @@
                 </div>
                 </div>
             </div>
             </div>
 
 
-            <form class="form" action="{{route('profile.update' , Auth::user()->id)}}" method="post">
+            <form class="form" action="{{ route('profile.update', Auth::user()->id) }}" method="post">
                 @csrf
                 @csrf
                 @method('PATCH')
                 @method('PATCH')
                 <div class="card">
                 <div class="card">
@@ -73,43 +72,42 @@
                             <div class="row">
                             <div class="row">
                                 <div class="col-12 col-sm-auto mb-4">
                                 <div class="col-12 col-sm-auto mb-4">
                                     <div class="slim rounded-circle  border-secondary border text-gray-dark"
                                     <div class="slim rounded-circle  border-secondary border text-gray-dark"
-                                         data-label="Change your avatar"
-                                         data-max-file-size="3"
-                                         data-save-initial-image="true"
-                                         style="width: 140px;height:140px; cursor: pointer"
-                                         data-size="140,140">
-                                        <img src="{{$user->getAvatar()}}" alt="avatar">
+                                        data-label="Change your avatar" data-max-file-size="3"
+                                        data-save-initial-image="true" style="width: 140px;height:140px; cursor: pointer"
+                                        data-size="140,140">
+                                        <img src="{{ $user->getAvatar() }}" alt="avatar">
                                     </div>
                                     </div>
                                 </div>
                                 </div>
                                 <div class="col d-flex flex-column flex-sm-row justify-content-between mb-3">
                                 <div class="col d-flex flex-column flex-sm-row justify-content-between mb-3">
-                                    <div class="text-center text-sm-left mb-2 mb-sm-0"><h4
-                                            class="pt-sm-2 pb-1 mb-0 text-nowrap">{{$user->name}}</h4>
-                                        <p class="mb-0">{{$user->email}}
-                                            @if($user->hasVerifiedEmail())
+                                    <div class="text-center text-sm-left mb-2 mb-sm-0">
+                                        <h4 class="pt-sm-2 pb-1 mb-0 text-nowrap">{{ $user->name }}</h4>
+                                        <p class="mb-0">{{ $user->email }}
+                                            @if ($user->hasVerifiedEmail())
                                                 <i data-toggle="popover" data-trigger="hover" data-content="Verified"
                                                 <i data-toggle="popover" data-trigger="hover" data-content="Verified"
-                                                   class="text-success fas fa-check-circle"></i>
+                                                    class="text-success fas fa-check-circle"></i>
                                             @else
                                             @else
-                                                <i data-toggle="popover" data-trigger="hover"
-                                                   data-content="Not verified"
-                                                   class="text-danger fas fa-exclamation-circle"></i>
+                                                <i data-toggle="popover" data-trigger="hover" data-content="Not verified"
+                                                    class="text-danger fas fa-exclamation-circle"></i>
                                             @endif
                                             @endif
 
 
                                         </p>
                                         </p>
                                         <div class="mt-1">
                                         <div class="mt-1">
-                                            <span class="badge badge-primary"><i class="fa fa-coins mr-2"></i>{{$user->Credits()}}</span>
+                                            <span class="badge badge-primary"><i
+                                                    class="fa fa-coins mr-2"></i>{{ $user->Credits() }}</span>
                                         </div>
                                         </div>
                                     </div>
                                     </div>
 
 
                                     <div class="text-center text-sm-right"><span
                                     <div class="text-center text-sm-right"><span
-                                            class="badge badge-secondary">{{$user->role}}</span>
-                                        <div class="text-muted"><small>{{$user->created_at->isoFormat('LL')}}</small>
+                                            class="badge badge-secondary">{{ $user->role }}</span>
+                                        <div class="text-muted">
+                                            <small>{{ $user->created_at->isoFormat('LL') }}</small>
                                         </div>
                                         </div>
                                     </div>
                                     </div>
                                 </div>
                                 </div>
                             </div>
                             </div>
                             <ul class="nav nav-tabs">
                             <ul class="nav nav-tabs">
                                 <li class="nav-item"><a href="javasript:void(0)"
                                 <li class="nav-item"><a href="javasript:void(0)"
-                                                        class="active nav-link">{{__('Settings')}}</a>
+                                        class="active nav-link">{{ __('Settings') }}</a>
                                 </li>
                                 </li>
                             </ul>
                             </ul>
                             <div class="tab-content pt-3">
                             <div class="tab-content pt-3">
@@ -134,29 +132,28 @@
                                                         @endif
                                                         @endif
                                                     <div class="form-group"><label>{{__('Name')}}</label> <input
                                                     <div class="form-group"><label>{{__('Name')}}</label> <input
                                                             class="form-control @error('name') is-invalid @enderror"
                                                             class="form-control @error('name') is-invalid @enderror"
-                                                            type="text" name="name"
-                                                            placeholder="{{$user->name}}" value="{{$user->name}}">
+                                                            type="text" name="name" placeholder="{{ $user->name }}"
+                                                            value="{{ $user->name }}">
 
 
                                                         @error('name')
                                                         @error('name')
-                                                        <div class="invalid-feedback">
-                                                            {{$message}}
-                                                        </div>
+                                                            <div class="invalid-feedback">
+                                                                {{ $message }}
+                                                            </div>
                                                         @enderror
                                                         @enderror
                                                     </div>
                                                     </div>
                                                 </div>
                                                 </div>
                                             </div>
                                             </div>
                                             <div class="row">
                                             <div class="row">
                                                 <div class="col">
                                                 <div class="col">
-                                                    <div class="form-group"><label>{{__('Email')}}</label> <input
+                                                    <div class="form-group"><label>{{ __('Email') }}</label> <input
                                                             class="form-control @error('email') is-invalid @enderror"
                                                             class="form-control @error('email') is-invalid @enderror"
-                                                            type="text"
-                                                            placeholder="{{$user->email}}" name="email"
-                                                            value="{{$user->email}}">
+                                                            type="text" placeholder="{{ $user->email }}" name="email"
+                                                            value="{{ $user->email }}">
 
 
                                                         @error('email')
                                                         @error('email')
-                                                        <div class="invalid-feedback">
-                                                            {{$message}}
-                                                        </div>
+                                                            <div class="invalid-feedback">
+                                                                {{ $message }}
+                                                            </div>
                                                         @enderror
                                                         @enderror
                                                     </div>
                                                     </div>
                                                 </div>
                                                 </div>
@@ -165,33 +162,34 @@
                                     </div>
                                     </div>
                                     <div class="row">
                                     <div class="row">
                                         <div class="col-12 col-sm-6 mb-3">
                                         <div class="col-12 col-sm-6 mb-3">
-                                            <div class="mb-3"><b>{{__('Change Password')}}</b></div>
+                                            <div class="mb-3"><b>{{ __('Change Password') }}</b></div>
                                             <div class="row">
                                             <div class="row">
                                                 <div class="col">
                                                 <div class="col">
-                                                    <div class="form-group"><label>{{__('Current Password')}}</label>
+                                                    <div class="form-group">
+                                                        <label>{{ __('Current Password') }}</label>
                                                         <input
                                                         <input
                                                             class="form-control @error('current_password') is-invalid @enderror"
                                                             class="form-control @error('current_password') is-invalid @enderror"
-                                                            name="current_password" type="password"
-                                                            placeholder="••••••">
+                                                            name="current_password" type="password" placeholder="••••••">
 
 
                                                         @error('current_password')
                                                         @error('current_password')
-                                                        <div class="invalid-feedback">
-                                                            {{$message}}
-                                                        </div>
+                                                            <div class="invalid-feedback">
+                                                                {{ $message }}
+                                                            </div>
                                                         @enderror
                                                         @enderror
                                                     </div>
                                                     </div>
                                                 </div>
                                                 </div>
                                             </div>
                                             </div>
                                             <div class="row">
                                             <div class="row">
                                                 <div class="col">
                                                 <div class="col">
-                                                    <div class="form-group"><label>{{__('New Password')}}</label> <input
+                                                    <div class="form-group"><label>{{ __('New Password') }}</label>
+                                                        <input
                                                             class="form-control @error('new_password') is-invalid @enderror"
                                                             class="form-control @error('new_password') is-invalid @enderror"
                                                             name="new_password" type="password" placeholder="••••••">
                                                             name="new_password" type="password" placeholder="••••••">
 
 
                                                         @error('new_password')
                                                         @error('new_password')
-                                                        <div class="invalid-feedback">
-                                                            {{$message}}
-                                                        </div>
+                                                            <div class="invalid-feedback">
+                                                                {{ $message }}
+                                                            </div>
                                                         @enderror
                                                         @enderror
                                                     </div>
                                                     </div>
                                                 </div>
                                                 </div>
@@ -199,60 +197,62 @@
                                             <div class="row">
                                             <div class="row">
                                                 <div class="col">
                                                 <div class="col">
                                                     <div class="form-group">
                                                     <div class="form-group">
-                                                        <label>{{__('Confirm Password')}}</span></label>
+                                                        <label>{{ __('Confirm Password') }}</span></label>
                                                         <input
                                                         <input
                                                             class="form-control @error('new_password_confirmation') is-invalid @enderror"
                                                             class="form-control @error('new_password_confirmation') is-invalid @enderror"
                                                             name="new_password_confirmation" type="password"
                                                             name="new_password_confirmation" type="password"
                                                             placeholder="••••••">
                                                             placeholder="••••••">
 
 
                                                         @error('new_password_confirmation')
                                                         @error('new_password_confirmation')
-                                                        <div class="invalid-feedback">
-                                                            {{$message}}
-                                                        </div>
+                                                            <div class="invalid-feedback">
+                                                                {{ $message }}
+                                                            </div>
                                                         @enderror
                                                         @enderror
                                                     </div>
                                                     </div>
                                                 </div>
                                                 </div>
                                             </div>
                                             </div>
                                         </div>
                                         </div>
-                                        @if(!empty(env('DISCORD_CLIENT_ID')) && !empty(env('DISCORD_CLIENT_SECRET')))
+                                        @if (!empty(config('SETTINGS::DISCORD:CLIENT_ID')) && !empty(config('SETTINGS::DISCORD:CLIENT_SECRET')))
                                             <div class="col-12 col-sm-5 offset-sm-1 mb-3">
                                             <div class="col-12 col-sm-5 offset-sm-1 mb-3">
-                                                @if(is_null(Auth::user()->discordUser))
-                                                    <b>{{__('Link your discord account!')}}</b>
+                                                @if (is_null(Auth::user()->discordUser))
+                                                    <b>{{ __('Link your discord account!') }}</b>
                                                     <div class="verify-discord">
                                                     <div class="verify-discord">
                                                         <div class="mb-3">
                                                         <div class="mb-3">
-                                                            @if($credits_reward_after_verify_discord)
-                                                                <p>{{__('By verifying your discord account, you receive extra Credits and increased Server amounts')}}
+                                                            @if ($credits_reward_after_verify_discord)
+                                                                <p>{{ __('By verifying your discord account, you receive extra Credits and increased Server amounts') }}
                                                                 </p>
                                                                 </p>
                                                             @endif
                                                             @endif
                                                         </div>
                                                         </div>
                                                     </div>
                                                     </div>
 
 
-                                                    <a class="btn btn-light" href="{{route('auth.redirect')}}">
-                                                        <i class="fab fa-discord mr-2"></i>{{__('Login with Discord')}}
+                                                    <a class="btn btn-light" href="{{ route('auth.redirect') }}">
+                                                        <i class="fab fa-discord mr-2"></i>{{ __('Login with Discord') }}
                                                     </a>
                                                     </a>
                                                 @else
                                                 @else
                                                     <div class="verified-discord">
                                                     <div class="verified-discord">
                                                         <div class="my-3 callout callout-info">
                                                         <div class="my-3 callout callout-info">
-                                                            <p>{{__('You are verified!')}}</p>
+                                                            <p>{{ __('You are verified!') }}</p>
                                                         </div>
                                                         </div>
                                                     </div>
                                                     </div>
                                                     <div class="row pl-2">
                                                     <div class="row pl-2">
                                                         <div class="small-box bg-dark">
                                                         <div class="small-box bg-dark">
                                                             <div class="d-flex justify-content-between">
                                                             <div class="d-flex justify-content-between">
                                                                 <div class="p-3">
                                                                 <div class="p-3">
-                                                                    <h3>{{$user->discordUser->username}}
-                                                                        <sup>{{$user->discordUser->locale}}</sup></h3>
-                                                                    <p>{{$user->discordUser->id}}
+                                                                    <h3>{{ $user->discordUser->username }}
+                                                                        <sup>{{ $user->discordUser->locale }}</sup>
+                                                                    </h3>
+                                                                    <p>{{ $user->discordUser->id }}
                                                                     </p>
                                                                     </p>
                                                                 </div>
                                                                 </div>
-                                                                <div class="p-3"><img width="100px" height="100px"
-                                                                                      class="rounded-circle"
-                                                                                      src="{{$user->discordUser->getAvatar()}}"
-                                                                                      alt="avatar"></div>
+                                                                <div class="p-3"><img width="100px"
+                                                                        height="100px" class="rounded-circle"
+                                                                        src="{{ $user->discordUser->getAvatar() }}"
+                                                                        alt="avatar"></div>
                                                             </div>
                                                             </div>
                                                             <div class="small-box-footer">
                                                             <div class="small-box-footer">
-                                                                <a href="{{route('auth.redirect')}}">
-                                                                    <i class="fab fa-discord mr-1"></i>{{__('Re-Sync Discord')}}
+                                                                <a href="{{ route('auth.redirect') }}">
+                                                                    <i
+                                                                        class="fab fa-discord mr-1"></i>{{ __('Re-Sync Discord') }}
                                                                 </a>
                                                                 </a>
                                                             </div>
                                                             </div>
                                                         </div>
                                                         </div>
@@ -265,7 +265,7 @@
                                     <div class="row">
                                     <div class="row">
                                         <div class="col d-flex justify-content-end">
                                         <div class="col d-flex justify-content-end">
                                             <button class="btn btn-primary"
                                             <button class="btn btn-primary"
-                                                    type="submit">{{__('Save Changes')}}</button>
+                                                type="submit">{{ __('Save Changes') }}</button>
                                         </div>
                                         </div>
                                     </div>
                                     </div>
 
 

+ 2 - 0
resources/views/servers/create.blade.php

@@ -42,7 +42,9 @@
                                     @if (Auth::user()->role == 'admin')
                                     @if (Auth::user()->role == 'admin')
                                         {{ __('Make sure to link your products to nodes and eggs.') }} <br>
                                         {{ __('Make sure to link your products to nodes and eggs.') }} <br>
                                         {{ __('There has to be at least 1 valid product for server creation') }}
                                         {{ __('There has to be at least 1 valid product for server creation') }}
+                                        <a href="{{route('admin.overview.sync')}}">{{ __('Sync now') }}</a>
                                     @endif
                                     @endif
+
                                 </p>
                                 </p>
                                 <ul>
                                 <ul>
                                     @if ($productCount === 0)
                                     @if ($productCount === 0)

+ 3 - 3
resources/views/servers/index.blade.php

@@ -55,8 +55,8 @@
                                         </a>
                                         </a>
                                         <div class="dropdown-menu dropdown-menu-right shadow animated--fade-in"
                                         <div class="dropdown-menu dropdown-menu-right shadow animated--fade-in"
                                             aria-labelledby="dropdownMenuLink">
                                             aria-labelledby="dropdownMenuLink">
-                                            @if (!empty(env('PHPMYADMIN_URL')))
-                                                <a href="{{ env('PHPMYADMIN_URL', 'http://localhost') }}"
+                                            @if (!empty(config('SETTINGS::MISC:PHPMYADMIN:URL')))
+                                                <a href="{{ config('SETTINGS::MISC:PHPMYADMIN:URL') }}"
                                                     class="dropdown-item text-info" target="__blank"><i title="manage"
                                                     class="dropdown-item text-info" target="__blank"><i title="manage"
                                                         class="fas fa-database mr-2"></i><span>{{ __('Database') }}</span></a>
                                                         class="fas fa-database mr-2"></i><span>{{ __('Database') }}</span></a>
                                             @endif
                                             @endif
@@ -149,7 +149,7 @@
                         </div>
                         </div>
 
 
                         <div class="card-footer d-flex align-items-center justify-content-between">
                         <div class="card-footer d-flex align-items-center justify-content-between">
-                            <a href="{{ env('PTERODACTYL_URL', 'http://localhost') }}/server/{{ $server->identifier }}"
+                            <a href="{{ config('SETTINGS::SYSTEM:PTERODACTYL:URL') }}/server/{{ $server->identifier }}"
                                 target="__blank"
                                 target="__blank"
                                 class="btn btn-info mx-3 w-100 align-items-center justify-content-center d-flex">
                                 class="btn btn-info mx-3 w-100 align-items-center justify-content-center d-flex">
                                 <i class="fas fa-tools mr-2"></i>
                                 <i class="fas fa-tools mr-2"></i>

+ 2 - 2
resources/views/store/checkout.blade.php

@@ -78,7 +78,7 @@
                                 <p class="lead">{{ __('Payment Methods') }}:</p>
                                 <p class="lead">{{ __('Payment Methods') }}:</p>
 
 
                                 <div>
                                 <div>
-                                    @if (env('PAYPAL_SANDBOX_SECRET') || env('PAYPAL_SECRET'))
+                                    @if (config('SETTINGS::PAYMENTS:PAYPAL:SECRET') || config('SETTINGS::PAYMENTS:PAYPAL:SANDBOX_SECRET'))
                                         <label class="text-center " for="paypal">
                                         <label class="text-center " for="paypal">
                                             <img class="mb-3" height="50"
                                             <img class="mb-3" height="50"
                                                 src="{{ url('/images/paypal_logo.png') }}"></br>
                                                 src="{{ url('/images/paypal_logo.png') }}"></br>
@@ -88,7 +88,7 @@
                                             </input>
                                             </input>
                                         </label>
                                         </label>
                                     @endif
                                     @endif
-                                    @if (env('STRIPE_TEST_SECRET') || env('STRIPE_SECRET'))
+                                    @if (config('SETTINGS::PAYMENTS:STRIPE:TEST_SECRET') || config('SETTINGS::PAYMENTS:STRIPE:SECRET'))
                                         <label class="ml-5 text-center " for="stripe">
                                         <label class="ml-5 text-center " for="stripe">
                                             <img class="mb-3" height="50"
                                             <img class="mb-3" height="50"
                                                 src="{{ url('/images/stripe_logo.png') }}" /></br>
                                                 src="{{ url('/images/stripe_logo.png') }}" /></br>

+ 31 - 19
routes/web.php

@@ -1,8 +1,10 @@
 <?php
 <?php
 
 
+use App\Classes\Settings\Misc;
+use App\Classes\Settings\Payments;
 use App\Http\Controllers\Admin\ActivityLogController;
 use App\Http\Controllers\Admin\ActivityLogController;
 use App\Http\Controllers\Admin\ApplicationApiController;
 use App\Http\Controllers\Admin\ApplicationApiController;
-use App\Http\Controllers\Admin\ConfigurationController;
+use App\Http\Controllers\Admin\InvoiceController;
 use App\Http\Controllers\Admin\OverViewController;
 use App\Http\Controllers\Admin\OverViewController;
 use App\Http\Controllers\Admin\PaymentController;
 use App\Http\Controllers\Admin\PaymentController;
 use App\Http\Controllers\Admin\CreditProductController;
 use App\Http\Controllers\Admin\CreditProductController;
@@ -23,6 +25,9 @@ use App\Http\Controllers\TranslationController;
 use Illuminate\Http\Request;
 use Illuminate\Http\Request;
 use Illuminate\Support\Facades\Auth;
 use Illuminate\Support\Facades\Auth;
 use Illuminate\Support\Facades\Route;
 use Illuminate\Support\Facades\Route;
+use App\Classes\Settings\Language;
+use App\Classes\Settings\Invoices;
+use App\Classes\Settings\System;
 
 
 /*
 /*
 |--------------------------------------------------------------------------
 |--------------------------------------------------------------------------
@@ -72,8 +77,6 @@ Route::middleware(['auth', 'checkSuspended'])->group(function () {
     Route::get('payment/StripeSuccess', [PaymentController::class, 'StripeSuccess'])->name('payment.StripeSuccess');
     Route::get('payment/StripeSuccess', [PaymentController::class, 'StripeSuccess'])->name('payment.StripeSuccess');
     Route::get('payment/Cancel', [PaymentController::class, 'Cancel'])->name('payment.Cancel');
     Route::get('payment/Cancel', [PaymentController::class, 'Cancel'])->name('payment.Cancel');
 
 
-
-
     Route::get('users/logbackin', [UserController::class, 'logBackIn'])->name('users.logbackin');
     Route::get('users/logbackin', [UserController::class, 'logBackIn'])->name('users.logbackin');
 
 
     #discord
     #discord
@@ -85,14 +88,18 @@ Route::middleware(['auth', 'checkSuspended'])->group(function () {
 
 
     #switch language
     #switch language
     Route::post('changelocale', [TranslationController::class, 'changeLocale'])->name('changeLocale');
     Route::post('changelocale', [TranslationController::class, 'changeLocale'])->name('changeLocale');
+
+
     #admin
     #admin
     Route::prefix('admin')->name('admin.')->middleware('admin')->group(function () {
     Route::prefix('admin')->name('admin.')->middleware('admin')->group(function () {
 
 
+        #overview
         Route::get('overview', [OverViewController::class, 'index'])->name('overview.index');
         Route::get('overview', [OverViewController::class, 'index'])->name('overview.index');
         Route::get('overview/sync', [OverViewController::class, 'syncPterodactyl'])->name('overview.sync');
         Route::get('overview/sync', [OverViewController::class, 'syncPterodactyl'])->name('overview.sync');
 
 
         Route::resource('activitylogs', ActivityLogController::class);
         Route::resource('activitylogs', ActivityLogController::class);
 
 
+        #users
         Route::get("users.json", [UserController::class, "json"])->name('users.json');
         Route::get("users.json", [UserController::class, "json"])->name('users.json');
         Route::get('users/loginas/{user}', [UserController::class, 'loginAs'])->name('users.loginas');
         Route::get('users/loginas/{user}', [UserController::class, 'loginAs'])->name('users.loginas');
         Route::get('users/datatable', [UserController::class, 'datatable'])->name('users.datatable');
         Route::get('users/datatable', [UserController::class, 'datatable'])->name('users.datatable');
@@ -101,50 +108,55 @@ Route::middleware(['auth', 'checkSuspended'])->group(function () {
         Route::post('users/togglesuspend/{user}', [UserController::class, 'toggleSuspended'])->name('users.togglesuspend');
         Route::post('users/togglesuspend/{user}', [UserController::class, 'toggleSuspended'])->name('users.togglesuspend');
         Route::resource('users', UserController::class);
         Route::resource('users', UserController::class);
 
 
+        #servers
         Route::get('servers/datatable', [AdminServerController::class, 'datatable'])->name('servers.datatable');
         Route::get('servers/datatable', [AdminServerController::class, 'datatable'])->name('servers.datatable');
         Route::post('servers/togglesuspend/{server}', [AdminServerController::class, 'toggleSuspended'])->name('servers.togglesuspend');
         Route::post('servers/togglesuspend/{server}', [AdminServerController::class, 'toggleSuspended'])->name('servers.togglesuspend');
         Route::resource('servers', AdminServerController::class);
         Route::resource('servers', AdminServerController::class);
 
 
+        #products
         Route::get('products/datatable', [ProductController::class, 'datatable'])->name('products.datatable');
         Route::get('products/datatable', [ProductController::class, 'datatable'])->name('products.datatable');
         Route::get('products/clone/{product}', [ProductController::class, 'clone'])->name('products.clone');
         Route::get('products/clone/{product}', [ProductController::class, 'clone'])->name('products.clone');
         Route::patch('products/disable/{product}', [ProductController::class, 'disable'])->name('products.disable');
         Route::patch('products/disable/{product}', [ProductController::class, 'disable'])->name('products.disable');
         Route::resource('products', ProductController::class);
         Route::resource('products', ProductController::class);
 
 
+        #store
         Route::get('store/datatable', [CreditProductController::class, 'datatable'])->name('store.datatable');
         Route::get('store/datatable', [CreditProductController::class, 'datatable'])->name('store.datatable');
         Route::patch('store/disable/{creditProduct}', [CreditProductController::class, 'disable'])->name('store.disable');
         Route::patch('store/disable/{creditProduct}', [CreditProductController::class, 'disable'])->name('store.disable');
         Route::resource('store', CreditProductController::class)->parameters([
         Route::resource('store', CreditProductController::class)->parameters([
             'store' => 'creditProduct',
             'store' => 'creditProduct',
         ]);
         ]);
 
 
+        #payments
         Route::get('payments/datatable', [PaymentController::class, 'datatable'])->name('payments.datatable');
         Route::get('payments/datatable', [PaymentController::class, 'datatable'])->name('payments.datatable');
         Route::get('payments', [PaymentController::class, 'index'])->name('payments.index');
         Route::get('payments', [PaymentController::class, 'index'])->name('payments.index');
 
 
-//        Route::get('nodes/datatable', [NodeController::class, 'datatable'])->name('nodes.datatable');
-//        Route::get('nodes/sync', [NodeController::class, 'sync'])->name('nodes.sync');
-//        Route::resource('nodes', NodeController::class);
-//
-//        Route::get('nests/datatable', [NestsController::class, 'datatable'])->name('nests.datatable');
-//        Route::get('nests/sync', [NestsController::class, 'sync'])->name('nests.sync');
-//        Route::resource('nests', NestsController::class);
-
-        Route::get('configurations/datatable', [ConfigurationController::class, 'datatable'])->name('configurations.datatable');
-        Route::patch('configurations/updatevalue', [ConfigurationController::class, 'updatevalue'])->name('configurations.updatevalue');
-        Route::resource('configurations', ConfigurationController::class);
-        Route::resource('configurations', ConfigurationController::class);
-
-        Route::patch('settings/update/icons', [SettingsController::class, 'updateIcons'])->name('settings.update.icons');
-        Route::patch('settings/update/invoice-settings', [SettingsController::class, 'updateInvoiceSettings'])->name('settings.update.invoicesettings');
-        Route::get('settings/download-invoices', [SettingsController::class, 'downloadAllInvoices'])->name('settings.downloadAllInvoices');;
+        #settings
+        Route::get('settings/datatable', [SettingsController::class, 'datatable'])->name('settings.datatable');
+        Route::patch('settings/updatevalue', [SettingsController::class, 'updatevalue'])->name('settings.updatevalue');
+
+        #settings
+        Route::patch('settings/update/invoice-settings', [Invoices::class, 'updateSettings'])->name('settings.update.invoicesettings');
+        Route::patch('settings/update/language', [Language::class, 'updateSettings'])->name('settings.update.languagesettings');
+        Route::patch('settings/update/payment', [Payments::class, 'updateSettings'])->name('settings.update.paymentsettings');
+        Route::patch('settings/update/misc', [Misc::class, 'updateSettings'])->name('settings.update.miscsettings');
+        Route::patch('settings/update/system', [System::class, 'updateSettings'])->name('settings.update.systemsettings');
         Route::resource('settings', SettingsController::class)->only('index');
         Route::resource('settings', SettingsController::class)->only('index');
 
 
+        #invoices
+        Route::get('invoices/download-invoices', [InvoiceController::class, 'downloadAllInvoices'])->name('invoices.downloadAllInvoices');;
+        Route::get('invoices/download-single-invoice', [InvoiceController::class, 'downloadSingleInvoice'])->name('invoices.downloadSingleInvoice');;
+
+        #usefullinks
         Route::get('usefullinks/datatable', [UsefulLinkController::class, 'datatable'])->name('usefullinks.datatable');
         Route::get('usefullinks/datatable', [UsefulLinkController::class, 'datatable'])->name('usefullinks.datatable');
         Route::resource('usefullinks', UsefulLinkController::class);
         Route::resource('usefullinks', UsefulLinkController::class);
 
 
+        #vouchers
         Route::get('vouchers/datatable', [VoucherController::class, 'datatable'])->name('vouchers.datatable');
         Route::get('vouchers/datatable', [VoucherController::class, 'datatable'])->name('vouchers.datatable');
         Route::get('vouchers/{voucher}/usersdatatable', [VoucherController::class, 'usersdatatable'])->name('vouchers.usersdatatable');
         Route::get('vouchers/{voucher}/usersdatatable', [VoucherController::class, 'usersdatatable'])->name('vouchers.usersdatatable');
         Route::get('vouchers/{voucher}/users', [VoucherController::class, 'users'])->name('vouchers.users');
         Route::get('vouchers/{voucher}/users', [VoucherController::class, 'users'])->name('vouchers.users');
         Route::resource('vouchers', VoucherController::class);
         Route::resource('vouchers', VoucherController::class);
 
 
+        #api-keys
         Route::get('api/datatable', [ApplicationApiController::class, 'datatable'])->name('api.datatable');
         Route::get('api/datatable', [ApplicationApiController::class, 'datatable'])->name('api.datatable');
         Route::resource('api', ApplicationApiController::class)->parameters([
         Route::resource('api', ApplicationApiController::class)->parameters([
             'api' => 'applicationApi',
             'api' => 'applicationApi',