Merge pull request #372 from ControlPanel-gg/settings_rewrite

Settings rewrite
This commit is contained in:
Dennis 2022-01-23 16:03:13 +01:00 committed by GitHub
commit 4ad5722e9c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
63 changed files with 2281 additions and 1402 deletions

View file

@ -8,18 +8,6 @@ APP_URL=http://localhost
APP_TIMEZONE=UTC
### --- 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_CONNECTION=mysql
DB_HOST=127.0.0.1
@ -29,42 +17,6 @@ DB_USERNAME=dashboarduser
DB_PASSWORD=
### --- 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)
RECAPTCHA_SITE_KEY=6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI

View file

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

View file

@ -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!'));
}
}

View file

@ -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!'));
}
}

View file

@ -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!'));
}
}

View file

@ -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!'));
}
}

View file

@ -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!'));
}
}

View file

@ -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();
}
}

View file

@ -3,6 +3,7 @@
namespace App\Http\Controllers\Admin;
use App\Models\CreditProduct;
use App\Models\Settings;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory;
use Illuminate\Contracts\View\View;
@ -25,8 +26,8 @@ class CreditProductController extends Controller
if (
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;
return view('admin.store.index', [

View file

@ -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);
}
}

View file

@ -4,10 +4,10 @@ namespace App\Http\Controllers\Admin;
use App\Events\UserUpdateCreditsEvent;
use App\Http\Controllers\Controller;
use App\Models\Configuration;
use App\Models\InvoiceSettings;
use App\Models\Payment;
use App\Models\CreditProduct;
use App\Models\Settings;
use App\Models\User;
use App\Notifications\InvoiceNotification;
use App\Notifications\ConfirmPaymentNotification;
@ -134,7 +134,7 @@ class PaymentController extends Controller
*/
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()
{
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);
//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));
$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
return redirect()->route('home')->with('success', __('Your credit balance has been increased!'));
@ -266,7 +270,7 @@ class PaymentController extends Controller
],
'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}',
'cancel_url' => route('payment.Cancel'),
]);
@ -304,9 +308,9 @@ class PaymentController extends Controller
$user->increment('credits', $creditProduct->quantity);
//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));
$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
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,
]);
$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
return redirect()->route('home')->with('success', __('Your payment is being processed!'));
@ -398,9 +408,9 @@ class PaymentController extends Controller
$user->increment('credits', $payment->amount);
//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));
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) {
abort(422);
@ -474,8 +487,8 @@ class PaymentController extends Controller
protected function getStripeSecret()
{
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()
{
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
$lastInvoiceID = \App\Models\Invoice::where("invoice_name", "like", "%" . now()->format('mY') . "%")->count("id");
$newInvoiceID = $lastInvoiceID + 1;
$InvoiceSettings = InvoiceSettings::query()->first();
$logoPath = storage_path('app/public/logo.png');
$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' => [
'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'))
->delimiter("-")
->sequence($newInvoiceID)
->serialNumberFormat($InvoiceSettings->invoice_prefix . '{DELIMITER}{SERIES}{SEQUENCE}')
->serialNumberFormat(Settings::getValueByKey("SETTINGS::INVOICE:PREFIX") . '{DELIMITER}{SERIES}{SEQUENCE}')
->notes($notes);
if (file_exists($logoPath)) {
@ -591,6 +603,11 @@ class PaymentController extends Controller
->editColumn('created_at', function (Payment $payment) {
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);
}
}

View file

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

View file

@ -6,6 +6,7 @@ use App\Classes\Pterodactyl;
use App\Classes\PterodactylWrapper;
use App\Http\Controllers\Controller;
use App\Models\Server;
use App\Models\Settings;
use Exception;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory;
@ -161,7 +162,7 @@ class ServerController extends Controller
return $server->suspended ? $server->suspended->diffForHumans() : '';
})
->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'])
->make();

View file

@ -3,13 +3,12 @@
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\InvoiceSettings;
use App\Models\Settings;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory;
use Illuminate\Contracts\View\View;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use ZipArchive;
class SettingsController extends Controller
{
@ -20,81 +19,68 @@ class SettingsController extends Controller
*/
public function index()
{
/** @var InvoiceSettings $invoiceSettings */
$invoiceSettings = InvoiceSettings::first();
//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');
}
return view('admin.settings.index', $invoiceSettings->toArray());
//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 view('admin.settings.index', [
'tabs' => $tabs,
'tabListItems' => $tabListItems,
]);
}
public function updateIcons(Request $request)
public function updatevalue(Request $request)
{
$setting = Settings::findOrFail($request->input('key'));
$request->validate([
'icon' => 'nullable|max:10000|mimes:jpg,png,jpeg',
'favicon' => 'nullable|max:10000|mimes:ico',
'key' => 'required|string|max:191',
'value' => 'required|string|max:191',
]);
if ($request->hasFile('icon')) {
$request->file('icon')->storeAs('public', 'icon.png');
}
$setting->update($request->all());
if ($request->hasFile('favicon')) {
$request->file('favicon')->storeAs('public', 'favicon.ico');
}
return redirect()->route('admin.settings.index')->with('success', __('Icons updated!'));
return redirect()->route('admin.settings.index')->with('success', __('configuration has been updated!'));
}
public function updateInvoiceSettings(Request $request)
/**
* Remove the specified resource from storage.
*
* @param Settings $setting
* @return Response
*/
public function destroy(Settings $setting)
{
$request->validate([
'logo' => 'nullable|max:10000|mimes:jpg,png,jpeg',
]);
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'),
]);
if ($request->hasFile('logo')) {
$request->file('logo')->storeAs('public', 'logo.png');
}
return redirect()->route('admin.settings.index')->with('success', 'Invoice settings updated!');
//
}
public function downloadAllInvoices()
public function datatable()
{
$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);
}
$query = Settings::where('key', 'like', '%SYSTEM%')
->orWhere('key', 'like', '%USER%')
->orWhere('key', 'like', '%SERVER%');
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;
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();
}
}

View file

@ -5,6 +5,7 @@ namespace App\Http\Controllers\Admin;
use App\Classes\Pterodactyl;
use App\Events\UserUpdateCreditsEvent;
use App\Http\Controllers\Controller;
use App\Models\Settings;
use App\Models\User;
use App\Notifications\DynamicNotification;
use Spatie\QueryBuilder\QueryBuilder;
@ -300,7 +301,7 @@ class UserController extends Controller
return '<span class="badge ' . $badgeColor . '">' . $user->role . '</span>';
})
->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) {
$query->orderBy('last_seen', $order);

View file

@ -5,8 +5,8 @@ namespace App\Http\Controllers\Api;
use App\Classes\Pterodactyl;
use App\Events\UserUpdateCreditsEvent;
use App\Http\Controllers\Controller;
use App\Models\Configuration;
use App\Models\DiscordUser;
use App\Models\Settings;
use App\Models\User;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
@ -242,8 +242,8 @@ class UserController extends Controller
$user = User::create([
'name' => $request->input('name'),
'email' => $request->input('email'),
'credits' => Configuration::getValueByKey('INITIAL_CREDITS', 150),
'server_limit' => Configuration::getValueByKey('INITIAL_SERVER_LIMIT', 1),
'credits' => Settings::getValueByKey('SETTINGS::USER:INITIAL_CREDITS', 150),
'server_limit' => Settings::getValueByKey('SETTINGS::USER:INITIAL_SERVER_LIMIT', 1),
'password' => Hash::make($request->input('password')),
]);

View file

@ -41,17 +41,25 @@ class LoginController extends Controller
public function login(Request $request)
{
$request->validate([
$validationRules = [
$this->username() => '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
// 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.
if (method_exists($this, 'hasTooManyLoginAttempts') &&
$this->hasTooManyLoginAttempts($request)) {
if (
method_exists($this, 'hasTooManyLoginAttempts') &&
$this->hasTooManyLoginAttempts($request)
) {
$this->fireLockoutEvent($request);
return $this->sendLockoutResponse($request);

View file

@ -4,7 +4,7 @@ namespace App\Http\Controllers\Auth;
use App\Classes\Pterodactyl;
use App\Http\Controllers\Controller;
use App\Models\Configuration;
use App\Models\Settings;
use App\Models\User;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\RegistersUsers;
@ -54,30 +54,28 @@ class RegisterController extends Controller
*/
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
$data['ip'] = session()->get('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([
'name' => $data['name'],
'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']),
]);

View file

@ -3,8 +3,8 @@
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Models\Configuration;
use App\Models\DiscordUser;
use App\Models\Settings;
use App\Models\User;
use App\Models\Voucher;
use Illuminate\Support\Facades\Auth;
@ -15,7 +15,7 @@ class SocialiteController extends Controller
{
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')
->scopes($scopes)
@ -31,17 +31,17 @@ class SocialiteController extends Controller
/** @var User $user */
$user = Auth::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
if (is_null($user->discordUser)) {
//create discord user in db
DiscordUser::create(array_merge($discord->user, ['user_id' => Auth::user()->id]));
//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()]);
} else {
$user->discordUser->update($discord->user);

View file

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

View file

@ -2,14 +2,11 @@
namespace App\Http\Controllers;
use App\Classes\Pterodactyl;
use App\Models\Configuration;
use App\Models\User;
use Illuminate\Contracts\View\Factory;
use Illuminate\Contracts\View\View;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\ValidationException;
@ -21,9 +18,9 @@ class ProfileController extends Controller
{
return view('profile.index')->with([
'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);
//update password if necessary
if (!is_null($request->input('new_password'))){
if (!is_null($request->input('new_password'))) {
//validate password request
$request->validate([
'current_password' => [
'required' ,
'required',
function ($attribute, $value, $fail) use ($user) {
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
$request->validate([
'name' => 'required|min:4|max:30|alpha_num|unique:users,name,'.$id.',id',
'email' => 'required|email|max:64|unique:users,email,'.$id.',id',
'name' => 'required|min:4|max:30|alpha_num|unique:users,name,' . $id . ',id',
'email' => 'required|email|max:64|unique:users,email,' . $id . ',id',
'avatar' => 'nullable'
]);
//update avatar
if(!is_null($request->input('avatar'))){
if (!is_null($request->input('avatar'))) {
$avatar = json_decode($request->input('avatar'));
if ($avatar->input->size > 3000000) abort(500);
@ -121,6 +118,6 @@ class ProfileController extends Controller
]);
$user->sendEmailVerificationNotification();
return redirect()->route('profile.index')->with('success' , __('Profile updated'));
return redirect()->route('profile.index')->with('success', __('Profile updated'));
}
}

View file

@ -3,13 +3,13 @@
namespace App\Http\Controllers;
use App\Classes\Pterodactyl;
use App\Models\Configuration;
use App\Models\Egg;
use App\Models\Location;
use App\Models\Nest;
use App\Models\Node;
use App\Models\Product;
use App\Models\Server;
use App\Models\Settings;
use App\Notifications\ServerCreationError;
use Exception;
use Illuminate\Database\Eloquent\Builder;
@ -107,7 +107,7 @@ class ServerController extends Controller
if (
Auth::user()->credits <
($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)
) {
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
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."));
}
//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."));
}
@ -168,7 +168,7 @@ class ServerController extends Controller
'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()) {
$request->user()->decrement('credits', $server->product->getHourlyPrice());
}

View file

@ -2,8 +2,8 @@
namespace App\Http\Controllers;
use App\Models\Configuration;
use App\Models\CreditProduct;
use App\Models\Settings;
use Illuminate\Support\Facades\Auth;
class StoreController extends Controller
@ -15,17 +15,17 @@ class StoreController extends Controller
if (
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;
//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."));
}
//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"));
}

View file

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

View file

@ -3,6 +3,7 @@
namespace App\Http\Middleware;
use App\Models\Configuration;
use App\Models\Settings;
use Closure;
use Illuminate\Http\Request;
@ -17,10 +18,10 @@ class GlobalNames
*/
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 = array_map( 'strtolower', $unsupported_lang_array );
$unsupported_lang_array = array_map('strtolower', $unsupported_lang_array);
define('UNSUPPORTED_LANGS', $unsupported_lang_array);
return $next($request);

View file

@ -2,6 +2,7 @@
namespace App\Http\Middleware;
use App\Models\Settings;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
@ -9,194 +10,6 @@ use Illuminate\Support\Facades\Session;
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)
{
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 {
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);
return $next($request);

View file

@ -3,11 +3,10 @@
namespace App\Listeners;
use App\Events\UserUpdateCreditsEvent;
use App\Models\Configuration;
use App\Models\Server;
use App\Models\Settings;
use Exception;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
class UnsuspendServers implements ShouldQueue
{
@ -20,7 +19,7 @@ class UnsuspendServers implements ShouldQueue
*/
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 */
foreach ($event->user->servers as $server){
if ($server->isSuspended()) $server->unSuspend();

View file

@ -2,9 +2,7 @@
namespace App\Listeners;
use App\Models\Configuration;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use App\Models\Settings;
class Verified
{
@ -26,7 +24,7 @@ class Verified
*/
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'));
}
}

View file

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

View file

@ -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'
];
}

View file

@ -6,11 +6,13 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache;
class Configuration extends Model
class Settings extends Model
{
use HasFactory;
public const CACHE_TAG = 'configuration';
protected $table = 'settings';
public const CACHE_TAG = 'setting';
public $primaryKey = 'key';
@ -28,8 +30,8 @@ class Configuration extends Model
{
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)
{
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;
});
}
}

View file

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

View file

@ -2,7 +2,7 @@
namespace App\Notifications;
use App\Models\Configuration;
use App\Models\Settings;
use App\Models\User;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
@ -38,25 +38,25 @@ class WelcomeMessage extends Notification implements ShouldQueue
return ['database'];
}
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.
*
@ -72,7 +72,7 @@ class WelcomeMessage extends Notification implements ShouldQueue
<h5>Verification</h5>
<p>You can verify your e-mail address and link/verify your Discord account.</p>
<p>
".$this->AdditionalLines()."
" . $this->AdditionalLines() . "
</p>
<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>

View file

@ -2,11 +2,13 @@
namespace App\Providers;
use App\Models\Settings;
use Illuminate\Pagination\Paginator;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\ServiceProvider;
use Spatie\QueryBuilder\QueryBuilderRequest;
class AppServiceProvider extends ServiceProvider
{
@ -31,14 +33,11 @@ class AppServiceProvider extends ServiceProvider
Schema::defaultStringLength(191);
Validator::extend('multiple_date_format', function ($attribute, $value, $parameters, $validator) {
$ok = true;
$result = [];
// iterate through all formats
foreach ($parameters as $parameter) {
//validate with laravels standard date format validation
$result[] = $validator->validateDateFormat($attribute, $value, [$parameter]);
}
@ -51,5 +50,59 @@ class AppServiceProvider extends ServiceProvider
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')]);
}
}

View file

@ -1,5 +1,7 @@
<?php
use App\Models\Settings;
return [
'version' => '0.6.2',
@ -70,16 +72,6 @@ return [
'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'),
'locale' =>"en",
/*
|--------------------------------------------------------------------------
| Available Locales
| Available Languages
|--------------------------------------------------------------------------
|
| 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'),
/*
|--------------------------------------------------------------------------
| Unsupported Locales
|--------------------------------------------------------------------------
|
| Locales the Owner of the Dashboard does not want to support
|
| 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.
|
*/
'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/
|
*/
'datatable_locale' => env('DATATABLE_LOCALE', 'en-gb'),
'available_locales' =>["en","cs","de","es","fr","hi","it","pl","zh"],
/*
|--------------------------------------------------------------------------

View file

@ -45,31 +45,22 @@ return [
'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',
// ],
],
/*

View file

@ -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');
}
}

View file

@ -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');
}
}

View file

@ -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']);
}
}

View file

@ -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();
});
}
}

View file

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

View file

@ -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'
]);
}
}

View file

@ -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'
]);
}
}

2
package-lock.json generated
View file

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View file

@ -68,7 +68,7 @@
"User ID": "User-ID",
"Server Creation Error": "Fehler beim erstellen des Servers",
"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",
"If you have any questions please let us know.": "Solltest du weiter fragen haben, melde dich gerne beim Support!",
"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.",
"Max": "Max",
"Expires at": "Läuft ab am",
"Used \/ Uses": "Benutzungen",
"Used / Uses": "Benutzungen",
"Expires": "Ablauf",
"Sign in to start your session": "Melde dich an um das Dashboard zu benutzen",
"Password": "Passwort",
@ -287,7 +287,7 @@
"No nodes have been linked!": "Es wurde keine Nodes verknüpft",
"No nests available!": "Keine Nests verfügbar",
"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",
"---": "---",
"Specification ": "Spezifikation",
@ -350,5 +350,14 @@
"Notes": "Notizen",
"Amount in words": "Betrag in Worten",
"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"
}

View file

@ -4,11 +4,12 @@
"api key has been removed!": "api key has been removed!",
"Edit": "Edit",
"Delete": "Delete",
"configuration has been updated!": "configuration has been updated!",
"Store item has been created!": "Store item has been created!",
"Store item has been updated!": "Store item has been updated!",
"Product has been updated!": "Product has been updated!",
"Store item has been removed!": "Store item has been removed!",
"Created at": "Created at",
"Error!": "Error!",
"unknown": "unknown",
"Pterodactyl synced": "Pterodactyl synced",
"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!",
"Payment method": "Payment method",
"Invoice": "Invoice",
"Download": "Download",
"Product has been created!": "Product has been created!",
"Product has been removed!": "Product has been removed!",
"Show": "Show",
@ -26,6 +28,7 @@
"Unsuspend": "Unsuspend",
"Suspend": "Suspend",
"Icons updated!": "Icons updated!",
"configuration has been updated!": "configuration has been updated!",
"link has been created!": "link has been created!",
"link has been updated!": "link has been updated!",
"product has been removed!": "product has been removed!",
@ -80,7 +83,6 @@
"Check the docs for it here": "Check the docs for it here",
"Causer": "Causer",
"Description": "Description",
"Created at": "Created at",
"Application API": "Application API",
"Create": "Create",
"Memo": "Memo",
@ -89,13 +91,6 @@
"Token": "Token",
"Last used": "Last used",
"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",
"Sync": "Sync",
"Active": "Active",
@ -118,6 +113,7 @@
"Locations": "Locations",
"Eggs": "Eggs",
"Last updated :date": "Last updated :date",
"Download all Invoices": "Download all Invoices",
"Product Price": "Product Price",
"Tax Value": "Tax Value",
"Tax Percentage": "Tax Percentage",
@ -151,11 +147,15 @@
"Config": "Config",
"Suspended at": "Suspended at",
"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 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 address": "Enter your companys address",
"Enter your companys phone number": "Enter your companys phone number",
@ -165,6 +165,15 @@
"Enter your custom invoice prefix": "Enter your custom invoice prefix",
"Logo": "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",
"Currency code": "Currency 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",
"Out of Credits in": "Out of Credits in",
"Home": "Home",
"Languages": "Languages",
"Language": "Language",
"See all Notifications": "See all Notifications",
"Redeem code": "Redeem code",
"Profile": "Profile",
@ -280,7 +289,6 @@
"Re-Sync Discord": "Re-Sync Discord",
"Save Changes": "Save Changes",
"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.",
"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!",
@ -321,9 +329,6 @@
"Canceled ...": "Canceled ...",
"Deletion has been canceled.": "Deletion has been canceled.",
"Date": "Date",
"To": "To",
"From": "From",
"Pending": "Pending",
"Subtotal": "Subtotal",
"Payment Methods": "Payment Methods",
"Amount Due": "Amount Due",
@ -350,5 +355,13 @@
"Notes": "Notes",
"Amount in words": "Amount in words",
"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"
}

View file

@ -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>

View file

@ -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

View file

@ -27,6 +27,10 @@
<div class="card">
<div class="card-header">
<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 class="card-body table-responsive">
@ -43,6 +47,7 @@
<th>{{ __('Payment ID') }}</th>
<th>{{ __('Payment Method') }}</th>
<th>{{ __('Created at') }}</th>
<th></th>
</tr>
</thead>
<tbody>
@ -78,6 +83,7 @@
{data: 'payment_id'},
{data: 'payment_method'},
{data: 'created_at'},
{data: 'actions' , sortable : false},
],
fnDrawCallback: function(oSettings) {
$('[data-toggle="popover"]').popover();

View file

@ -6,13 +6,13 @@
<div class="container-fluid">
<div class="row mb-2">
<div class="col-sm-6">
<h1>{{__('Settings')}}</h1>
<h1>{{ __('Settings') }}</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 href="{{ route('home') }}">{{ __('Dashboard') }}</a></li>
<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>
</div>
</div>
@ -28,7 +28,7 @@
<div class="card-header">
<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>
@ -36,169 +36,18 @@
<!-- Nav pills -->
<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>
<!-- Tab panes -->
<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>
@ -218,12 +67,25 @@
<script>
// Add the following code if you want the name of the file appear on select
document.addEventListener('DOMContentLoaded', () => {
$(".custom-file-input").on("change", function () {
$(".custom-file-input").on("change", function() {
var fileName = $(this).val().split("\\").pop();
$(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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -1,5 +1,6 @@
<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
@ -8,7 +9,9 @@
<meta name="csrf-token" content="{{ csrf_token() }}">
<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 -->
<script src="{{ asset('js/app.js') }}" defer></script>
@ -17,27 +20,32 @@
<link rel="dns-prefetch" href="//fonts.gstatic.com">
<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>
@yield('content')
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@10.14.1/dist/sweetalert2.all.min.js"></script>
<script>
@if(Session::has('error'))
Swal.fire({
@if (Session::has('error'))
Swal.fire({
icon: 'error',
title: 'Oops...',
html: '{{Session::get('error')}}',
})
html: '{{ Session::get('error') }}',
})
@endif
@if(Session::has('success'))
Swal.fire({
@if (Session::has('success'))
Swal.fire({
icon: 'success',
title: '{{Session::get('success')}}',
title: '{{ Session::get('success') }}',
position: 'top-end',
showConfirmButton: false,
background : '#343a40',
@ -45,10 +53,11 @@
timer: 3000,
timerProgressBar: true,
didOpen: (toast) => {
toast.addEventListener('mouseenter', Swal.stopTimer)
toast.addEventListener('mouseleave', Swal.resumeTimer)
toast.addEventListener('mouseenter', Swal.stopTimer)
toast.addEventListener('mouseleave', Swal.resumeTimer)
}
})
})
@endif
</script>
</html>

View file

@ -32,6 +32,7 @@
<noscript>
<link rel="stylesheet" href="{{ asset('plugins/fontawesome-free/css/all.min.css') }}">
</noscript>
<script src="{{ asset('js/app.js') }}"></script>
</head>
<body class="sidebar-mini layout-fixed dark-mode" style="height: auto;">
@ -53,7 +54,6 @@
<!-- Select2 -->
<script src={{ asset('plugins/select2/js/select2.min.js') }}></script>
<div class="wrapper">
<!-- Navbar -->
<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>
</li>
<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>
</li>
<!-- 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>
@endif
@endforeach
@endforeach
</form>
</div>
</li>
<!-- End Language Selection -->
</form>
</div>
</li>
<!-- End Language Selection -->
@endif
</ul>
<!-- Right navbar links -->
@ -230,7 +230,7 @@
</a>
</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">
<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>
@ -251,13 +251,6 @@
</a>
</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">
<a href="{{ route('admin.settings.index') }}"
@ -300,8 +293,7 @@
</li>
<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>
<p>{{ __('Store') }}</p>
</a>
@ -411,6 +403,27 @@
</div>
<!-- ./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>
$(document).ready(function() {
$('[data-toggle="popover"]').popover();
@ -430,7 +443,6 @@
html: '{{ Session::get('error') }}',
})
@endif
@if (Session::has('success'))
Swal.fire({
icon: 'success',

View file

@ -6,13 +6,13 @@
<div class="container-fluid">
<div class="row mb-2">
<div class="col-sm-6">
<h1>{{__('Profile')}}</h1>
<h1>{{ __('Profile') }}</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 href="{{ route('home') }}">{{ __('Dashboard') }}</a></li>
<li class="breadcrumb-item"><a class="text-muted"
href="{{route('profile.index')}}">{{__('Profile')}}</a>
href="{{ route('profile.index') }}">{{ __('Profile') }}</a>
</li>
</ol>
</div>
@ -27,36 +27,35 @@
<div class="row">
<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">
<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>
{{__('You have not yet verified your email address')}}
{{ __('You have not yet verified your email address') }}
<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>
{{__('Please contact support If you didnt receive your verification email.')}}
{{ __('Please contact support If you didnt receive your verification email.') }}
</div>
@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">
<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>
{{__('You have not yet verified your discord account')}}
{{ __('You have not yet verified your discord account') }}
<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>
@else
<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>
{{__('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>
@endif
@endif
@ -64,7 +63,7 @@
</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
@method('PATCH')
<div class="card">
@ -73,43 +72,42 @@
<div class="row">
<div class="col-12 col-sm-auto mb-4">
<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 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"
class="text-success fas fa-check-circle"></i>
class="text-success fas fa-check-circle"></i>
@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
</p>
<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 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>
<ul class="nav nav-tabs">
<li class="nav-item"><a href="javasript:void(0)"
class="active nav-link">{{__('Settings')}}</a>
class="active nav-link">{{ __('Settings') }}</a>
</li>
</ul>
<div class="tab-content pt-3">
@ -134,29 +132,28 @@
@endif
<div class="form-group"><label>{{__('Name')}}</label> <input
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')
<div class="invalid-feedback">
{{$message}}
</div>
<div class="invalid-feedback">
{{ $message }}
</div>
@enderror
</div>
</div>
</div>
<div class="row">
<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"
type="text"
placeholder="{{$user->email}}" name="email"
value="{{$user->email}}">
type="text" placeholder="{{ $user->email }}" name="email"
value="{{ $user->email }}">
@error('email')
<div class="invalid-feedback">
{{$message}}
</div>
<div class="invalid-feedback">
{{ $message }}
</div>
@enderror
</div>
</div>
@ -165,33 +162,34 @@
</div>
<div class="row">
<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="col">
<div class="form-group"><label>{{__('Current Password')}}</label>
<div class="form-group">
<label>{{ __('Current Password') }}</label>
<input
class="form-control @error('current_password') is-invalid @enderror"
name="current_password" type="password"
placeholder="••••••">
name="current_password" type="password" placeholder="••••••">
@error('current_password')
<div class="invalid-feedback">
{{$message}}
</div>
<div class="invalid-feedback">
{{ $message }}
</div>
@enderror
</div>
</div>
</div>
<div class="row">
<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"
name="new_password" type="password" placeholder="••••••">
@error('new_password')
<div class="invalid-feedback">
{{$message}}
</div>
<div class="invalid-feedback">
{{ $message }}
</div>
@enderror
</div>
</div>
@ -199,60 +197,62 @@
<div class="row">
<div class="col">
<div class="form-group">
<label>{{__('Confirm Password')}}</span></label>
<label>{{ __('Confirm Password') }}</span></label>
<input
class="form-control @error('new_password_confirmation') is-invalid @enderror"
name="new_password_confirmation" type="password"
placeholder="••••••">
@error('new_password_confirmation')
<div class="invalid-feedback">
{{$message}}
</div>
<div class="invalid-feedback">
{{ $message }}
</div>
@enderror
</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">
@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="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>
@endif
</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>
@else
<div class="verified-discord">
<div class="my-3 callout callout-info">
<p>{{__('You are verified!')}}</p>
<p>{{ __('You are verified!') }}</p>
</div>
</div>
<div class="row pl-2">
<div class="small-box bg-dark">
<div class="d-flex justify-content-between">
<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>
</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 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>
</div>
</div>
@ -265,7 +265,7 @@
<div class="row">
<div class="col d-flex justify-content-end">
<button class="btn btn-primary"
type="submit">{{__('Save Changes')}}</button>
type="submit">{{ __('Save Changes') }}</button>
</div>
</div>

View file

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

View file

@ -55,8 +55,8 @@
</a>
<div class="dropdown-menu dropdown-menu-right shadow animated--fade-in"
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="fas fa-database mr-2"></i><span>{{ __('Database') }}</span></a>
@endif
@ -149,7 +149,7 @@
</div>
<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"
class="btn btn-info mx-3 w-100 align-items-center justify-content-center d-flex">
<i class="fas fa-tools mr-2"></i>

View file

@ -78,7 +78,7 @@
<p class="lead">{{ __('Payment Methods') }}:</p>
<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">
<img class="mb-3" height="50"
src="{{ url('/images/paypal_logo.png') }}"></br>
@ -88,7 +88,7 @@
</input>
</label>
@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">
<img class="mb-3" height="50"
src="{{ url('/images/stripe_logo.png') }}" /></br>

View file

@ -1,8 +1,10 @@
<?php
use App\Classes\Settings\Misc;
use App\Classes\Settings\Payments;
use App\Http\Controllers\Admin\ActivityLogController;
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\PaymentController;
use App\Http\Controllers\Admin\CreditProductController;
@ -23,6 +25,9 @@ use App\Http\Controllers\TranslationController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
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/Cancel', [PaymentController::class, 'Cancel'])->name('payment.Cancel');
Route::get('users/logbackin', [UserController::class, 'logBackIn'])->name('users.logbackin');
#discord
@ -85,14 +88,18 @@ Route::middleware(['auth', 'checkSuspended'])->group(function () {
#switch language
Route::post('changelocale', [TranslationController::class, 'changeLocale'])->name('changeLocale');
#admin
Route::prefix('admin')->name('admin.')->middleware('admin')->group(function () {
#overview
Route::get('overview', [OverViewController::class, 'index'])->name('overview.index');
Route::get('overview/sync', [OverViewController::class, 'syncPterodactyl'])->name('overview.sync');
Route::resource('activitylogs', ActivityLogController::class);
#users
Route::get("users.json", [UserController::class, "json"])->name('users.json');
Route::get('users/loginas/{user}', [UserController::class, 'loginAs'])->name('users.loginas');
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::resource('users', UserController::class);
#servers
Route::get('servers/datatable', [AdminServerController::class, 'datatable'])->name('servers.datatable');
Route::post('servers/togglesuspend/{server}', [AdminServerController::class, 'toggleSuspended'])->name('servers.togglesuspend');
Route::resource('servers', AdminServerController::class);
#products
Route::get('products/datatable', [ProductController::class, 'datatable'])->name('products.datatable');
Route::get('products/clone/{product}', [ProductController::class, 'clone'])->name('products.clone');
Route::patch('products/disable/{product}', [ProductController::class, 'disable'])->name('products.disable');
Route::resource('products', ProductController::class);
#store
Route::get('store/datatable', [CreditProductController::class, 'datatable'])->name('store.datatable');
Route::patch('store/disable/{creditProduct}', [CreditProductController::class, 'disable'])->name('store.disable');
Route::resource('store', CreditProductController::class)->parameters([
'store' => 'creditProduct',
]);
#payments
Route::get('payments/datatable', [PaymentController::class, 'datatable'])->name('payments.datatable');
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);
#settings
Route::get('settings/datatable', [SettingsController::class, 'datatable'])->name('settings.datatable');
Route::patch('settings/updatevalue', [SettingsController::class, 'updatevalue'])->name('settings.updatevalue');
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::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');
#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::resource('usefullinks', UsefulLinkController::class);
#vouchers
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}/users', [VoucherController::class, 'users'])->name('vouchers.users');
Route::resource('vouchers', VoucherController::class);
#api-keys
Route::get('api/datatable', [ApplicationApiController::class, 'datatable'])->name('api.datatable');
Route::resource('api', ApplicationApiController::class)->parameters([
'api' => 'applicationApi',