Revert "Merge branch 'development' into main"

This reverts commit 3810b487cd, reversing
changes made to d9a41840ce.
This commit is contained in:
1day2die 2023-04-25 09:22:30 +02:00
parent 3810b487cd
commit 0c067e26c8
171 changed files with 5028 additions and 7477 deletions

View file

@ -62,6 +62,3 @@ PUSHER_APP_CLUSTER=mt1
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}" MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
# Settings Cache
SETTINGS_CACHE_ENABLED=true

View file

@ -2,68 +2,46 @@
namespace App\Classes; namespace App\Classes;
use App\Models\Pterodactyl\Egg; use App\Models\Egg;
use App\Models\Pterodactyl\Nest; use App\Models\Nest;
use App\Models\Pterodactyl\Node; use App\Models\Node;
use App\Models\Product; use App\Models\Product;
use App\Models\Server; use App\Models\Server;
use App\Models\User;
use Exception; use Exception;
use Illuminate\Http\Client\PendingRequest; use Illuminate\Http\Client\PendingRequest;
use Illuminate\Http\Client\Response; use Illuminate\Http\Client\Response;
use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Http;
use App\Settings\PterodactylSettings;
use App\Settings\ServerSettings;
class PterodactylClient class Pterodactyl
{ {
//TODO: Extend error handling (maybe logger for more errors when debugging) //TODO: Extend error handling (maybe logger for more errors when debugging)
private int $per_page_limit = 200;
private int $allocation_limit = 200;
public PendingRequest $client;
public PendingRequest $application;
public function __construct(PterodactylSettings $ptero_settings)
{
$server_settings = new ServerSettings();
try {
$this->client = $this->client($ptero_settings);
$this->application = $this->clientAdmin($ptero_settings);
$this->per_page_limit = $ptero_settings->per_page_limit;
$this->allocation_limit = $server_settings->allocation_limit;
} catch (Exception $exception) {
logger('Failed to construct Pterodactyl client, Settings table not available?', ['exception' => $exception]);
}
}
/** /**
* @return PendingRequest * @return PendingRequest
*/ */
public function client(PterodactylSettings $ptero_settings) public static function client()
{ {
return Http::withHeaders([ return Http::withHeaders([
'Authorization' => 'Bearer ' . $ptero_settings->user_token, 'Authorization' => 'Bearer ' . config('SETTINGS::SYSTEM:PTERODACTYL:TOKEN'),
'Content-type' => 'application/json', 'Content-type' => 'application/json',
'Accept' => 'Application/vnd.pterodactyl.v1+json', 'Accept' => 'Application/vnd.pterodactyl.v1+json',
])->baseUrl($ptero_settings->getUrl() . 'api' . '/'); ])->baseUrl(config('SETTINGS::SYSTEM:PTERODACTYL:URL') . '/api');
} }
public function clientAdmin(PterodactylSettings $ptero_settings) public static function clientAdmin()
{ {
return Http::withHeaders([ return Http::withHeaders([
'Authorization' => 'Bearer ' . $ptero_settings->admin_token, 'Authorization' => 'Bearer ' . config('SETTINGS::SYSTEM:PTERODACTYL:ADMIN_USER_TOKEN'),
'Content-type' => 'application/json', 'Content-type' => 'application/json',
'Accept' => 'Application/vnd.pterodactyl.v1+json', 'Accept' => 'Application/vnd.pterodactyl.v1+json',
])->baseUrl($ptero_settings->getUrl() . 'api' . '/'); ])->baseUrl(config('SETTINGS::SYSTEM:PTERODACTYL:URL') . '/api');
} }
/** /**
* @return Exception * @return Exception
*/ */
private function getException(string $message = '', int $status = 0): Exception private static function getException(string $message = '', int $status = 0): Exception
{ {
if ($status == 404) { if ($status == 404) {
return new Exception('Ressource does not exist on pterodactyl - ' . $message, 404); return new Exception('Ressource does not exist on pterodactyl - ' . $message, 404);
@ -90,10 +68,10 @@ class PterodactylClient
* *
* @throws Exception * @throws Exception
*/ */
public function getEggs(Nest $nest) public static function getEggs(Nest $nest)
{ {
try { try {
$response = $this->application->get("application/nests/{$nest->id}/eggs?include=nest,variables&per_page=" . $this->per_page_limit); $response = self::client()->get("/application/nests/{$nest->id}/eggs?include=nest,variables&per_page=" . config('SETTINGS::SYSTEM:PTERODACTYL:PER_PAGE_LIMIT'));
} catch (Exception $e) { } catch (Exception $e) {
throw self::getException($e->getMessage()); throw self::getException($e->getMessage());
} }
@ -109,10 +87,10 @@ class PterodactylClient
* *
* @throws Exception * @throws Exception
*/ */
public function getNodes() public static function getNodes()
{ {
try { try {
$response = $this->application->get('application/nodes?per_page=' . $this->per_page_limit); $response = self::client()->get('/application/nodes?per_page=' . config('SETTINGS::SYSTEM:PTERODACTYL:PER_PAGE_LIMIT'));
} catch (Exception $e) { } catch (Exception $e) {
throw self::getException($e->getMessage()); throw self::getException($e->getMessage());
} }
@ -129,10 +107,10 @@ class PterodactylClient
* @throws Exception * @throws Exception
* @description Returns the infos of a single node * @description Returns the infos of a single node
*/ */
public function getNode($id) public static function getNode($id)
{ {
try { try {
$response = $this->application->get('application/nodes/' . $id); $response = self::client()->get('/application/nodes/' . $id);
} catch (Exception $e) { } catch (Exception $e) {
throw self::getException($e->getMessage()); throw self::getException($e->getMessage());
} }
@ -143,10 +121,10 @@ class PterodactylClient
return $response->json()['attributes']; return $response->json()['attributes'];
} }
public function getServers() public static function getServers()
{ {
try { try {
$response = $this->application->get('application/servers?per_page=' . $this->per_page_limit); $response = self::client()->get('/application/servers?per_page=' . config('SETTINGS::SYSTEM:PTERODACTYL:PER_PAGE_LIMIT'));
} catch (Exception $e) { } catch (Exception $e) {
throw self::getException($e->getMessage()); throw self::getException($e->getMessage());
} }
@ -162,10 +140,10 @@ class PterodactylClient
* *
* @throws Exception * @throws Exception
*/ */
public function getNests() public static function getNests()
{ {
try { try {
$response = $this->application->get('application/nests?per_page=' . $this->per_page_limit); $response = self::client()->get('/application/nests?per_page=' . config('SETTINGS::SYSTEM:PTERODACTYL:PER_PAGE_LIMIT'));
} catch (Exception $e) { } catch (Exception $e) {
throw self::getException($e->getMessage()); throw self::getException($e->getMessage());
} }
@ -181,10 +159,10 @@ class PterodactylClient
* *
* @throws Exception * @throws Exception
*/ */
public function getLocations() public static function getLocations()
{ {
try { try {
$response = $this->application->get('application/locations?per_page=' . $this->per_page_limit); $response = self::client()->get('/application/locations?per_page=' . config('SETTINGS::SYSTEM:PTERODACTYL:PER_PAGE_LIMIT'));
} catch (Exception $e) { } catch (Exception $e) {
throw self::getException($e->getMessage()); throw self::getException($e->getMessage());
} }
@ -201,7 +179,7 @@ class PterodactylClient
* *
* @throws Exception * @throws Exception
*/ */
public function getFreeAllocationId(Node $node) public static function getFreeAllocationId(Node $node)
{ {
return self::getFreeAllocations($node)[0]['attributes']['id'] ?? null; return self::getFreeAllocations($node)[0]['attributes']['id'] ?? null;
} }
@ -212,7 +190,7 @@ class PterodactylClient
* *
* @throws Exception * @throws Exception
*/ */
public function getFreeAllocations(Node $node) public static function getFreeAllocations(Node $node)
{ {
$response = self::getAllocations($node); $response = self::getAllocations($node);
$freeAllocations = []; $freeAllocations = [];
@ -236,10 +214,11 @@ class PterodactylClient
* *
* @throws Exception * @throws Exception
*/ */
public function getAllocations(Node $node) public static function getAllocations(Node $node)
{ {
$per_page = config('SETTINGS::SERVER:ALLOCATION_LIMIT', 200);
try { try {
$response = $this->application->get("application/nodes/{$node->id}/allocations?per_page={$this->allocation_limit}"); $response = self::client()->get("/application/nodes/{$node->id}/allocations?per_page={$per_page}");
} catch (Exception $e) { } catch (Exception $e) {
throw self::getException($e->getMessage()); throw self::getException($e->getMessage());
} }
@ -250,15 +229,24 @@ class PterodactylClient
return $response->json(); return $response->json();
} }
/**
* @param string $route
* @return string
*/
public static function url(string $route): string
{
return config('SETTINGS::SYSTEM:PTERODACTYL:URL') . $route;
}
/** /**
* @param Server $server * @param Server $server
* @param Egg $egg * @param Egg $egg
* @param int $allocationId * @param int $allocationId
* @return Response * @return Response
*/ */
public function createServer(Server $server, Egg $egg, int $allocationId) public static function createServer(Server $server, Egg $egg, int $allocationId)
{ {
return $this->application->post('application/servers', [ return self::client()->post('/application/servers', [
'name' => $server->name, 'name' => $server->name,
'external_id' => $server->id, 'external_id' => $server->id,
'user' => $server->user->pterodactyl_id, 'user' => $server->user->pterodactyl_id,
@ -284,10 +272,10 @@ class PterodactylClient
]); ]);
} }
public function suspendServer(Server $server) public static function suspendServer(Server $server)
{ {
try { try {
$response = $this->application->post("application/servers/$server->pterodactyl_id/suspend"); $response = self::client()->post("/application/servers/$server->pterodactyl_id/suspend");
} catch (Exception $e) { } catch (Exception $e) {
throw self::getException($e->getMessage()); throw self::getException($e->getMessage());
} }
@ -298,10 +286,10 @@ class PterodactylClient
return $response; return $response;
} }
public function unSuspendServer(Server $server) public static function unSuspendServer(Server $server)
{ {
try { try {
$response = $this->application->post("application/servers/$server->pterodactyl_id/unsuspend"); $response = self::client()->post("/application/servers/$server->pterodactyl_id/unsuspend");
} catch (Exception $e) { } catch (Exception $e) {
throw self::getException($e->getMessage()); throw self::getException($e->getMessage());
} }
@ -321,7 +309,7 @@ class PterodactylClient
public function getUser(int $pterodactylId) public function getUser(int $pterodactylId)
{ {
try { try {
$response = $this->application->get("application/users/{$pterodactylId}"); $response = self::client()->get("/application/users/{$pterodactylId}");
} catch (Exception $e) { } catch (Exception $e) {
throw self::getException($e->getMessage()); throw self::getException($e->getMessage());
} }
@ -338,10 +326,10 @@ class PterodactylClient
* @param int $pterodactylId * @param int $pterodactylId
* @return mixed * @return mixed
*/ */
public function getServerAttributes(int $pterodactylId, bool $deleteOn404 = false) public static function getServerAttributes(int $pterodactylId, bool $deleteOn404 = false)
{ {
try { try {
$response = $this->application->get("application/servers/{$pterodactylId}?include=egg,node,nest,location"); $response = self::client()->get("/application/servers/{$pterodactylId}?include=egg,node,nest,location");
} catch (Exception $e) { } catch (Exception $e) {
throw self::getException($e->getMessage()); throw self::getException($e->getMessage());
} }
@ -368,9 +356,9 @@ class PterodactylClient
* @param Product $product * @param Product $product
* @return Response * @return Response
*/ */
public function updateServer(Server $server, Product $product) public static function updateServer(Server $server, Product $product)
{ {
return $this->application->patch("application/servers/{$server->pterodactyl_id}/build", [ return self::client()->patch("/application/servers/{$server->pterodactyl_id}/build", [
'allocation' => $server->allocation, 'allocation' => $server->allocation,
'memory' => $product->memory, 'memory' => $product->memory,
'swap' => $product->swap, 'swap' => $product->swap,
@ -393,9 +381,9 @@ class PterodactylClient
* @param Server $server * @param Server $server
* @return mixed * @return mixed
*/ */
public function updateServerOwner(Server $server, int $userId) public static function updateServerOwner(Server $server, int $userId)
{ {
return $this->application->patch("application/servers/{$server->pterodactyl_id}/details", [ return self::client()->patch("/application/servers/{$server->pterodactyl_id}/details", [
'name' => $server->name, 'name' => $server->name,
'user' => $userId, 'user' => $userId,
]); ]);
@ -408,9 +396,9 @@ class PterodactylClient
* @param string $action * @param string $action
* @return Response * @return Response
*/ */
public function powerAction(Server $server, $action) public static function powerAction(Server $server, $action)
{ {
return $this->client->post("client/servers/{$server->identifier}/power", [ return self::clientAdmin()->post("/client/servers/{$server->identifier}/power", [
'signal' => $action, 'signal' => $action,
]); ]);
} }
@ -418,9 +406,9 @@ class PterodactylClient
/** /**
* Get info about user * Get info about user
*/ */
public function getClientUser() public static function getClientUser()
{ {
return $this->client->get('client/account'); return self::clientAdmin()->get('/client/account');
} }
/** /**
@ -431,10 +419,10 @@ class PterodactylClient
* @param int $requireDisk * @param int $requireDisk
* @return bool * @return bool
*/ */
public function checkNodeResources(Node $node, int $requireMemory, int $requireDisk) public static function checkNodeResources(Node $node, int $requireMemory, int $requireDisk)
{ {
try { try {
$response = $this->application->get("application/nodes/{$node->id}"); $response = self::client()->get("/application/nodes/{$node->id}");
} catch (Exception $e) { } catch (Exception $e) {
throw self::getException($e->getMessage()); throw self::getException($e->getMessage());
} }

View file

@ -0,0 +1,47 @@
<?php
namespace App\Classes\Settings;
use App\Models\Settings;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
class Invoices
{
public function __construct()
{
}
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,56 @@
<?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()
{
}
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,107 @@
<?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()
{
}
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',
'enable_referral' => 'nullable|string',
'referral_reward' => 'nullable|numeric',
'referral_allowed' => 'nullable|string',
'always_give_commission' => 'nullable|string',
'referral_percentage' => 'nullable|numeric',
'referral_mode' => 'nullable|string',
'ticket_enabled' => 'nullable|string',
'ticket_notify' => 'string',
]);
$validator->after(function ($validator) use ($request) {
// if enable-recaptcha is true then recaptcha-site-key and recaptcha-secret-key must be set
if ($request->get('enable-recaptcha') == 'true' && (! $request->get('recaptcha-site-key') || ! $request->get('recaptcha-secret-key'))) {
$validator->errors()->add('recaptcha-site-key', 'The site key is required if recaptcha is enabled.');
$validator->errors()->add('recaptcha-secret-key', 'The secret key is required if recaptcha is enabled.');
}
});
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',
'SETTINGS::REFERRAL::ENABLED' => 'enable_referral',
'SETTINGS::REFERRAL::REWARD' => 'referral_reward',
'SETTINGS::REFERRAL::ALLOWED' => 'referral_allowed',
'SETTINGS::REFERRAL:MODE' => 'referral_mode',
'SETTINGS::REFERRAL::ALWAYS_GIVE_COMMISSION' => 'always_give_commission',
'SETTINGS::REFERRAL:PERCENTAGE' => 'referral_percentage',
'SETTINGS::TICKET:ENABLED' => 'ticket_enabled',
'SETTINGS::TICKET:NOTIFY' => 'ticket_notify',
];
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,58 @@
<?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()
{
}
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,154 @@
<?php
namespace App\Classes\Settings;
use App\Classes\Pterodactyl;
use App\Models\Settings;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Validator;
use Qirolab\Theme\Theme;
class System
{
public function __construct()
{
}
public function checkPteroClientkey()
{
$response = Pterodactyl::getClientUser();
if ($response->failed()) {
return redirect()->back()->with('error', __('Your Key or URL is not correct'));
}
return redirect()->back()->with('success', __('Everything is good!'));
}
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',
'server-limit-purchase' => 'required|min:0|integer',
'pterodactyl-api-key' => 'required|string',
'pterodactyl-url' => 'required|string',
'per-page-limit' => 'required|min:0|integer',
'pterodactyl-admin-api-key' => 'required|string',
'enable-upgrades' => 'string',
'enable-disable-servers' => 'string',
'enable-disable-new-users' => 'string',
'show-imprint' => 'string',
'show-privacy' => 'string',
'show-tos' => 'string',
'alert-enabled' => 'string',
'alter-type' => 'string',
'alert-message' => 'string|nullable',
'motd-enabled' => 'string',
'usefullinks-enabled' => 'string',
'motd-message' => 'string|nullable',
'seo-title' => 'string|nullable',
'seo-description' => 'string|nullable',
]);
$validator->after(function ($validator) use ($request) {
// if enable-recaptcha is true then recaptcha-site-key and recaptcha-secret-key must be set
if ($request->get('enable-upgrades') == 'true' && (! $request->get('pterodactyl-admin-api-key'))) {
$validator->errors()->add('pterodactyl-admin-api-key', 'The admin api key is required when upgrades are enabled.');
}
});
if ($validator->fails()) {
return redirect(route('admin.settings.index').'#system')->with('error', __('System settings have not been updated!'))->withErrors($validator)
->withInput();
}
// update Icons from request
$this->updateIcons($request);
$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:MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER" => "minimum-credits",
"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::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE" => "server-limit-purchase",
"SETTINGS::MISC:PHPMYADMIN:URL" => "phpmyadmin-url",
"SETTINGS::SYSTEM:PTERODACTYL:URL" => "pterodactyl-url",
'SETTINGS::SYSTEM:PTERODACTYL:PER_PAGE_LIMIT' => "per-page-limit",
"SETTINGS::SYSTEM:PTERODACTYL:TOKEN" => "pterodactyl-api-key",
"SETTINGS::SYSTEM:ENABLE_LOGIN_LOGO" => "enable-login-logo",
"SETTINGS::SYSTEM:PTERODACTYL:ADMIN_USER_TOKEN" => "pterodactyl-admin-api-key",
"SETTINGS::SYSTEM:ENABLE_UPGRADE" => "enable-upgrade",
"SETTINGS::SYSTEM:CREATION_OF_NEW_SERVERS" => "enable-disable-servers",
"SETTINGS::SYSTEM:CREATION_OF_NEW_USERS" => "enable-disable-new-users",
"SETTINGS::SYSTEM:SHOW_IMPRINT" => "show-imprint",
"SETTINGS::SYSTEM:SHOW_PRIVACY" => "show-privacy",
"SETTINGS::SYSTEM:SHOW_TOS" => "show-tos",
"SETTINGS::SYSTEM:ALERT_ENABLED" => "alert-enabled",
"SETTINGS::SYSTEM:ALERT_TYPE" => "alert-type",
"SETTINGS::SYSTEM:ALERT_MESSAGE" => "alert-message",
"SETTINGS::SYSTEM:THEME" => "theme",
"SETTINGS::SYSTEM:MOTD_ENABLED" => "motd-enabled",
"SETTINGS::SYSTEM:MOTD_MESSAGE" => "motd-message",
"SETTINGS::SYSTEM:USEFULLINKS_ENABLED" => "usefullinks-enabled",
"SETTINGS::SYSTEM:SEO_TITLE" => "seo-title",
"SETTINGS::SYSTEM:SEO_DESCRIPTION" => "seo-description",
];
foreach ($values as $key => $value) {
$param = $request->get($value);
Settings::where('key', $key)->updateOrCreate(['key' => $key], ['value' => $param]);
Cache::forget('setting'.':'.$key);
}
//SET THEME
$theme = $request->get('theme');
Theme::set($theme);
return redirect(route('admin.settings.index').'#system')->with('success', __('System settings updated!'));
}
private function updateIcons(Request $request)
{
$request->validate([
'icon' => 'nullable|max:10000|mimes:jpg,png,jpeg',
'logo' => 'nullable|max:10000|mimes:jpg,png,jpeg',
'favicon' => 'nullable|max:10000|mimes:ico',
]);
if ($request->hasFile('icon')) {
$request->file('icon')->storeAs('public', 'icon.png');
}
if ($request->hasFile('logo')) {
$request->file('logo')->storeAs('public', 'logo.png');
}
if ($request->hasFile('favicon')) {
$request->file('favicon')->storeAs('public', 'favicon.ico');
}
}
}

View file

@ -2,20 +2,18 @@
namespace App\Console\Commands; namespace App\Console\Commands;
use App\Classes\PterodactylClient; use App\Classes\Pterodactyl;
use App\Models\User; use App\Models\User;
use App\Settings\PterodactylSettings;
use App\Traits\Referral; use App\Traits\Referral;
use Illuminate\Console\Command; use Illuminate\Console\Command;
use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator; use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;
class MakeUserCommand extends Command class MakeUserCommand extends Command
{ {
use Referral; use Referral;
private $pterodactyl;
/** /**
* The name and signature of the console command. * The name and signature of the console command.
* *
@ -30,14 +28,17 @@ class MakeUserCommand extends Command
*/ */
protected $description = 'Create an admin account with the Artisan Console'; protected $description = 'Create an admin account with the Artisan Console';
private Pterodactyl $pterodactyl;
/** /**
* Create a new command instance. * Create a new command instance.
* *
* @return void * @return void
*/ */
public function __construct() public function __construct(Pterodactyl $pterodactyl)
{ {
parent::__construct(); parent::__construct();
$this->pterodactyl = $pterodactyl;
} }
@ -46,9 +47,8 @@ class MakeUserCommand extends Command
* *
* @return int * @return int
*/ */
public function handle(PterodactylSettings $ptero_settings) public function handle()
{ {
$this->pterodactyl = new PterodactylClient($ptero_settings);
$ptero_id = $this->option('ptero_id') ?? $this->ask('Please specify your Pterodactyl ID.'); $ptero_id = $this->option('ptero_id') ?? $this->ask('Please specify your Pterodactyl ID.');
$password = $this->secret('password') ?? $this->ask('Please specify your password.'); $password = $this->secret('password') ?? $this->ask('Please specify your password.');

View file

@ -1,146 +0,0 @@
<?php
namespace App\Extensions\PaymentGateways\Mollie;
use App\Helpers\AbstractExtension;
use App\Events\PaymentEvent;
use App\Events\UserUpdateCreditsEvent;
use App\Models\PartnerDiscount;
use App\Models\Payment;
use App\Models\ShopProduct;
use App\Models\User;
use Exception;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Http;
/**
* Summary of PayPalExtension
*/
class MollieExtension extends AbstractExtension
{
public static function getConfig(): array
{
return [
"name" => "Mollie",
"RoutesIgnoreCsrf" => [
"payment/MollieWebhook"
],
];
}
static function pay(Request $request): void
{
$url = 'https://api.mollie.com/v2/payments';
$settings = new MollieSettings();
$user = Auth::user();
$shopProduct = ShopProduct::findOrFail($request->shopProduct);
$discount = PartnerDiscount::getDiscount();
// create a new payment
$payment = Payment::create([
'user_id' => $user->id,
'payment_id' => null,
'payment_method' => 'mollie',
'type' => $shopProduct->type,
'status' => 'open',
'amount' => $shopProduct->quantity,
'price' => $shopProduct->price - ($shopProduct->price * $discount / 100),
'tax_value' => $shopProduct->getTaxValue(),
'tax_percent' => $shopProduct->getTaxPercent(),
'total_price' => $shopProduct->getTotalPrice(),
'currency_code' => $shopProduct->currency_code,
'shop_item_product_id' => $shopProduct->id,
]);
try {
$response = Http::withHeaders([
'Content-Type' => 'application/json',
'Authorization' => 'Bearer ' . $settings->api_key,
])->post($url, [
'amount' => [
'currency' => $shopProduct->currency_code,
'value' => number_format($shopProduct->getTotalPrice(), 2, '.', ''),
],
'description' => "Order #{$payment->id} - " . $shopProduct->name,
'redirectUrl' => route('payment.MollieSuccess'),
'cancelUrl' => route('payment.Cancel'),
'webhookUrl' => url('/extensions/payment/MollieWebhook'),
'metadata' => [
'payment_id' => $payment->id,
],
]);
if ($response->status() != 201) {
Log::error('Mollie Payment: ' . $response->body());
$payment->delete();
Redirect::route('store.index')->with('error', __('Payment failed'))->send();
return;
}
$payment->update([
'payment_id' => $response->json()['id'],
]);
Redirect::away($response->json()['_links']['checkout']['href'])->send();
return;
} catch (Exception $ex) {
Log::error('Mollie Payment: ' . $ex->getMessage());
$payment->delete();
Redirect::route('store.index')->with('error', __('Payment failed'))->send();
return;
}
}
static function success(Request $request): void
{
$payment = Payment::findOrFail($request->input('payment'));
$payment->status = 'pending';
Redirect::route('home')->with('success', 'Your payment is being processed')->send();
return;
}
static function webhook(Request $request): JsonResponse
{
$url = 'https://api.mollie.com/v2/payments/' . $request->id;
$settings = new MollieSettings();
try {
$response = Http::withHeaders([
'Content-Type' => 'application/json',
'Authorization' => 'Bearer ' . $settings->api_key,
])->get($url);
if ($response->status() != 200) {
Log::error('Mollie Payment Webhook: ' . $response->json()['title']);
return response()->json(['success' => false]);
}
$payment = Payment::findOrFail($response->json()['metadata']['payment_id']);
$payment->status->update([
'status' => $response->json()['status'],
]);
$shopProduct = ShopProduct::findOrFail($payment->shop_item_product_id);
event(new PaymentEvent($payment, $payment, $shopProduct));
if ($response->json()['status'] == 'paid') {
$user = User::findOrFail($payment->user_id);
event(new UserUpdateCreditsEvent($user));
}
} catch (Exception $ex) {
Log::error('Mollie Payment Webhook: ' . $ex->getMessage());
return response()->json(['success' => false]);
}
// return a 200 status code
return response()->json(['success' => true]);
}
}

View file

@ -1,41 +0,0 @@
<?php
namespace App\Extensions\PaymentGateways\Mollie;
use Spatie\LaravelSettings\Settings;
class MollieSettings extends Settings
{
public bool $enabled = false;
public ?string $api_key;
public static function group(): string
{
return 'mollie';
}
public static function encrypted(): array
{
return [
'api_key',
];
}
public static function getOptionInputData()
{
return [
'category_icon' => 'fas fa-dollar-sign',
'api_key' => [
'type' => 'string',
'label' => 'API Key',
'description' => 'The API Key of your Mollie App',
],
'enabled' => [
'type' => 'boolean',
'label' => 'Enabled',
'description' => 'Enable or disable this payment gateway',
],
];
}
}

View file

@ -1,18 +0,0 @@
<?php
use Spatie\LaravelSettings\Migrations\SettingsMigration;
class CreateMollieSettings extends SettingsMigration
{
public function up(): void
{
$this->migrator->addEncrypted('mollie.api_key', null);
$this->migrator->add('mollie.enabled', false);
}
public function down(): void
{
$this->migrator->delete('mollie.api_key');
$this->migrator->delete('mollie.enabled');
}
}

View file

@ -1,22 +0,0 @@
<?php
use Illuminate\Support\Facades\Route;
use App\Extensions\PaymentGateways\Mollie\MollieExtension;
Route::middleware(['web', 'auth'])->group(function () {
Route::get('payment/MolliePay/{shopProduct}', function () {
MollieExtension::pay(request());
})->name('payment.MolliePay');
Route::get(
'payment/MollieSuccess',
function () {
MollieExtension::success(request());
}
)->name('payment.MollieSuccess');
});
Route::post('payment/MollieWebhook', function () {
MollieExtension::webhook(request());
})->name('payment.MollieWebhook');

View file

@ -1,197 +0,0 @@
<?php
namespace App\Extensions\PaymentGateways\PayPal;
use App\Helpers\AbstractExtension;
use App\Events\PaymentEvent;
use App\Events\UserUpdateCreditsEvent;
use App\Extensions\PaymentGateways\PayPal\PayPalSettings;
use App\Models\PartnerDiscount;
use App\Models\Payment;
use App\Models\ShopProduct;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\Log;
use PayPalCheckoutSdk\Core\PayPalHttpClient;
use PayPalCheckoutSdk\Core\ProductionEnvironment;
use PayPalCheckoutSdk\Core\SandboxEnvironment;
use PayPalCheckoutSdk\Orders\OrdersCaptureRequest;
use PayPalCheckoutSdk\Orders\OrdersCreateRequest;
use PayPalHttp\HttpException;
/**
* Summary of PayPalExtension
*/
class PayPalExtension extends AbstractExtension
{
public static function getConfig(): array
{
return [
"name" => "PayPal",
"RoutesIgnoreCsrf" => [],
];
}
static function PaypalPay(Request $request): void
{
/** @var User $user */
$user = Auth::user();
$shopProduct = ShopProduct::findOrFail($request->shopProduct);
$discount = PartnerDiscount::getDiscount();
// create a new payment
$payment = Payment::create([
'user_id' => $user->id,
'payment_id' => null,
'payment_method' => 'paypal',
'type' => $shopProduct->type,
'status' => 'open',
'amount' => $shopProduct->quantity,
'price' => $shopProduct->price - ($shopProduct->price * $discount / 100),
'tax_value' => $shopProduct->getTaxValue(),
'tax_percent' => $shopProduct->getTaxPercent(),
'total_price' => $shopProduct->getTotalPrice(),
'currency_code' => $shopProduct->currency_code,
'shop_item_product_id' => $shopProduct->id,
]);
$request = new OrdersCreateRequest();
$request->prefer('return=representation');
$request->body = [
"intent" => "CAPTURE",
"purchase_units" => [
[
"reference_id" => uniqid(),
"description" => $shopProduct->display . ($discount ? (" (" . __('Discount') . " " . $discount . '%)') : ""),
"amount" => [
"value" => $shopProduct->getTotalPrice(),
'currency_code' => strtoupper($shopProduct->currency_code),
'breakdown' => [
'item_total' =>
[
'currency_code' => strtoupper($shopProduct->currency_code),
'value' => $shopProduct->getPriceAfterDiscount(),
],
'tax_total' =>
[
'currency_code' => strtoupper($shopProduct->currency_code),
'value' => $shopProduct->getTaxValue(),
]
]
]
]
],
"application_context" => [
"cancel_url" => route('payment.Cancel'),
"return_url" => route('payment.PayPalSuccess', ['payment' => $payment->id]),
'brand_name' => config('app.name', 'Controlpanel.GG'),
'shipping_preference' => 'NO_SHIPPING'
]
];
try {
// Call API with your client and get a response for your call
$response = self::getPayPalClient()->execute($request);
// check for any errors in the response
if ($response->statusCode != 201) {
throw new \Exception($response->statusCode);
}
// make sure the link is not empty
if (empty($response->result->links[1]->href)) {
throw new \Exception('No redirect link found');
}
Redirect::away($response->result->links[1]->href)->send();
return;
} catch (HttpException $ex) {
Log::error('PayPal Payment: ' . $ex->getMessage());
$payment->delete();
Redirect::route('store.index')->with('error', __('Payment failed'))->send();
return;
}
}
static function PaypalSuccess(Request $laravelRequest): void
{
$user = Auth::user();
$user = User::findOrFail($user->id);
$payment = Payment::findOrFail($laravelRequest->payment);
$shopProduct = ShopProduct::findOrFail($payment->shop_item_product_id);
$request = new OrdersCaptureRequest($laravelRequest->input('token'));
$request->prefer('return=representation');
try {
// Call API with your client and get a response for your call
$response = self::getPayPalClient()->execute($request);
if ($response->statusCode == 201 || $response->statusCode == 200) {
//update payment
$payment->update([
'status' => 'paid',
'payment_id' => $response->result->id,
]);
event(new UserUpdateCreditsEvent($user));
event(new PaymentEvent($user, $payment, $shopProduct));
// redirect to the payment success page with success message
Redirect::route('home')->with('success', 'Payment successful')->send();
} elseif (env('APP_ENV') == 'local') {
// If call returns body in response, you can get the deserialized version from the result attribute of the response
$payment->delete();
dd($response);
} else {
$payment->update([
'status' => 'cancelled',
'payment_id' => $response->result->id,
]);
abort(500);
}
} catch (HttpException $ex) {
if (env('APP_ENV') == 'local') {
echo $ex->statusCode;
$payment->delete();
dd($ex->getMessage());
} else {
$payment->update([
'status' => 'cancelled',
'payment_id' => $response->result->id,
]);
abort(422);
}
}
}
static function getPayPalClient(): PayPalHttpClient
{
$environment = env('APP_ENV') == 'local'
? new SandboxEnvironment(self::getPaypalClientId(), self::getPaypalClientSecret())
: new ProductionEnvironment(self::getPaypalClientId(), self::getPaypalClientSecret());
return new PayPalHttpClient($environment);
}
/**
* @return string
*/
static function getPaypalClientId(): string
{
$settings = new PayPalSettings();
return env('APP_ENV') == 'local' ? $settings->sandbox_client_id : $settings->client_id;
}
/**
* @return string
*/
static function getPaypalClientSecret(): string
{
$settings = new PayPalSettings();
return env('APP_ENV') == 'local' ? $settings->sandbox_client_secret : $settings->client_secret;
}
}

View file

@ -1,67 +0,0 @@
<?php
namespace App\Extensions\PaymentGateways\PayPal;
use Spatie\LaravelSettings\Settings;
class PayPalSettings extends Settings
{
public bool $enabled = false;
public ?string $client_id;
public ?string $client_secret;
public ?string $sandbox_client_id;
public ?string $sandbox_client_secret;
public static function group(): string
{
return 'paypal';
}
public static function encrypted(): array
{
return [
'client_id',
'client_secret',
'sandbox_client_id',
'sandbox_client_secret'
];
}
/**
* Summary of optionInputData array
* Only used for the settings page
* @return array<array<'type'|'label'|'description'|'options', string|bool|float|int|array<string, string>>>
*/
public static function getOptionInputData()
{
return [
'category_icon' => 'fas fa-dollar-sign',
'client_id' => [
'type' => 'string',
'label' => 'Client ID',
'description' => 'The Client ID of your PayPal App',
],
'client_secret' => [
'type' => 'string',
'label' => 'Client Secret',
'description' => 'The Client Secret of your PayPal App',
],
'enabled' => [
'type' => 'boolean',
'label' => 'Enabled',
'description' => 'Enable this payment gateway',
],
'sandbox_client_id' => [
'type' => 'string',
'label' => 'Sandbox Client ID',
'description' => 'The Sandbox Client ID used when app_env = local',
],
'sandbox_client_secret' => [
'type' => 'string',
'label' => 'Sandbox Client Secret',
'description' => 'The Sandbox Client Secret used when app_env = local',
],
];
}
}

View file

@ -0,0 +1,13 @@
<?php
namespace App\Extensions\PaymentGateways\PayPal;
function getConfig()
{
return [
"name" => "PayPal",
"description" => "PayPal payment gateway",
"RoutesIgnoreCsrf" => [],
"enabled" => (config('SETTINGS::PAYMENTS:PAYPAL:SECRET') && config('SETTINGS::PAYMENTS:PAYPAL:CLIENT_ID')) || (config('SETTINGS::PAYMENTS:PAYPAL:SANDBOX_SECRET') && config('SETTINGS::PAYMENTS:PAYPAL:SANDBOX_CLIENT_ID') && env("APP_ENV") === "local"),
];
}

View file

@ -0,0 +1,186 @@
<?php
use App\Events\PaymentEvent;
use App\Events\UserUpdateCreditsEvent;
use App\Models\PartnerDiscount;
use App\Models\Payment;
use App\Models\ShopProduct;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\Log;
use PayPalCheckoutSdk\Core\PayPalHttpClient;
use PayPalCheckoutSdk\Core\ProductionEnvironment;
use PayPalCheckoutSdk\Core\SandboxEnvironment;
use PayPalCheckoutSdk\Orders\OrdersCaptureRequest;
use PayPalCheckoutSdk\Orders\OrdersCreateRequest;
use PayPalHttp\HttpException;
/**
* @param Request $request
* @param ShopProduct $shopProduct
*/
function PaypalPay(Request $request)
{
/** @var User $user */
$user = Auth::user();
$shopProduct = ShopProduct::findOrFail($request->shopProduct);
$discount = PartnerDiscount::getDiscount();
// create a new payment
$payment = Payment::create([
'user_id' => $user->id,
'payment_id' => null,
'payment_method' => 'paypal',
'type' => $shopProduct->type,
'status' => 'open',
'amount' => $shopProduct->quantity,
'price' => $shopProduct->price - ($shopProduct->price * $discount / 100),
'tax_value' => $shopProduct->getTaxValue(),
'tax_percent' => $shopProduct->getTaxPercent(),
'total_price' => $shopProduct->getTotalPrice(),
'currency_code' => $shopProduct->currency_code,
'shop_item_product_id' => $shopProduct->id,
]);
$request = new OrdersCreateRequest();
$request->prefer('return=representation');
$request->body = [
"intent" => "CAPTURE",
"purchase_units" => [
[
"reference_id" => uniqid(),
"description" => $shopProduct->display . ($discount ? (" (" . __('Discount') . " " . $discount . '%)') : ""),
"amount" => [
"value" => $shopProduct->getTotalPrice(),
'currency_code' => strtoupper($shopProduct->currency_code),
'breakdown' => [
'item_total' =>
[
'currency_code' => strtoupper($shopProduct->currency_code),
'value' => $shopProduct->getPriceAfterDiscount(),
],
'tax_total' =>
[
'currency_code' => strtoupper($shopProduct->currency_code),
'value' => $shopProduct->getTaxValue(),
]
]
]
]
],
"application_context" => [
"cancel_url" => route('payment.Cancel'),
"return_url" => route('payment.PayPalSuccess', ['payment' => $payment->id]),
'brand_name' => config('app.name', 'Controlpanel.GG'),
'shipping_preference' => 'NO_SHIPPING'
]
];
try {
// Call API with your client and get a response for your call
$response = getPayPalClient()->execute($request);
// check for any errors in the response
if ($response->statusCode != 201) {
throw new \Exception($response->statusCode);
}
// make sure the link is not empty
if (empty($response->result->links[1]->href)) {
throw new \Exception('No redirect link found');
}
Redirect::away($response->result->links[1]->href)->send();
return;
} catch (HttpException $ex) {
Log::error('PayPal Payment: ' . $ex->getMessage());
$payment->delete();
Redirect::route('store.index')->with('error', __('Payment failed'))->send();
return;
}
}
/**
* @param Request $laravelRequest
*/
function PaypalSuccess(Request $laravelRequest)
{
$user = Auth::user();
$user = User::findOrFail($user->id);
$payment = Payment::findOrFail($laravelRequest->payment);
$shopProduct = ShopProduct::findOrFail($payment->shop_item_product_id);
$request = new OrdersCaptureRequest($laravelRequest->input('token'));
$request->prefer('return=representation');
try {
// Call API with your client and get a response for your call
$response = getPayPalClient()->execute($request);
if ($response->statusCode == 201 || $response->statusCode == 200) {
//update payment
$payment->update([
'status' => 'paid',
'payment_id' => $response->result->id,
]);
event(new UserUpdateCreditsEvent($user));
event(new PaymentEvent($user, $payment, $shopProduct));
// redirect to the payment success page with success message
Redirect::route('home')->with('success', 'Payment successful')->send();
} elseif (env('APP_ENV') == 'local') {
// If call returns body in response, you can get the deserialized version from the result attribute of the response
$payment->delete();
dd($response);
} else {
$payment->update([
'status' => 'cancelled',
'payment_id' => $response->result->id,
]);
abort(500);
}
} catch (HttpException $ex) {
if (env('APP_ENV') == 'local') {
echo $ex->statusCode;
$payment->delete();
dd($ex->getMessage());
} else {
$payment->update([
'status' => 'cancelled',
'payment_id' => $response->result->id,
]);
abort(422);
}
}
}
/**
* @return PayPalHttpClient
*/
function getPayPalClient()
{
$environment = env('APP_ENV') == 'local'
? new SandboxEnvironment(getPaypalClientId(), getPaypalClientSecret())
: new ProductionEnvironment(getPaypalClientId(), getPaypalClientSecret());
return new PayPalHttpClient($environment);
}
/**
* @return string
*/
function getPaypalClientId()
{
return env('APP_ENV') == 'local' ? config("SETTINGS::PAYMENTS:PAYPAL:SANDBOX_CLIENT_ID") : config("SETTINGS::PAYMENTS:PAYPAL:CLIENT_ID");
}
/**
* @return string
*/
function getPaypalClientSecret()
{
return env('APP_ENV') == 'local' ? config("SETTINGS::PAYMENTS:PAYPAL:SANDBOX_SECRET") : config("SETTINGS::PAYMENTS:PAYPAL:SECRET");
}

View file

@ -1,100 +0,0 @@
<?php
use Spatie\LaravelSettings\Migrations\SettingsMigration;
use Illuminate\Support\Facades\DB;
class CreatePayPalSettings extends SettingsMigration
{
public function up(): void
{
$table_exists = DB::table('settings_old')->exists();
$this->migrator->addEncrypted('paypal.client_id', $table_exists ? $this->getOldValue('SETTINGS::PAYMENTS:PAYPAL:CLIENT_ID') : null);
$this->migrator->addEncrypted('paypal.client_secret', $table_exists ? $this->getOldValue('SETTINGS::PAYMENTS:PAYPAL:SECRET') : null);
$this->migrator->addEncrypted('paypal.sandbox_client_id', $table_exists ? $this->getOldValue('SETTINGS::PAYMENTS:PAYPAL:SANDBOX_CLIENT_ID') : null);
$this->migrator->addEncrypted('paypal.sandbox_client_secret', $table_exists ? $this->getOldValue('SETTINGS::PAYMENTS:PAYPAL:SANDBOX_SECRET') : null);
$this->migrator->add('paypal.enabled', false);
}
public function down(): void
{
DB::table('settings_old')->insert([
[
'key' => 'SETTINGS::PAYMENTS:PAYPAL:CLIENT_ID',
'value' => $this->getNewValue('client_id'),
'type' => 'string',
'description' => 'The Client ID of your PayPal App'
],
[
'key' => 'SETTINGS::PAYMENTS:PAYPAL:SECRET',
'value' => $this->getNewValue('client_secret'),
'type' => 'string',
'description' => 'The Client Secret of your PayPal App'
],
[
'key' => 'SETTINGS::PAYMENTS:PAYPAL:SANDBOX_CLIENT_ID',
'value' => $this->getNewValue('sandbox_client_id'),
'type' => 'string',
'description' => 'The Sandbox Client ID of your PayPal App'
],
[
'key' => 'SETTINGS::PAYMENTS:PAYPAL:SANDBOX_SECRET',
'value' => $this->getNewValue('sandbox_client_secret'),
'type' => 'string',
'description' => 'The Sandbox Client Secret of your PayPal App'
]
]);
$this->migrator->delete('paypal.client_id');
$this->migrator->delete('paypal.client_secret');
$this->migrator->delete('paypal.enabled');
$this->migrator->delete('paypal.sandbox_client_id');
$this->migrator->delete('paypal.sandbox_client_secret');
}
public function getNewValue(string $name)
{
$new_value = DB::table('settings')->where([['group', '=', 'paypal'], ['name', '=', $name]])->get(['payload'])->first();
// Some keys returns '""' as a value.
if ($new_value->payload === '""') {
return null;
}
// remove the quotes from the string
if (substr($new_value->payload, 0, 1) === '"' && substr($new_value->payload, -1) === '"') {
return substr($new_value->payload, 1, -1);
}
return $new_value->payload;
}
public function getOldValue(string $key)
{
// Always get the first value of the key.
$old_value = DB::table('settings_old')->where('key', '=', $key)->get(['value', 'type'])->first();
// Handle the old values to return without it being a string in all cases.
if ($old_value->type === "string" || $old_value->type === "text") {
if (is_null($old_value->value)) {
return '';
}
// Some values have the type string, but their values are boolean.
if ($old_value->value === "false" || $old_value->value === "true") {
return filter_var($old_value->value, FILTER_VALIDATE_BOOL);
}
return $old_value->value;
}
if ($old_value->type === "boolean") {
return filter_var($old_value->value, FILTER_VALIDATE_BOOL);
}
return filter_var($old_value->value, FILTER_VALIDATE_INT);
}
}

View file

@ -1,17 +1,18 @@
<?php <?php
use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Route;
use App\Extensions\PaymentGateways\PayPal\PayPalExtension;
include_once(__DIR__ . '/index.php');
Route::middleware(['web', 'auth'])->group(function () { Route::middleware(['web', 'auth'])->group(function () {
Route::get('payment/PayPalPay/{shopProduct}', function () { Route::get('payment/PayPalPay/{shopProduct}', function () {
PayPalExtension::PaypalPay(request()); PaypalPay(request());
})->name('payment.PayPalPay'); })->name('payment.PayPalPay');
Route::get( Route::get(
'payment/PayPalSuccess', 'payment/PayPalSuccess',
function () { function () {
PayPalExtension::PaypalSuccess(request()); PaypalSuccess(request());
} }
)->name('payment.PayPalSuccess'); )->name('payment.PayPalSuccess');
}); });

View file

@ -1,390 +0,0 @@
<?php
namespace App\Extensions\PaymentGateways\Stripe;
use App\Helpers\AbstractExtension;
use App\Events\PaymentEvent;
use App\Events\UserUpdateCreditsEvent;
use App\Extensions\PaymentGateways\Stripe\StripeSettings;
use App\Models\PartnerDiscount;
use App\Models\Payment;
use App\Models\ShopProduct;
use App\Models\User;
use App\Notifications\ConfirmPaymentNotification;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Redirect;
use Stripe\Exception\SignatureVerificationException;
use Stripe\Stripe;
use Stripe\StripeClient;
class StripeExtension extends AbstractExtension
{
public static function getConfig(): array
{
return [
"name" => "Stripe",
"RoutesIgnoreCsrf" => [
"payment/StripeWebhooks",
],
];
}
/**
* @param Request $request
* @param ShopProduct $shopProduct
*/
public static function StripePay(Request $request)
{
$user = Auth::user();
$shopProduct = ShopProduct::findOrFail($request->shopProduct);
// check if the price is valid for stripe
if (!self::checkPriceAmount($shopProduct->getTotalPrice(), strtoupper($shopProduct->currency_code), 'stripe')) {
Redirect::route('home')->with('error', __('The product you chose can\'t be purchased with this payment method. The total amount is too small. Please buy a bigger amount or try a different payment method.'))->send();
return;
}
$discount = PartnerDiscount::getDiscount();
// create payment
$payment = Payment::create([
'user_id' => $user->id,
'payment_id' => null,
'payment_method' => 'stripe',
'type' => $shopProduct->type,
'status' => 'open',
'amount' => $shopProduct->quantity,
'price' => $shopProduct->price - ($shopProduct->price * $discount / 100),
'tax_value' => $shopProduct->getTaxValue(),
'total_price' => $shopProduct->getTotalPrice(),
'tax_percent' => $shopProduct->getTaxPercent(),
'currency_code' => $shopProduct->currency_code,
'shop_item_product_id' => $shopProduct->id,
]);
$stripeClient = self::getStripeClient();
$request = $stripeClient->checkout->sessions->create([
'line_items' => [
[
'price_data' => [
'currency' => $shopProduct->currency_code,
'product_data' => [
'name' => $shopProduct->display . ($discount ? (' (' . __('Discount') . ' ' . $discount . '%)') : ''),
'description' => $shopProduct->description,
],
'unit_amount_decimal' => round($shopProduct->getPriceAfterDiscount() * 100, 2),
],
'quantity' => 1,
],
[
'price_data' => [
'currency' => $shopProduct->currency_code,
'product_data' => [
'name' => __('Tax'),
'description' => $shopProduct->getTaxPercent() . '%',
],
'unit_amount_decimal' => round($shopProduct->getTaxValue(), 2) * 100,
],
'quantity' => 1,
],
],
'mode' => 'payment',
'success_url' => route('payment.StripeSuccess', ['payment' => $payment->id]) . '&session_id={CHECKOUT_SESSION_ID}',
'cancel_url' => route('payment.Cancel'),
'payment_intent_data' => [
'metadata' => [
'payment_id' => $payment->id,
],
],
]);
Redirect::to($request->url)->send();
}
/**
* @param Request $request
*/
public static function StripeSuccess(Request $request)
{
$user = Auth::user();
$user = User::findOrFail($user->id);
$payment = Payment::findOrFail($request->input('payment'));
$shopProduct = ShopProduct::findOrFail($payment->shop_item_product_id);
Redirect::route('home')->with('success', 'Please wait for success')->send();
$stripeClient = self::getStripeClient();
try {
//get stripe data
$paymentSession = $stripeClient->checkout->sessions->retrieve($request->input('session_id'));
$paymentIntent = $stripeClient->paymentIntents->retrieve($paymentSession->payment_intent);
//get DB entry of this payment ID if existing
$paymentDbEntry = Payment::where('payment_id', $paymentSession->payment_intent)->count();
// check if payment is 100% completed and payment does not exist in db already
if ($paymentSession->status == 'complete' && $paymentIntent->status == 'succeeded' && $paymentDbEntry == 0) {
//update payment
$payment->update([
'payment_id' => $paymentSession->payment_intent,
'status' => 'paid',
]);
//payment notification
$user->notify(new ConfirmPaymentNotification($payment));
event(new UserUpdateCreditsEvent($user));
event(new PaymentEvent($user, $payment, $shopProduct));
//redirect back to home
Redirect::route('home')->with('success', 'Payment successful')->send();
} else {
if ($paymentIntent->status == 'processing') {
//update payment
$payment->update([
'payment_id' => $paymentSession->payment_intent,
'status' => 'processing',
]);
event(new PaymentEvent($user, $payment, $shopProduct));
Redirect::route('home')->with('success', 'Your payment is being processed')->send();
}
if ($paymentDbEntry == 0 && $paymentIntent->status != 'processing') {
$stripeClient->paymentIntents->cancel($paymentIntent->id);
//redirect back to home
Redirect::route('home')->with('info', __('Your payment has been canceled!'))->send();
} else {
abort(402);
}
}
} catch (Exception $e) {
if (env('APP_ENV') == 'local') {
dd($e->getMessage());
} else {
abort(422);
}
}
}
/**
* @param Request $request
*/
public static function handleStripePaymentSuccessHook($paymentIntent)
{
try {
$payment = Payment::where('id', $paymentIntent->metadata->payment_id)->with('user')->first();
$user = User::where('id', $payment->user_id)->first();
$shopProduct = ShopProduct::findOrFail($payment->shop_item_product_id);
if ($paymentIntent->status == 'succeeded' && $payment->status == 'processing') {
//update payment db entry status
$payment->update([
'payment_id' => $payment->payment_id ?? $paymentIntent->id,
'status' => 'paid'
]);
//payment notification
$user->notify(new ConfirmPaymentNotification($payment));
event(new UserUpdateCreditsEvent($user));
event(new PaymentEvent($user, $payment, $shopProduct));
}
// return 200
return response()->json(['success' => true], 200);
} catch (Exception $ex) {
abort(422);
}
}
/**
* @param Request $request
*/
public static function StripeWebhooks(Request $request)
{
Stripe::setApiKey(self::getStripeSecret());
try {
$payload = @file_get_contents('php://input');
$sig_header = $request->header('Stripe-Signature');
$event = null;
$event = \Stripe\Webhook::constructEvent(
$payload,
$sig_header,
self::getStripeEndpointSecret()
);
} catch (\UnexpectedValueException $e) {
// Invalid payload
abort(400);
} catch (SignatureVerificationException $e) {
// Invalid signature
abort(400);
}
// Handle the event
switch ($event->type) {
case 'payment_intent.succeeded':
$paymentIntent = $event->data->object; // contains a \Stripe\PaymentIntent
self::handleStripePaymentSuccessHook($paymentIntent);
break;
default:
echo 'Received unknown event type ' . $event->type;
}
}
/**
* @return \Stripe\StripeClient
*/
public static function getStripeClient()
{
return new StripeClient(self::getStripeSecret());
}
/**
* @return string
*/
public static function getStripeSecret()
{
$settings = new StripeSettings();
return env('APP_ENV') == 'local'
? $settings->test_secret_key
: $settings->secret_key;
}
/**
* @return string
*/
public static function getStripeEndpointSecret()
{
$settings = new StripeSettings();
return env('APP_ENV') == 'local'
? $settings->test_endpoint_secret
: $settings->endpoint_secret;
}
/**
* @param $amount
* @param $currencyCode
* @param $payment_method
* @return bool
* @description check if the amount is higher than the minimum amount for the stripe gateway
*/
public static function checkPriceAmount($amount, $currencyCode, $payment_method)
{
$minimums = [
"USD" => [
"paypal" => 0,
"stripe" => 0.5
],
"AED" => [
"paypal" => 0,
"stripe" => 2
],
"AUD" => [
"paypal" => 0,
"stripe" => 0.5
],
"BGN" => [
"paypal" => 0,
"stripe" => 1
],
"BRL" => [
"paypal" => 0,
"stripe" => 0.5
],
"CAD" => [
"paypal" => 0,
"stripe" => 0.5
],
"CHF" => [
"paypal" => 0,
"stripe" => 0.5
],
"CZK" => [
"paypal" => 0,
"stripe" => 15
],
"DKK" => [
"paypal" => 0,
"stripe" => 2.5
],
"EUR" => [
"paypal" => 0,
"stripe" => 0.5
],
"GBP" => [
"paypal" => 0,
"stripe" => 0.3
],
"HKD" => [
"paypal" => 0,
"stripe" => 4
],
"HRK" => [
"paypal" => 0,
"stripe" => 0.5
],
"HUF" => [
"paypal" => 0,
"stripe" => 175
],
"INR" => [
"paypal" => 0,
"stripe" => 0.5
],
"JPY" => [
"paypal" => 0,
"stripe" => 0.5
],
"MXN" => [
"paypal" => 0,
"stripe" => 10
],
"MYR" => [
"paypal" => 0,
"stripe" => 2
],
"NOK" => [
"paypal" => 0,
"stripe" => 3
],
"NZD" => [
"paypal" => 0,
"stripe" => 0.5
],
"PLN" => [
"paypal" => 0,
"stripe" => 2
],
"RON" => [
"paypal" => 0,
"stripe" => 2
],
"SEK" => [
"paypal" => 0,
"stripe" => 3
],
"SGD" => [
"paypal" => 0,
"stripe" => 0.5
],
"THB" => [
"paypal" => 0,
"stripe" => 10
]
];
return $amount >= $minimums[$currencyCode][$payment_method];
}
}

View file

@ -1,63 +0,0 @@
<?php
namespace App\Extensions\PaymentGateways\Stripe;
use Spatie\LaravelSettings\Settings;
class StripeSettings extends Settings
{
public bool $enabled = false;
public ?string $secret_key;
public ?string $endpoint_secret;
public ?string $test_secret_key;
public ?string $test_endpoint_secret;
public static function group(): string
{
return 'stripe';
}
public static function encrypted(): array
{
return [
"secret_key",
"endpoint_secret",
"test_secret_key",
"test_endpoint_secret"
];
}
public static function getOptionInputData()
{
return [
'category_icon' => 'fas fa-dollar-sign',
'secret_key' => [
'type' => 'string',
'label' => 'Secret Key',
'description' => 'The Secret Key of your Stripe App',
],
'endpoint_secret' => [
'type' => 'string',
'label' => 'Endpoint Secret',
'description' => 'The Endpoint Secret of your Stripe App',
],
'test_secret_key' => [
'type' => 'string',
'label' => 'Test Secret Key',
'description' => 'The Test Secret Key used when app_env = local',
],
'test_endpoint_secret' => [
'type' => 'string',
'label' => 'Test Endpoint Secret',
'description' => 'The Test Endpoint Secret used when app_env = local',
],
'enabled' => [
'type' => 'boolean',
'label' => 'Enabled',
'description' => 'Enable this payment gateway',
]
];
}
}

View file

@ -0,0 +1,15 @@
<?php
namespace App\Extensions\PaymentGateways\Stripe;
function getConfig()
{
return [
"name" => "Stripe",
"description" => "Stripe payment gateway",
"RoutesIgnoreCsrf" => [
"payment/StripeWebhooks",
],
"enabled" => config('SETTINGS::PAYMENTS:STRIPE:SECRET') && config('SETTINGS::PAYMENTS:STRIPE:ENDPOINT_SECRET') || config('SETTINGS::PAYMENTS:STRIPE:ENDPOINT_TEST_SECRET') && config('SETTINGS::PAYMENTS:STRIPE:TEST_SECRET') && env("APP_ENV") === "local",
];
}

View file

@ -0,0 +1,373 @@
<?php
use App\Events\PaymentEvent;
use App\Events\UserUpdateCreditsEvent;
use App\Models\PartnerDiscount;
use App\Models\Payment;
use App\Models\ShopProduct;
use App\Models\User;
use App\Notifications\ConfirmPaymentNotification;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Redirect;
use Stripe\Exception\SignatureVerificationException;
use Stripe\Stripe;
use Stripe\StripeClient;
/**
* @param Request $request
* @param ShopProduct $shopProduct
*/
function StripePay(Request $request)
{
$user = Auth::user();
$shopProduct = ShopProduct::findOrFail($request->shopProduct);
// check if the price is valid for stripe
if (!checkPriceAmount($shopProduct->getTotalPrice(), strtoupper($shopProduct->currency_code), 'stripe')) {
Redirect::route('home')->with('error', __('The product you chose can\'t be purchased with this payment method. The total amount is too small. Please buy a bigger amount or try a different payment method.'))->send();
return;
}
$discount = PartnerDiscount::getDiscount();
// create payment
$payment = Payment::create([
'user_id' => $user->id,
'payment_id' => null,
'payment_method' => 'stripe',
'type' => $shopProduct->type,
'status' => 'open',
'amount' => $shopProduct->quantity,
'price' => $shopProduct->price - ($shopProduct->price * $discount / 100),
'tax_value' => $shopProduct->getTaxValue(),
'total_price' => $shopProduct->getTotalPrice(),
'tax_percent' => $shopProduct->getTaxPercent(),
'currency_code' => $shopProduct->currency_code,
'shop_item_product_id' => $shopProduct->id,
]);
$stripeClient = getStripeClient();
$request = $stripeClient->checkout->sessions->create([
'line_items' => [
[
'price_data' => [
'currency' => $shopProduct->currency_code,
'product_data' => [
'name' => $shopProduct->display . ($discount ? (' (' . __('Discount') . ' ' . $discount . '%)') : ''),
'description' => $shopProduct->description,
],
'unit_amount_decimal' => round($shopProduct->getPriceAfterDiscount() * 100, 2),
],
'quantity' => 1,
],
[
'price_data' => [
'currency' => $shopProduct->currency_code,
'product_data' => [
'name' => __('Tax'),
'description' => $shopProduct->getTaxPercent() . '%',
],
'unit_amount_decimal' => round($shopProduct->getTaxValue(), 2) * 100,
],
'quantity' => 1,
],
],
'mode' => 'payment',
'payment_method_types' => str_getcsv(config('SETTINGS::PAYMENTS:STRIPE:METHODS')),
'success_url' => route('payment.StripeSuccess', ['payment' => $payment->id]) . '&session_id={CHECKOUT_SESSION_ID}',
'cancel_url' => route('payment.Cancel'),
'payment_intent_data' => [
'metadata' => [
'payment_id' => $payment->id,
],
],
]);
Redirect::to($request->url)->send();
}
/**
* @param Request $request
*/
function StripeSuccess(Request $request)
{
$user = Auth::user();
$user = User::findOrFail($user->id);
$payment = Payment::findOrFail($request->input('payment'));
$shopProduct = ShopProduct::findOrFail($payment->shop_item_product_id);
Redirect::route('home')->with('success', 'Please wait for success')->send();
$stripeClient = getStripeClient();
try {
//get stripe data
$paymentSession = $stripeClient->checkout->sessions->retrieve($request->input('session_id'));
$paymentIntent = $stripeClient->paymentIntents->retrieve($paymentSession->payment_intent);
//get DB entry of this payment ID if existing
$paymentDbEntry = Payment::where('payment_id', $paymentSession->payment_intent)->count();
// check if payment is 100% completed and payment does not exist in db already
if ($paymentSession->status == 'complete' && $paymentIntent->status == 'succeeded' && $paymentDbEntry == 0) {
//update payment
$payment->update([
'payment_id' => $paymentSession->payment_intent,
'status' => 'paid',
]);
//payment notification
$user->notify(new ConfirmPaymentNotification($payment));
event(new UserUpdateCreditsEvent($user));
event(new PaymentEvent($user, $payment, $shopProduct));
//redirect back to home
Redirect::route('home')->with('success', 'Payment successful')->send();
} else {
if ($paymentIntent->status == 'processing') {
//update payment
$payment->update([
'payment_id' => $paymentSession->payment_intent,
'status' => 'processing',
]);
event(new PaymentEvent($user, $payment, $shopProduct));
Redirect::route('home')->with('success', 'Your payment is being processed')->send();
}
if ($paymentDbEntry == 0 && $paymentIntent->status != 'processing') {
$stripeClient->paymentIntents->cancel($paymentIntent->id);
//redirect back to home
Redirect::route('home')->with('info', __('Your payment has been canceled!'))->send();
} else {
abort(402);
}
}
} catch (Exception $e) {
if (env('APP_ENV') == 'local') {
dd($e->getMessage());
} else {
abort(422);
}
}
}
/**
* @param Request $request
*/
function handleStripePaymentSuccessHook($paymentIntent)
{
try {
$payment = Payment::where('id', $paymentIntent->metadata->payment_id)->with('user')->first();
$user = User::where('id', $payment->user_id)->first();
$shopProduct = ShopProduct::findOrFail($payment->shop_item_product_id);
if ($paymentIntent->status == 'succeeded' && $payment->status == 'processing') {
//update payment db entry status
$payment->update([
'payment_id' => $payment->payment_id ?? $paymentIntent->id,
'status' => 'paid'
]);
//payment notification
$user->notify(new ConfirmPaymentNotification($payment));
event(new UserUpdateCreditsEvent($user));
event(new PaymentEvent($user, $payment, $shopProduct));
}
// return 200
return response()->json(['success' => true], 200);
} catch (Exception $ex) {
abort(422);
}
}
/**
* @param Request $request
*/
function StripeWebhooks(Request $request)
{
Stripe::setApiKey(getStripeSecret());
try {
$payload = @file_get_contents('php://input');
$sig_header = $request->header('Stripe-Signature');
$event = null;
$event = \Stripe\Webhook::constructEvent(
$payload,
$sig_header,
getStripeEndpointSecret()
);
} catch (\UnexpectedValueException $e) {
// Invalid payload
abort(400);
} catch (SignatureVerificationException $e) {
// Invalid signature
abort(400);
}
// Handle the event
switch ($event->type) {
case 'payment_intent.succeeded':
$paymentIntent = $event->data->object; // contains a \Stripe\PaymentIntent
handleStripePaymentSuccessHook($paymentIntent);
break;
default:
echo 'Received unknown event type ' . $event->type;
}
}
/**
* @return \Stripe\StripeClient
*/
function getStripeClient()
{
return new StripeClient(getStripeSecret());
}
/**
* @return string
*/
function getStripeSecret()
{
return env('APP_ENV') == 'local'
? config('SETTINGS::PAYMENTS:STRIPE:TEST_SECRET')
: config('SETTINGS::PAYMENTS:STRIPE:SECRET');
}
/**
* @return string
*/
function getStripeEndpointSecret()
{
return env('APP_ENV') == 'local'
? config('SETTINGS::PAYMENTS:STRIPE:ENDPOINT_TEST_SECRET')
: config('SETTINGS::PAYMENTS:STRIPE:ENDPOINT_SECRET');
}
/**
* @param $amount
* @param $currencyCode
* @param $payment_method
* @return bool
* @description check if the amount is higher than the minimum amount for the stripe gateway
*/
function checkPriceAmount($amount, $currencyCode, $payment_method)
{
$minimums = [
"USD" => [
"paypal" => 0,
"stripe" => 0.5
],
"AED" => [
"paypal" => 0,
"stripe" => 2
],
"AUD" => [
"paypal" => 0,
"stripe" => 0.5
],
"BGN" => [
"paypal" => 0,
"stripe" => 1
],
"BRL" => [
"paypal" => 0,
"stripe" => 0.5
],
"CAD" => [
"paypal" => 0,
"stripe" => 0.5
],
"CHF" => [
"paypal" => 0,
"stripe" => 0.5
],
"CZK" => [
"paypal" => 0,
"stripe" => 15
],
"DKK" => [
"paypal" => 0,
"stripe" => 2.5
],
"EUR" => [
"paypal" => 0,
"stripe" => 0.5
],
"GBP" => [
"paypal" => 0,
"stripe" => 0.3
],
"HKD" => [
"paypal" => 0,
"stripe" => 4
],
"HRK" => [
"paypal" => 0,
"stripe" => 0.5
],
"HUF" => [
"paypal" => 0,
"stripe" => 175
],
"INR" => [
"paypal" => 0,
"stripe" => 0.5
],
"JPY" => [
"paypal" => 0,
"stripe" => 0.5
],
"MXN" => [
"paypal" => 0,
"stripe" => 10
],
"MYR" => [
"paypal" => 0,
"stripe" => 2
],
"NOK" => [
"paypal" => 0,
"stripe" => 3
],
"NZD" => [
"paypal" => 0,
"stripe" => 0.5
],
"PLN" => [
"paypal" => 0,
"stripe" => 2
],
"RON" => [
"paypal" => 0,
"stripe" => 2
],
"SEK" => [
"paypal" => 0,
"stripe" => 3
],
"SGD" => [
"paypal" => 0,
"stripe" => 0.5
],
"THB" => [
"paypal" => 0,
"stripe" => 10
]
];
return $amount >= $minimums[$currencyCode][$payment_method];
}

View file

@ -1,98 +0,0 @@
<?php
use Spatie\LaravelSettings\Migrations\SettingsMigration;
use Illuminate\Support\Facades\DB;
class CreateStripeSettings extends SettingsMigration
{
public function up(): void
{
$table_exists = DB::table('settings_old')->exists();
$this->migrator->addEncrypted('stripe.secret_key', $table_exists ? $this->getOldValue('SETTINGS::PAYMENTS:STRIPE:SECRET') : null);
$this->migrator->addEncrypted('stripe.endpoint_secret', $table_exists ? $this->getOldValue('SETTINGS::PAYMENTS:STRIPE:ENDPOINT_SECRET') : null);
$this->migrator->addEncrypted('stripe.test_secret_key', $table_exists ? $this->getOldValue('SETTINGS::PAYMENTS:STRIPE:TEST_SECRET') : null);
$this->migrator->addEncrypted('stripe.test_endpoint_secret', $table_exists ? $this->getOldValue('SETTINGS::PAYMENTS:STRIPE:ENDPOINT_TEST_SECRET') : null);
$this->migrator->add('stripe.enabled', false);
}
public function down(): void
{
DB::table('settings_old')->insert([
[
'key' => 'SETTINGS::PAYMENTS:STRIPE:SECRET',
'value' => $this->getNewValue('secret_key'),
'type' => 'string',
'description' => 'The Secret Key of your Stripe App'
],
[
'key' => 'SETTINGS::PAYMENTS:STRIPE:ENDPOINT_SECRET',
'value' => $this->getNewValue('endpoint_secret'),
'type' => 'string',
'description' => 'The Endpoint Secret of your Stripe App'
],
[
'key' => 'SETTINGS::PAYMENTS:STRIPE:TEST_SECRET',
'value' => $this->getNewValue('test_secret_key'),
'type' => 'string',
'description' => 'The Test Secret Key of your Stripe App'
],
[
'key' => 'SETTINGS::PAYMENTS:STRIPE:ENDPOINT_TEST_SECRET',
'value' => $this->getNewValue('test_endpoint_secret'),
'type' => 'string',
'description' => 'The Test Endpoint Secret of your Stripe App'
]
]);
$this->migrator->delete('stripe.secret_key');
$this->migrator->delete('stripe.endpoint_secret');
$this->migrator->delete('stripe.enabled');
$this->migrator->delete('stripe.test_secret_key');
$this->migrator->delete('stripe.test_endpoint_secret');
}
public function getNewValue(string $name)
{
$new_value = DB::table('settings')->where([['group', '=', 'stripe'], ['name', '=', $name]])->get(['payload'])->first();
// Some keys returns '""' as a value.
if ($new_value->payload === '""') {
return null;
}
// remove the quotes from the string
if (substr($new_value->payload, 0, 1) === '"' && substr($new_value->payload, -1) === '"') {
return substr($new_value->payload, 1, -1);
}
return $new_value->payload;
}
public function getOldValue(string $key)
{
// Always get the first value of the key.
$old_value = DB::table('settings_old')->where('key', '=', $key)->get(['value', 'type'])->first();
// Handle the old values to return without it being a string in all cases.
if ($old_value->type === "string" || $old_value->type === "text") {
if (is_null($old_value->value)) {
return '';
}
// Some values have the type string, but their values are boolean.
if ($old_value->value === "false" || $old_value->value === "true") {
return filter_var($old_value->value, FILTER_VALIDATE_BOOL);
}
return $old_value->value;
}
if ($old_value->type === "boolean") {
return filter_var($old_value->value, FILTER_VALIDATE_BOOL);
}
return filter_var($old_value->value, FILTER_VALIDATE_INT);
}
}

View file

@ -1,17 +1,17 @@
<?php <?php
use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Route;
use App\Extensions\PaymentGateways\Stripe\StripeExtension;
include_once(__DIR__ . '/index.php');
Route::middleware(['web', 'auth'])->group(function () { Route::middleware(['web', 'auth'])->group(function () {
Route::get('payment/StripePay/{shopProduct}', function () { Route::get('payment/StripePay/{shopProduct}', function () {
StripeExtension::StripePay(request()); StripePay(request());
})->name('payment.StripePay'); })->name('payment.StripePay');
Route::get( Route::get(
'payment/StripeSuccess', 'payment/StripeSuccess',
function () { function () {
StripeExtension::StripeSuccess(request()); StripeSuccess(request());
} }
)->name('payment.StripeSuccess'); )->name('payment.StripeSuccess');
}); });
@ -19,5 +19,5 @@ Route::middleware(['web', 'auth'])->group(function () {
// Stripe WebhookRoute -> validation in Route Handler // Stripe WebhookRoute -> validation in Route Handler
Route::post('payment/StripeWebhooks', function () { Route::post('payment/StripeWebhooks', function () {
StripeExtension::StripeWebhooks(request()); StripeWebhooks(request());
})->name('payment.StripeWebhooks'); })->name('payment.StripeWebhooks');

View file

@ -1,9 +0,0 @@
<?php
namespace App\Helpers;
// create a abstract class for the extension that will contain all the methods that will be used in the extension
abstract class AbstractExtension
{
abstract public static function getConfig(): array;
}

View file

@ -2,14 +2,65 @@
namespace App\Helpers; namespace App\Helpers;
/**
* Summary of ExtensionHelper
*/
class ExtensionHelper class ExtensionHelper
{ {
/**
* Get a config of an extension by its name
* @param string $extensionName
* @param string $configname
*/
public static function getExtensionConfig(string $extensionName, string $configname)
{
$extensions = ExtensionHelper::getAllExtensions();
// call the getConfig function of the config file of the extension like that
// call_user_func("App\\Extensions\\PaymentGateways\\Stripe" . "\\getConfig");
foreach ($extensions as $extension) {
if (!(basename($extension) == $extensionName)) {
continue;
}
$configFile = $extension . '/config.php';
if (file_exists($configFile)) {
include_once $configFile;
$config = call_user_func('App\\Extensions\\' . basename(dirname($extension)) . '\\' . basename($extension) . "\\getConfig");
}
if (isset($config[$configname])) {
return $config[$configname];
}
}
return null;
}
public static function getAllCsrfIgnoredRoutes()
{
$extensions = ExtensionHelper::getAllExtensions();
$routes = [];
foreach ($extensions as $extension) {
$configFile = $extension . '/config.php';
if (file_exists($configFile)) {
include_once $configFile;
$config = call_user_func('App\\Extensions\\' . basename(dirname($extension)) . '\\' . basename($extension) . "\\getConfig");
}
if (isset($config['RoutesIgnoreCsrf'])) {
$routes = array_merge($routes, $config['RoutesIgnoreCsrf']);
}
// map over the routes and add the extension name as prefix
$result = array_map(fn ($item) => "extensions/{$item}", $routes);
}
return $result;
}
/** /**
* Get all extensions * Get all extensions
* @return array array of all extensions e.g. ["App\Extensions\PayPal", "App\Extensions\Stripe"] * @return array
*/ */
public static function getAllExtensions() public static function getAllExtensions()
{ {
@ -18,195 +69,14 @@ class ExtensionHelper
foreach ($extensionNamespaces as $extensionNamespace) { foreach ($extensionNamespaces as $extensionNamespace) {
$extensions = array_merge($extensions, glob($extensionNamespace . '/*', GLOB_ONLYDIR)); $extensions = array_merge($extensions, glob($extensionNamespace . '/*', GLOB_ONLYDIR));
} }
// remove base path from every extension but keep app/Extensions/...
$extensions = array_map(fn ($item) => str_replace('/', '\\', str_replace(app_path() . '/', 'App/', $item)), $extensions);
return $extensions; return $extensions;
} }
/**
* Get all extensions by namespace
* @param string $namespace case sensitive namespace of the extension e.g. PaymentGateways
* @return array array of all extensions e.g. ["App\Extensions\PayPal", "App\Extensions\Stripe"]
*/
public static function getAllExtensionsByNamespace(string $namespace) public static function getAllExtensionsByNamespace(string $namespace)
{ {
$extensions = glob(app_path() . '/Extensions/' . $namespace . '/*', GLOB_ONLYDIR); $extensions = glob(app_path() . '/Extensions/' . $namespace . '/*', GLOB_ONLYDIR);
// remove base path from every extension but keep app/Extensions/...
$extensions = array_map(fn ($item) => str_replace('/', '\\', str_replace(app_path() . '/', 'App/', $item)), $extensions);
return $extensions; return $extensions;
} }
/**
* Get an extension by its name
* @param string $extensionName case sensitive name of the extension e.g. PayPal
* @return string|null the path of the extension e.g. App\Extensions\PayPal
*/
public static function getExtension(string $extensionName)
{
$extensions = self::getAllExtensions();
// filter the extensions by the extension name
$extensions = array_filter($extensions, fn ($item) => basename($item) == $extensionName);
// return the only extension
return array_shift($extensions);
}
/**
* Get all extension classes
* @return array array of all extension classes e.g. ["App\Extensions\PayPal\PayPalExtension", "App\Extensions\Stripe\StripeExtension"]
*/
public static function getAllExtensionClasses()
{
$extensions = self::getAllExtensions();
// add the ExtensionClass to the end of the namespace
$extensions = array_map(fn ($item) => $item . '\\' . basename($item) . 'Extension', $extensions);
// filter out non existing extension classes
$extensions = array_filter($extensions, fn ($item) => class_exists($item));
return $extensions;
}
/**
* Get all extension classes by namespace
* @param string $namespace case sensitive namespace of the extension e.g. PaymentGateways
* @return array array of all extension classes e.g. ["App\Extensions\PayPal\PayPalExtension", "App\Extensions\Stripe\StripeExtension"]
*/
public static function getAllExtensionClassesByNamespace(string $namespace)
{
$extensions = self::getAllExtensionsByNamespace($namespace);
// add the ExtensionClass to the end of the namespace
$extensions = array_map(fn ($item) => $item . '\\' . basename($item) . 'Extension', $extensions);
// filter out non existing extension classes
$extensions = array_filter($extensions, fn ($item) => class_exists($item));
return $extensions;
}
/**
* Get the class of an extension by its name
* @param string $extensionName case sensitive name of the extension e.g. PayPal
* @return string|null the class name of the extension e.g. App\Extensions\PayPal\PayPalExtension
*/
public static function getExtensionClass(string $extensionName)
{
$extensions = self::getAllExtensions();
foreach ($extensions as $extension) {
if (!(basename($extension) == $extensionName)) {
continue;
}
$extensionClass = $extension . '\\' . $extensionName . 'Extension';
return $extensionClass;
}
}
/**
* Get a config of an extension by its name
* @param string $extensionName
* @param string $configname
*/
public static function getExtensionConfig(string $extensionName, string $configname)
{
$extension = self::getExtensionClass($extensionName);
$config = $extension::getConfig();
if (isset($config[$configname])) {
return $config[$configname];
}
return null;
}
public static function getAllCsrfIgnoredRoutes()
{
$extensions = self::getAllExtensionClasses();
$routes = [];
foreach ($extensions as $extension) {
$config = $extension::getConfig();
if (isset($config['RoutesIgnoreCsrf'])) {
$routes = array_merge($routes, $config['RoutesIgnoreCsrf']);
}
}
// map over the routes and add the extension name as prefix
$result = array_map(fn ($item) => "extensions/{$item}", $routes);
return $result;
}
/**
* Summary of getAllExtensionMigrations
* @return array of all migration paths look like: app/Extensions/ExtensionNamespace/ExtensionName/migrations/
*/
public static function getAllExtensionMigrations()
{
$extensions = self::getAllExtensions();
// Transform the extensions to a path
$extensions = array_map(fn ($item) => self::extensionNameToPath($item), $extensions);
// get all migration directories of the extensions and return them as array
$migrations = [];
foreach ($extensions as $extension) {
$migrationDir = $extension . '/migrations';
if (file_exists($migrationDir)) {
$migrations[] = $migrationDir;
}
}
return $migrations;
}
/**
* Summary of getAllExtensionSettings
* @return array of all setting classes look like: App\Extensions\PaymentGateways\PayPal\PayPalSettings
*/
public static function getAllExtensionSettingsClasses()
{
$extensions = self::getAllExtensions();
$settings = [];
foreach ($extensions as $extension) {
$extensionName = basename($extension);
$settingsClass = $extension . '\\' . $extensionName . 'Settings';
if (class_exists($settingsClass)) {
$settings[] = $settingsClass;
}
}
return $settings;
}
public static function getExtensionSettings(string $extensionName)
{
$extension = self::getExtension($extensionName);
$settingClass = $extension . '\\' . $extensionName . 'Settings';
if (class_exists($settingClass)) {
return new $settingClass();
}
}
/**
* Transforms a extension name to a path
* @param string $extensionName e.g. App\Extensions\PaymentGateways\PayPal
* @return string e.g. C:\xampp\htdocs\laravel\app/Extensions/PaymentGateways/PayPal
*/
private static function extensionNameToPath(string $extensionName)
{
return app_path() . '/' . str_replace('\\', '/', str_replace('App\\', '', $extensionName));
}
} }

View file

@ -4,7 +4,6 @@ namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Models\ApplicationApi; use App\Models\ApplicationApi;
use App\Settings\LocaleSettings;
use Exception; use Exception;
use Illuminate\Contracts\Foundation\Application; use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory; use Illuminate\Contracts\View\Factory;
@ -21,11 +20,9 @@ class ApplicationApiController extends Controller
* *
* @return Application|Factory|View|Response * @return Application|Factory|View|Response
*/ */
public function index(LocaleSettings $locale_settings) public function index()
{ {
return view('admin.api.index', [ return view('admin.api.index');
'locale_datatables' => $locale_settings->datatables
]);
} }
/** /**

View file

@ -15,7 +15,7 @@ class InvoiceController extends Controller
$zip = new ZipArchive; $zip = new ZipArchive;
$zip_safe_path = storage_path('invoices.zip'); $zip_safe_path = storage_path('invoices.zip');
$res = $zip->open($zip_safe_path, ZipArchive::CREATE | ZipArchive::OVERWRITE); $res = $zip->open($zip_safe_path, ZipArchive::CREATE | ZipArchive::OVERWRITE);
$result = $this->rglob(storage_path('app/invoice/*')); $result = $this::rglob(storage_path('app/invoice/*'));
if ($res === true) { if ($res === true) {
$zip->addFromString('1. Info.txt', __('Created at').' '.now()->format('d.m.Y')); $zip->addFromString('1. Info.txt', __('Created at').' '.now()->format('d.m.Y'));
foreach ($result as $file) { foreach ($result as $file) {
@ -38,7 +38,7 @@ class InvoiceController extends Controller
{ {
$files = glob($pattern, $flags); $files = glob($pattern, $flags);
foreach (glob(dirname($pattern).'/*', GLOB_ONLYDIR | GLOB_NOSORT) as $dir) { foreach (glob(dirname($pattern).'/*', GLOB_ONLYDIR | GLOB_NOSORT) as $dir) {
$files = array_merge($files, $this->rglob($dir.'/'.basename($pattern), $flags)); $files = array_merge($files, $this::rglob($dir.'/'.basename($pattern), $flags));
} }
return $files; return $files;

View file

@ -2,14 +2,12 @@
namespace App\Http\Controllers\Admin; namespace App\Http\Controllers\Admin;
use App\Classes\PterodactylClient; use App\Classes\Pterodactyl;
use App\Settings\PterodactylSettings;
use App\Settings\GeneralSettings;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Models\Pterodactyl\Egg; use App\Models\Egg;
use App\Models\Pterodactyl\Location; use App\Models\Location;
use App\Models\Pterodactyl\Nest; use App\Models\Nest;
use App\Models\Pterodactyl\Node; use App\Models\Node;
use App\Models\Payment; use App\Models\Payment;
use App\Models\Product; use App\Models\Product;
use App\Models\Server; use App\Models\Server;
@ -21,14 +19,7 @@ class OverViewController extends Controller
{ {
public const TTL = 86400; public const TTL = 86400;
private $pterodactyl; public function index()
public function __construct(PterodactylSettings $ptero_settings)
{
$this->pterodactyl = new PterodactylClient($ptero_settings);
}
public function index(GeneralSettings $general_settings)
{ {
//Get counters //Get counters
$counters = collect(); $counters = collect();
@ -143,7 +134,7 @@ class OverViewController extends Controller
//Get node information and prepare collection //Get node information and prepare collection
$pteroNodeIds = []; $pteroNodeIds = [];
foreach ($this->pterodactyl->getNodes() as $pteroNode) { foreach (Pterodactyl::getNodes() as $pteroNode) {
array_push($pteroNodeIds, $pteroNode['attributes']['id']); array_push($pteroNodeIds, $pteroNode['attributes']['id']);
} }
$nodes = collect(); $nodes = collect();
@ -154,7 +145,7 @@ class OverViewController extends Controller
} //Check if node exists on pterodactyl too, if not, skip } //Check if node exists on pterodactyl too, if not, skip
$nodes->put($nodeId, collect()); $nodes->put($nodeId, collect());
$nodes[$nodeId]->name = $DBnode['name']; $nodes[$nodeId]->name = $DBnode['name'];
$pteroNode = $this->pterodactyl->getNode($nodeId); $pteroNode = Pterodactyl::getNode($nodeId);
$nodes[$nodeId]->usagePercent = round(max($pteroNode['allocated_resources']['memory'] / ($pteroNode['memory'] * ($pteroNode['memory_overallocate'] + 100) / 100), $pteroNode['allocated_resources']['disk'] / ($pteroNode['disk'] * ($pteroNode['disk_overallocate'] + 100) / 100)) * 100, 2); $nodes[$nodeId]->usagePercent = round(max($pteroNode['allocated_resources']['memory'] / ($pteroNode['memory'] * ($pteroNode['memory_overallocate'] + 100) / 100), $pteroNode['allocated_resources']['disk'] / ($pteroNode['disk'] * ($pteroNode['disk_overallocate'] + 100) / 100)) * 100, 2);
$counters['totalUsagePercent'] += $nodes[$nodeId]->usagePercent; $counters['totalUsagePercent'] += $nodes[$nodeId]->usagePercent;
@ -165,7 +156,7 @@ class OverViewController extends Controller
} }
$counters['totalUsagePercent'] = ($DBnodes->count()) ? round($counters['totalUsagePercent'] / $DBnodes->count(), 2) : 0; $counters['totalUsagePercent'] = ($DBnodes->count()) ? round($counters['totalUsagePercent'] / $DBnodes->count(), 2) : 0;
foreach ($this->pterodactyl->getServers() as $server) { //gets all servers from Pterodactyl and calculates total of credit usage for each node separately + total foreach (Pterodactyl::getServers() as $server) { //gets all servers from Pterodactyl and calculates total of credit usage for each node separately + total
$nodeId = $server['attributes']['node']; $nodeId = $server['attributes']['node'];
if ($CPServer = Server::query()->where('pterodactyl_id', $server['attributes']['id'])->first()) { if ($CPServer = Server::query()->where('pterodactyl_id', $server['attributes']['id'])->first()) {
@ -216,7 +207,6 @@ class OverViewController extends Controller
'deletedNodesPresent' => ($DBnodes->count() != count($pteroNodeIds)) ? true : false, 'deletedNodesPresent' => ($DBnodes->count() != count($pteroNodeIds)) ? true : false,
'perPageLimit' => ($counters['servers']->total != Server::query()->count()) ? true : false, 'perPageLimit' => ($counters['servers']->total != Server::query()->count()) ? true : false,
'tickets' => $tickets, 'tickets' => $tickets,
'credits_display_name' => $general_settings->credits_display_name
]); ]);
} }

View file

@ -5,17 +5,13 @@ namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Models\PartnerDiscount; use App\Models\PartnerDiscount;
use App\Models\User; use App\Models\User;
use App\Settings\LocaleSettings;
use App\Settings\ReferralSettings;
use Illuminate\Http\Request; use Illuminate\Http\Request;
class PartnerController extends Controller class PartnerController extends Controller
{ {
public function index(LocaleSettings $locale_settings) public function index()
{ {
return view('admin.partners.index', [ return view('admin.partners.index');
'locale_datatables' => $locale_settings->datatables
]);
} }
/** /**
@ -132,8 +128,8 @@ class PartnerController extends Controller
->editColumn('registered_user_discount', function (PartnerDiscount $partner) { ->editColumn('registered_user_discount', function (PartnerDiscount $partner) {
return $partner->registered_user_discount ? $partner->registered_user_discount.'%' : '0%'; return $partner->registered_user_discount ? $partner->registered_user_discount.'%' : '0%';
}) })
->editColumn('referral_system_commission', function (PartnerDiscount $partner, ReferralSettings $referral_settings) { ->editColumn('referral_system_commission', function (PartnerDiscount $partner) {
return $partner->referral_system_commission >= 0 ? $partner->referral_system_commission . '%' : __('Default') . ' ('.$referral_settings->percentage . '%)'; return $partner->referral_system_commission >= 0 ? $partner->referral_system_commission.'%' : __('Default').' ('.config('SETTINGS::REFERRAL:PERCENTAGE').'%)';
}) })
->rawColumns(['user', 'actions']) ->rawColumns(['user', 'actions'])
->make(); ->make();

View file

@ -18,19 +18,17 @@ use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use App\Helpers\ExtensionHelper; use App\Helpers\ExtensionHelper;
use App\Settings\GeneralSettings;
use App\Settings\LocaleSettings;
class PaymentController extends Controller class PaymentController extends Controller
{ {
/** /**
* @return Application|Factory|View * @return Application|Factory|View
*/ */
public function index(LocaleSettings $locale_settings) public function index()
{ {
return view('admin.payments.index')->with([ return view('admin.payments.index')->with([
'payments' => Payment::paginate(15), 'payments' => Payment::paginate(15),
'locale_datatables' => $locale_settings->datatables
]); ]);
} }
@ -39,7 +37,7 @@ class PaymentController extends Controller
* @param ShopProduct $shopProduct * @param ShopProduct $shopProduct
* @return Application|Factory|View * @return Application|Factory|View
*/ */
public function checkOut(ShopProduct $shopProduct, GeneralSettings $general_settings) public function checkOut(ShopProduct $shopProduct)
{ {
$discount = PartnerDiscount::getDiscount(); $discount = PartnerDiscount::getDiscount();
$price = $shopProduct->price - ($shopProduct->price * $discount / 100); $price = $shopProduct->price - ($shopProduct->price * $discount / 100);
@ -51,10 +49,7 @@ class PaymentController extends Controller
// build a paymentgateways array that contains the routes for the payment gateways and the image path for the payment gateway which lays in public/images/Extensions/PaymentGateways with the extensionname in lowercase // build a paymentgateways array that contains the routes for the payment gateways and the image path for the payment gateway which lays in public/images/Extensions/PaymentGateways with the extensionname in lowercase
foreach ($extensions as $extension) { foreach ($extensions as $extension) {
$extensionName = basename($extension); $extensionName = basename($extension);
if (!ExtensionHelper::getExtensionConfig($extensionName, 'enabled')) continue; // skip if not enabled
$extensionSettings = ExtensionHelper::getExtensionSettings($extensionName);
if ($extensionSettings->enabled == false) continue;
$payment = new \stdClass(); $payment = new \stdClass();
$payment->name = ExtensionHelper::getExtensionConfig($extensionName, 'name'); $payment->name = ExtensionHelper::getExtensionConfig($extensionName, 'name');
@ -63,6 +58,11 @@ class PaymentController extends Controller
} }
} }
return view('store.checkout')->with([ return view('store.checkout')->with([
'product' => $shopProduct, 'product' => $shopProduct,
'discountpercent' => $discount, 'discountpercent' => $discount,
@ -73,7 +73,6 @@ class PaymentController extends Controller
'total' => $shopProduct->getTotalPrice(), 'total' => $shopProduct->getTotalPrice(),
'paymentGateways' => $paymentGateways, 'paymentGateways' => $paymentGateways,
'productIsFree' => $price <= 0, 'productIsFree' => $price <= 0,
'credits_display_name' => $general_settings->credits_display_name
]); ]);
} }

View file

@ -3,12 +3,9 @@
namespace App\Http\Controllers\Admin; namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Models\Pterodactyl\Location; use App\Models\Location;
use App\Models\Pterodactyl\Nest; use App\Models\Nest;
use App\Models\Product; use App\Models\Product;
use App\Settings\GeneralSettings;
use App\Settings\LocaleSettings;
use App\Settings\UserSettings;
use Exception; use Exception;
use Illuminate\Contracts\Foundation\Application; use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory; use Illuminate\Contracts\View\Factory;
@ -24,11 +21,9 @@ class ProductController extends Controller
* *
* @return Application|Factory|View * @return Application|Factory|View
*/ */
public function index(LocaleSettings $locale_settings) public function index()
{ {
return view('admin.products.index', [ return view('admin.products.index');
'locale_datatables' => $locale_settings->datatables
]);
} }
/** /**
@ -36,16 +31,15 @@ class ProductController extends Controller
* *
* @return Application|Factory|View * @return Application|Factory|View
*/ */
public function create(GeneralSettings $general_settings) public function create()
{ {
return view('admin.products.create', [ return view('admin.products.create', [
'locations' => Location::with('nodes')->get(), 'locations' => Location::with('nodes')->get(),
'nests' => Nest::with('eggs')->get(), 'nests' => Nest::with('eggs')->get(),
'credits_display_name' => $general_settings->credits_display_name
]); ]);
} }
public function clone(Product $product) public function clone(Request $request, Product $product)
{ {
return view('admin.products.create', [ return view('admin.products.create', [
'product' => $product, 'product' => $product,
@ -96,12 +90,11 @@ class ProductController extends Controller
* @param Product $product * @param Product $product
* @return Application|Factory|View * @return Application|Factory|View
*/ */
public function show(Product $product, UserSettings $user_settings, GeneralSettings $general_settings) public function show(Product $product)
{ {
return view('admin.products.show', [ return view('admin.products.show', [
'product' => $product, 'product' => $product,
'minimum_credits' => $user_settings->min_credits_to_make_server, 'minimum_credits' => config('SETTINGS::USER:MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER'),
'credits_display_name' => $general_settings->credits_display_name
]); ]);
} }
@ -111,13 +104,12 @@ class ProductController extends Controller
* @param Product $product * @param Product $product
* @return Application|Factory|View * @return Application|Factory|View
*/ */
public function edit(Product $product, GeneralSettings $general_settings) public function edit(Product $product)
{ {
return view('admin.products.edit', [ return view('admin.products.edit', [
'product' => $product, 'product' => $product,
'locations' => Location::with('nodes')->get(), 'locations' => Location::with('nodes')->get(),
'nests' => Nest::with('eggs')->get(), 'nests' => Nest::with('eggs')->get(),
'credits_display_name' => $general_settings->credits_display_name
]); ]);
} }
@ -165,7 +157,7 @@ class ProductController extends Controller
* @param Product $product * @param Product $product
* @return RedirectResponse * @return RedirectResponse
*/ */
public function disable(Product $product) public function disable(Request $request, Product $product)
{ {
$product->update(['disabled' => ! $product->disabled]); $product->update(['disabled' => ! $product->disabled]);
@ -198,6 +190,7 @@ class ProductController extends Controller
public function dataTable() public function dataTable()
{ {
$query = Product::with(['servers']); $query = Product::with(['servers']);
return datatables($query) return datatables($query)
->addColumn('actions', function (Product $product) { ->addColumn('actions', function (Product $product) {
return ' return '
@ -236,8 +229,8 @@ class ProductController extends Controller
</form> </form>
'; ';
}) })
->editColumn('minimum_credits', function (Product $product, UserSettings $user_settings) { ->editColumn('minimum_credits', function (Product $product) {
return $product->minimum_credits==-1 ? $user_settings->min_credits_to_make_server : $product->minimum_credits; return $product->minimum_credits==-1 ? config('SETTINGS::USER:MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER') : $product->minimum_credits;
}) })
->editColumn('created_at', function (Product $product) { ->editColumn('created_at', function (Product $product) {
return $product->created_at ? $product->created_at->diffForHumans() : ''; return $product->created_at ? $product->created_at->diffForHumans() : '';

View file

@ -2,12 +2,10 @@
namespace App\Http\Controllers\Admin; namespace App\Http\Controllers\Admin;
use App\Classes\Pterodactyl;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Models\Server; use App\Models\Server;
use App\Models\User; use App\Models\User;
use App\Settings\LocaleSettings;
use App\Settings\PterodactylSettings;
use App\Classes\PterodactylClient;
use Exception; use Exception;
use Illuminate\Contracts\Foundation\Application; use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory; use Illuminate\Contracts\View\Factory;
@ -20,23 +18,14 @@ use Illuminate\Support\Facades\Log;
class ServerController extends Controller class ServerController extends Controller
{ {
private $pterodactyl;
public function __construct(PterodactylSettings $ptero_settings)
{
$this->pterodactyl = new PterodactylClient($ptero_settings);
}
/** /**
* Display a listing of the resource. * Display a listing of the resource.
* *
* @return Application|Factory|View|Response * @return Application|Factory|View|Response
*/ */
public function index(LocaleSettings $locale_settings) public function index()
{ {
return view('admin.servers.index', [ return view('admin.servers.index');
'locale_datatables' => $locale_settings->datatables
]);
} }
/** /**
@ -76,7 +65,7 @@ class ServerController extends Controller
// try to update the owner on pterodactyl // try to update the owner on pterodactyl
try { try {
$response = $this->pterodactyl->updateServerOwner($server, $user->pterodactyl_id); $response = Pterodactyl::updateServerOwner($server, $user->pterodactyl_id);
if ($response->getStatusCode() != 200) { if ($response->getStatusCode() != 200) {
return redirect()->back()->with('error', 'Failed to update server owner on pterodactyl'); return redirect()->back()->with('error', 'Failed to update server owner on pterodactyl');
} }
@ -129,6 +118,7 @@ class ServerController extends Controller
public function syncServers() public function syncServers()
{ {
$pteroServers = Pterodactyl::getServers();
$CPServers = Server::get(); $CPServers = Server::get();
$CPIDArray = []; $CPIDArray = [];
@ -139,7 +129,7 @@ class ServerController extends Controller
} }
} }
foreach ($this->pterodactyl->getServers() as $server) { //go thru all ptero servers, if server exists, change value to true in array. foreach ($pteroServers as $server) { //go thru all ptero servers, if server exists, change value to true in array.
if (isset($CPIDArray[$server['attributes']['id']])) { if (isset($CPIDArray[$server['attributes']['id']])) {
$CPIDArray[$server['attributes']['id']] = true; $CPIDArray[$server['attributes']['id']] = true;
@ -159,7 +149,7 @@ class ServerController extends Controller
}, ARRAY_FILTER_USE_BOTH); //Array of servers, that dont exist on ptero (value == false) }, ARRAY_FILTER_USE_BOTH); //Array of servers, that dont exist on ptero (value == false)
$deleteCount = 0; $deleteCount = 0;
foreach ($filteredArray as $key => $CPID) { //delete servers that dont exist on ptero anymore foreach ($filteredArray as $key => $CPID) { //delete servers that dont exist on ptero anymore
if (!$this->pterodactyl->getServerAttributes($key, true)) { if (!Pterodactyl::getServerAttributes($key, true)) {
$deleteCount++; $deleteCount++;
} }
} }
@ -226,8 +216,8 @@ class ServerController extends Controller
->editColumn('suspended', function (Server $server) { ->editColumn('suspended', function (Server $server) {
return $server->suspended ? $server->suspended->diffForHumans() : ''; return $server->suspended ? $server->suspended->diffForHumans() : '';
}) })
->editColumn('name', function (Server $server, PterodactylSettings $ptero_settings) { ->editColumn('name', function (Server $server) {
return '<a class="text-info" target="_blank" href="' . $ptero_settings->panel_url . '/admin/servers/view/' . $server->pterodactyl_id . '">' . strip_tags($server->name) . '</a>'; return '<a class="text-info" target="_blank" href="' . config('SETTINGS::SYSTEM:PTERODACTYL:URL') . '/admin/servers/view/' . $server->pterodactyl_id . '">' . strip_tags($server->name) . '</a>';
}) })
->rawColumns(['user', 'actions', 'status', 'name']) ->rawColumns(['user', 'actions', 'status', 'name'])
->make(); ->make();

View file

@ -2,15 +2,11 @@
namespace App\Http\Controllers\Admin; namespace App\Http\Controllers\Admin;
use App\Helpers\ExtensionHelper;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use Illuminate\Contracts\Foundation\Application; use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory; use Illuminate\Contracts\View\Factory;
use Illuminate\Contracts\View\View; use Illuminate\Contracts\View\View;
use Illuminate\Http\Response; use Illuminate\Http\Response;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\Validator;
use Qirolab\Theme\Theme; use Qirolab\Theme\Theme;
class SettingsController extends Controller class SettingsController extends Controller
@ -23,109 +19,37 @@ class SettingsController extends Controller
public function index() public function index()
{ {
// get all other settings in app/Settings directory
// group items by file name like $categories
$settings = collect();
$settings_classes = [];
// get all app settings //Get all tabs as laravel view paths
$app_settings = scandir(app_path('Settings')); $tabs = [];
$app_settings = array_diff($app_settings, ['.', '..']); if(file_exists(Theme::getViewPaths()[0] . '/admin/settings/tabs/')){
// append App\Settings to class name $tabspath = glob(Theme::getViewPaths()[0] . '/admin/settings/tabs/*.blade.php');
foreach ($app_settings as $app_setting) {
$settings_classes[] = 'App\\Settings\\' . str_replace('.php', '', $app_setting);
}
// get all extension settings
$settings_files = array_merge($settings_classes, ExtensionHelper::getAllExtensionSettingsClasses());
foreach ($settings_files as $file) {
$className = $file;
// instantiate the class and call toArray method to get all options
$options = (new $className())->toArray();
// call getOptionInputData method to get all options
if (method_exists($className, 'getOptionInputData')) {
$optionInputData = $className::getOptionInputData();
}else{ }else{
$optionInputData = []; $tabspath = glob(Theme::path($path = 'views', $themeName = 'default').'/admin/settings/tabs/*.blade.php');
} }
// collect all option input data foreach ($tabspath as $filename) {
$optionsData = []; $tabs[] = 'admin.settings.tabs.'.basename($filename, '.blade.php');
foreach ($options as $key => $value) {
$optionsData[$key] = [
'value' => $value,
'label' => $optionInputData[$key]['label'] ?? ucwords(str_replace('_', ' ', $key)),
'type' => $optionInputData[$key]['type'] ?? 'string',
'description' => $optionInputData[$key]['description'] ?? '',
'options' => $optionInputData[$key]['options'] ?? [],
];
} }
// collect category icon if available
if (isset($optionInputData['category_icon'])) { //Generate a html list item for each tab based on tabs file basename, set first tab as active
$optionsData['category_icon'] = $optionInputData['category_icon']; $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>';
} }
$optionsData['settings_class'] = $className;
$settings[str_replace('Settings', '', class_basename($className))] = $optionsData;
}
$settings->sort();
$themes = array_diff(scandir(base_path('themes')), array('..', '.')); $themes = array_diff(scandir(base_path('themes')), array('..', '.'));
return view('admin.settings.index', [ return view('admin.settings.index', [
'settings' => $settings->all(), 'tabs' => $tabs,
'tabListItems' => $tabListItems,
'themes' => $themes, 'themes' => $themes,
'active_theme' => Theme::active(), 'active_theme' => Theme::active(),
]); ]);
} }
/**
* Update the specified resource in storage.
*
*/
public function update(Request $request)
{
$category = request()->get('category');
$settings_class = request()->get('settings_class');
if (method_exists($settings_class, 'getValidations')) {
$validations = $settings_class::getValidations();
} else {
$validations = [];
}
$validator = Validator::make($request->all(), $validations);
if ($validator->fails()) {
return Redirect::to('admin/settings' . '#' . $category)->withErrors($validator)->withInput();
}
$settingsClass = new $settings_class();
foreach ($settingsClass->toArray() as $key => $value) {
// Get the type of the settingsclass property
$rp = new \ReflectionProperty($settingsClass, $key);
$rpType = $rp->getType();
if ($rpType == 'bool') {
$settingsClass->$key = $request->has($key);
continue;
}
$nullable = $rpType->allowsNull();
if ($nullable) $settingsClass->$key = $request->input($key) ?? null;
else $settingsClass->$key = $request->input($key);
}
$settingsClass->save();
return Redirect::to('admin/settings' . '#' . $category)->with('success', 'Settings updated successfully.');
}
} }

View file

@ -3,8 +3,6 @@
namespace App\Http\Controllers\Admin; namespace App\Http\Controllers\Admin;
use App\Models\ShopProduct; use App\Models\ShopProduct;
use App\Settings\GeneralSettings;
use App\Settings\LocaleSettings;
use Illuminate\Contracts\Foundation\Application; use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory; use Illuminate\Contracts\View\Factory;
use Illuminate\Contracts\View\View; use Illuminate\Contracts\View\View;
@ -22,14 +20,20 @@ class ShopProductController extends Controller
* *
* @return Application|Factory|View|Response * @return Application|Factory|View|Response
*/ */
public function index(LocaleSettings $locale_settings, GeneralSettings $general_settings) public function index(Request $request)
{ {
$isStoreEnabled = $general_settings->store_enabled; $isPaymentSetup = false;
if (
env('APP_ENV') == 'local' ||
config('SETTINGS::PAYMENTS:PAYPAL:SECRET') && config('SETTINGS::PAYMENTS:PAYPAL:CLIENT_ID') ||
config('SETTINGS::PAYMENTS:STRIPE:SECRET') && config('SETTINGS::PAYMENTS:STRIPE:ENDPOINT_SECRET') && config('SETTINGS::PAYMENTS:STRIPE:METHODS')
) {
$isPaymentSetup = true;
}
return view('admin.store.index', [ return view('admin.store.index', [
'isStoreEnabled' => $isStoreEnabled, 'isPaymentSetup' => $isPaymentSetup,
'locale_datatables' => $locale_settings->datatables
]); ]);
} }
@ -38,11 +42,10 @@ class ShopProductController extends Controller
* *
* @return Application|Factory|View|Response * @return Application|Factory|View|Response
*/ */
public function create(GeneralSettings $general_settings) public function create()
{ {
return view('admin.store.create', [ return view('admin.store.create', [
'currencyCodes' => config('currency_codes'), 'currencyCodes' => config('currency_codes'),
'credits_display_name' => $general_settings->credits_display_name
]); ]);
} }
@ -76,12 +79,11 @@ class ShopProductController extends Controller
* @param ShopProduct $shopProduct * @param ShopProduct $shopProduct
* @return Application|Factory|View|Response * @return Application|Factory|View|Response
*/ */
public function edit(ShopProduct $shopProduct, GeneralSettings $general_settings) public function edit(ShopProduct $shopProduct)
{ {
return view('admin.store.edit', [ return view('admin.store.edit', [
'currencyCodes' => config('currency_codes'), 'currencyCodes' => config('currency_codes'),
'shopProduct' => $shopProduct, 'shopProduct' => $shopProduct,
'credits_display_name' => $general_settings->credits_display_name
]); ]);
} }
@ -115,7 +117,7 @@ class ShopProductController extends Controller
* @param ShopProduct $shopProduct * @param ShopProduct $shopProduct
* @return RedirectResponse * @return RedirectResponse
*/ */
public function disable(ShopProduct $shopProduct) public function disable(Request $request, ShopProduct $shopProduct)
{ {
$shopProduct->update(['disabled' => !$shopProduct->disabled]); $shopProduct->update(['disabled' => !$shopProduct->disabled]);

View file

@ -5,7 +5,6 @@ namespace App\Http\Controllers\Admin;
use App\Enums\UsefulLinkLocation; use App\Enums\UsefulLinkLocation;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Models\UsefulLink; use App\Models\UsefulLink;
use App\Settings\LocaleSettings;
use Illuminate\Contracts\Foundation\Application; use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory; use Illuminate\Contracts\View\Factory;
use Illuminate\Contracts\View\View; use Illuminate\Contracts\View\View;
@ -20,11 +19,9 @@ class UsefulLinkController extends Controller
* *
* @return Application|Factory|View|Response * @return Application|Factory|View|Response
*/ */
public function index(LocaleSettings $locale_settings) public function index()
{ {
return view('admin.usefullinks.index', [ return view('admin.usefullinks.index');
'locale_datatables' => $locale_settings->datatables
]);
} }
/** /**

View file

@ -2,14 +2,11 @@
namespace App\Http\Controllers\Admin; namespace App\Http\Controllers\Admin;
use App\Classes\Pterodactyl;
use App\Events\UserUpdateCreditsEvent; use App\Events\UserUpdateCreditsEvent;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Models\User; use App\Models\User;
use App\Notifications\DynamicNotification; use App\Notifications\DynamicNotification;
use App\Settings\LocaleSettings;
use App\Settings\PterodactylSettings;
use App\Classes\PterodactylClient;
use App\Settings\GeneralSettings;
use Exception; use Exception;
use Illuminate\Contracts\Foundation\Application; use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory; use Illuminate\Contracts\View\Factory;
@ -29,11 +26,12 @@ use Spatie\QueryBuilder\QueryBuilder;
class UserController extends Controller class UserController extends Controller
{ {
private $pterodactyl;
public function __construct(PterodactylSettings $ptero_settings) private Pterodactyl $pterodactyl;
public function __construct(Pterodactyl $pterodactyl)
{ {
$this->pterodactyl = new PterodactylClient($ptero_settings); $this->pterodactyl = $pterodactyl;
} }
/** /**
@ -42,12 +40,9 @@ class UserController extends Controller
* @param Request $request * @param Request $request
* @return Application|Factory|View|Response * @return Application|Factory|View|Response
*/ */
public function index(LocaleSettings $locale_settings, GeneralSettings $general_settings) public function index(Request $request)
{ {
return view('admin.users.index', [ return view('admin.users.index');
'locale_datatables' => $locale_settings->datatables,
'credits_display_name' => $general_settings->credits_display_name
]);
} }
/** /**
@ -56,7 +51,7 @@ class UserController extends Controller
* @param User $user * @param User $user
* @return Application|Factory|View|Response * @return Application|Factory|View|Response
*/ */
public function show(User $user, LocaleSettings $locale_settings, GeneralSettings $general_settings) public function show(User $user)
{ {
//QUERY ALL REFERRALS A USER HAS //QUERY ALL REFERRALS A USER HAS
//i am not proud of this at all. //i am not proud of this at all.
@ -70,8 +65,6 @@ class UserController extends Controller
return view('admin.users.show')->with([ return view('admin.users.show')->with([
'user' => $user, 'user' => $user,
'referrals' => $allReferals, 'referrals' => $allReferals,
'locale_datatables' => $locale_settings->datatables,
'credits_display_name' => $general_settings->credits_display_name
]); ]);
} }
@ -106,11 +99,10 @@ class UserController extends Controller
* @param User $user * @param User $user
* @return Application|Factory|View|Response * @return Application|Factory|View|Response
*/ */
public function edit(User $user, GeneralSettings $general_settings) public function edit(User $user)
{ {
return view('admin.users.edit')->with([ return view('admin.users.edit')->with([
'user' => $user, 'user' => $user,
'credits_display_name' => $general_settings->credits_display_name
]); ]);
} }
@ -166,10 +158,6 @@ class UserController extends Controller
*/ */
public function destroy(User $user) public function destroy(User $user)
{ {
if ($user->role === 'admin' && User::query()->where('role', 'admin')->count() === 1) {
return redirect()->back()->with('error', __('You can not delete the last admin!'));
}
$user->delete(); $user->delete();
return redirect()->back()->with('success', __('user has been removed!')); return redirect()->back()->with('success', __('user has been removed!'));
@ -181,7 +169,7 @@ class UserController extends Controller
* @param User $user * @param User $user
* @return RedirectResponse * @return RedirectResponse
*/ */
public function verifyEmail(User $user) public function verifyEmail(Request $request, User $user)
{ {
$user->verifyEmail(); $user->verifyEmail();
@ -219,7 +207,7 @@ class UserController extends Controller
* @param User $user * @param User $user
* @return Application|Factory|View|Response * @return Application|Factory|View|Response
*/ */
public function notifications() public function notifications(User $user)
{ {
return view('admin.users.notifications'); return view('admin.users.notifications');
} }
@ -260,11 +248,7 @@ class UserController extends Controller
} }
$all = $data['all'] ?? false; $all = $data['all'] ?? false;
$users = $all ? User::all() : User::whereIn('id', $data['users'])->get(); $users = $all ? User::all() : User::whereIn('id', $data['users'])->get();
try {
Notification::send($users, new DynamicNotification($data['via'], $database, $mail)); Notification::send($users, new DynamicNotification($data['via'], $database, $mail));
} catch (Exception $e) {
return redirect()->route('admin.users.notifications')->with('error', __('The attempt to send the email failed with the error: ' . $e->getMessage()));
}
return redirect()->route('admin.users.notifications')->with('success', __('Notification sent!')); return redirect()->route('admin.users.notifications')->with('success', __('Notification sent!'));
} }
@ -349,8 +333,8 @@ class UserController extends Controller
->editColumn('last_seen', function (User $user) { ->editColumn('last_seen', function (User $user) {
return $user->last_seen ? $user->last_seen->diffForHumans() : __('Never'); return $user->last_seen ? $user->last_seen->diffForHumans() : __('Never');
}) })
->editColumn('name', function (User $user, PterodactylSettings $ptero_settings) { ->editColumn('name', function (User $user) {
return '<a class="text-info" target="_blank" href="' . $ptero_settings->panel_url . '/admin/users/view/' . $user->pterodactyl_id . '">' . strip_tags($user->name) . '</a>'; return '<a class="text-info" target="_blank" href="' . config('SETTINGS::SYSTEM:PTERODACTYL:URL') . '/admin/users/view/' . $user->pterodactyl_id . '">' . strip_tags($user->name) . '</a>';
}) })
->rawColumns(['avatar', 'name', 'credits', 'role', 'usage', 'actions']) ->rawColumns(['avatar', 'name', 'credits', 'role', 'usage', 'actions'])
->make(); ->make();

View file

@ -6,8 +6,6 @@ use App\Events\UserUpdateCreditsEvent;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Models\User; use App\Models\User;
use App\Models\Voucher; use App\Models\Voucher;
use App\Settings\GeneralSettings;
use App\Settings\LocaleSettings;
use Illuminate\Contracts\Foundation\Application; use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory; use Illuminate\Contracts\View\Factory;
use Illuminate\Contracts\View\View; use Illuminate\Contracts\View\View;
@ -24,12 +22,9 @@ class VoucherController extends Controller
* *
* @return Application|Factory|View * @return Application|Factory|View
*/ */
public function index(LocaleSettings $locale_settings, GeneralSettings $general_settings) public function index()
{ {
return view('admin.vouchers.index', [ return view('admin.vouchers.index');
'locale_datatables' => $locale_settings->datatables,
'credits_display_name' => $general_settings->credits_display_name
]);
} }
/** /**
@ -37,11 +32,9 @@ class VoucherController extends Controller
* *
* @return Application|Factory|View * @return Application|Factory|View
*/ */
public function create(GeneralSettings $general_settings) public function create()
{ {
return view('admin.vouchers.create', [ return view('admin.vouchers.create');
'credits_display_name' => $general_settings->credits_display_name
]);
} }
/** /**
@ -82,11 +75,10 @@ class VoucherController extends Controller
* @param Voucher $voucher * @param Voucher $voucher
* @return Application|Factory|View * @return Application|Factory|View
*/ */
public function edit(Voucher $voucher, GeneralSettings $general_settings) public function edit(Voucher $voucher)
{ {
return view('admin.vouchers.edit', [ return view('admin.vouchers.edit', [
'voucher' => $voucher, 'voucher' => $voucher,
'credits_display_name' => $general_settings->credits_display_name
]); ]);
} }
@ -125,12 +117,10 @@ class VoucherController extends Controller
return redirect()->back()->with('success', __('voucher has been removed!')); return redirect()->back()->with('success', __('voucher has been removed!'));
} }
public function users(Voucher $voucher, LocaleSettings $locale_settings, GeneralSettings $general_settings) public function users(Voucher $voucher)
{ {
return view('admin.vouchers.users', [ return view('admin.vouchers.users', [
'voucher' => $voucher, 'voucher' => $voucher,
'locale_datatables' => $locale_settings->datatables,
'credits_display_name' => $general_settings->credits_display_name
]); ]);
} }
@ -140,7 +130,7 @@ class VoucherController extends Controller
* *
* @throws ValidationException * @throws ValidationException
*/ */
public function redeem(Request $request, GeneralSettings $general_settings) public function redeem(Request $request)
{ {
//general validations //general validations
$request->validate([ $request->validate([
@ -171,7 +161,7 @@ class VoucherController extends Controller
if ($request->user()->credits + $voucher->credits >= 99999999) { if ($request->user()->credits + $voucher->credits >= 99999999) {
throw ValidationException::withMessages([ throw ValidationException::withMessages([
'code' => "You can't redeem this voucher because you would exceed the limit of " . $general_settings->credits_display_name, 'code' => "You can't redeem this voucher because you would exceed the limit of ".CREDITS_DISPLAY_NAME,
]); ]);
} }
@ -181,7 +171,7 @@ class VoucherController extends Controller
event(new UserUpdateCreditsEvent($request->user())); event(new UserUpdateCreditsEvent($request->user()));
return response()->json([ return response()->json([
'success' => "{$voucher->credits} ". $general_settings->credits_display_name .' '.__('have been added to your balance!'), 'success' => "{$voucher->credits} ".CREDITS_DISPLAY_NAME.' '.__('have been added to your balance!'),
]); ]);
} }

View file

@ -14,7 +14,6 @@ use Illuminate\Support\Facades\Notification;
use Illuminate\Support\HtmlString; use Illuminate\Support\HtmlString;
use Illuminate\Validation\ValidationException; use Illuminate\Validation\ValidationException;
use Spatie\ValidationRules\Rules\Delimited; use Spatie\ValidationRules\Rules\Delimited;
use Exception;
class NotificationController extends Controller class NotificationController extends Controller
{ {
@ -105,12 +104,8 @@ class NotificationController extends Controller
'users' => ['No users found!'], 'users' => ['No users found!'],
]); ]);
} }
try {
Notification::send($users, new DynamicNotification($via, $database, $mail)); Notification::send($users, new DynamicNotification($via, $database, $mail));
}
catch (Exception $e) {
return response()->json(['message' => 'The attempt to send the email failed with the error: ' . $e->getMessage()], 500);
}
return response()->json(['message' => 'Notification successfully sent.', 'user_count' => $users->count()]); return response()->json(['message' => 'Notification successfully sent.', 'user_count' => $users->count()]);
} }

View file

@ -2,16 +2,13 @@
namespace App\Http\Controllers\Api; namespace App\Http\Controllers\Api;
use App\Classes\Pterodactyl;
use App\Events\UserUpdateCreditsEvent; use App\Events\UserUpdateCreditsEvent;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Models\DiscordUser; use App\Models\DiscordUser;
use App\Models\User; use App\Models\User;
use App\Notifications\ReferralNotification; use App\Notifications\ReferralNotification;
use App\Traits\Referral; use App\Traits\Referral;
use App\Settings\PterodactylSettings;
use App\Classes\PterodactylClient;
use App\Settings\ReferralSettings;
use App\Settings\UserSettings;
use Carbon\Carbon; use Carbon\Carbon;
use Illuminate\Contracts\Foundation\Application; use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\Pagination\LengthAwarePaginator; use Illuminate\Contracts\Pagination\LengthAwarePaginator;
@ -37,13 +34,6 @@ class UserController extends Controller
const ALLOWED_FILTERS = ['name', 'server_limit', 'email', 'pterodactyl_id', 'role', 'suspended']; const ALLOWED_FILTERS = ['name', 'server_limit', 'email', 'pterodactyl_id', 'role', 'suspended'];
private $pterodactyl;
public function __construct(PterodactylSettings $ptero_settings)
{
$this->pterodactyl = new PterodactylClient($ptero_settings);
}
/** /**
* Display a listing of the resource. * Display a listing of the resource.
* *
@ -105,7 +95,7 @@ class UserController extends Controller
//Update Users Password on Pterodactyl //Update Users Password on Pterodactyl
//Username,Mail,First and Lastname are required aswell //Username,Mail,First and Lastname are required aswell
$response = $this->pterodactyl->application->patch('/application/users/' . $user->pterodactyl_id, [ $response = Pterodactyl::client()->patch('/application/users/' . $user->pterodactyl_id, [
'username' => $request->name, 'username' => $request->name,
'first_name' => $request->name, 'first_name' => $request->name,
'last_name' => $request->name, 'last_name' => $request->name,
@ -213,7 +203,7 @@ class UserController extends Controller
* *
* @throws ValidationException * @throws ValidationException
*/ */
public function suspend(int $id) public function suspend(Request $request, int $id)
{ {
$discordUser = DiscordUser::find($id); $discordUser = DiscordUser::find($id);
$user = $discordUser ? $discordUser->user : User::findOrFail($id); $user = $discordUser ? $discordUser->user : User::findOrFail($id);
@ -237,7 +227,7 @@ class UserController extends Controller
* *
* @throws ValidationException * @throws ValidationException
*/ */
public function unsuspend(int $id) public function unsuspend(Request $request, int $id)
{ {
$discordUser = DiscordUser::find($id); $discordUser = DiscordUser::find($id);
$user = $discordUser ? $discordUser->user : User::findOrFail($id); $user = $discordUser ? $discordUser->user : User::findOrFail($id);
@ -256,7 +246,7 @@ class UserController extends Controller
/** /**
* @throws ValidationException * @throws ValidationException
*/ */
public function store(Request $request, UserSettings $user_settings, ReferralSettings $referral_settings) public function store(Request $request)
{ {
$request->validate([ $request->validate([
'name' => ['required', 'string', 'max:30', 'min:4', 'alpha_num', 'unique:users'], 'name' => ['required', 'string', 'max:30', 'min:4', 'alpha_num', 'unique:users'],
@ -265,7 +255,7 @@ class UserController extends Controller
]); ]);
// Prevent the creation of new users via API if this is enabled. // Prevent the creation of new users via API if this is enabled.
if (!$user_settings->creation_enabled) { if (!config('SETTINGS::SYSTEM:CREATION_OF_NEW_USERS', 'true')) {
throw ValidationException::withMessages([ throw ValidationException::withMessages([
'error' => 'The creation of new users has been blocked by the system administrator.', 'error' => 'The creation of new users has been blocked by the system administrator.',
]); ]);
@ -274,13 +264,13 @@ class UserController extends Controller
$user = User::create([ $user = User::create([
'name' => $request->input('name'), 'name' => $request->input('name'),
'email' => $request->input('email'), 'email' => $request->input('email'),
'credits' => $user_settings->initial_credits, 'credits' => config('SETTINGS::USER:INITIAL_CREDITS', 150),
'server_limit' => $user_settings->initial_server_limit, 'server_limit' => config('SETTINGS::USER:INITIAL_SERVER_LIMIT', 1),
'password' => Hash::make($request->input('password')), 'password' => Hash::make($request->input('password')),
'referral_code' => $this->createReferralCode(), 'referral_code' => $this->createReferralCode(),
]); ]);
$response = $this->pterodactyl->application->post('/application/users', [ $response = Pterodactyl::client()->post('/application/users', [
'external_id' => App::environment('local') ? Str::random(16) : (string) $user->id, 'external_id' => App::environment('local') ? Str::random(16) : (string) $user->id,
'username' => $user->name, 'username' => $user->name,
'email' => $user->email, 'email' => $user->email,
@ -307,8 +297,8 @@ class UserController extends Controller
$ref_code = $request->input('referral_code'); $ref_code = $request->input('referral_code');
$new_user = $user->id; $new_user = $user->id;
if ($ref_user = User::query()->where('referral_code', '=', $ref_code)->first()) { if ($ref_user = User::query()->where('referral_code', '=', $ref_code)->first()) {
if ($referral_settings->mode === 'register' || $referral_settings->mode === 'both') { if (config('SETTINGS::REFERRAL:MODE') == 'register' || config('SETTINGS::REFERRAL:MODE') == 'both') {
$ref_user->increment('credits', $referral_settings->reward); $ref_user->increment('credits', config('SETTINGS::REFERRAL::REWARD'));
$ref_user->notify(new ReferralNotification($ref_user->id, $new_user)); $ref_user->notify(new ReferralNotification($ref_user->id, $new_user));
} }
//INSERT INTO USER_REFERRALS TABLE //INSERT INTO USER_REFERRALS TABLE

View file

@ -3,7 +3,6 @@
namespace App\Http\Controllers\Auth; namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Settings\GeneralSettings;
use Illuminate\Foundation\Auth\SendsPasswordResetEmails; use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
use Illuminate\Http\Request; use Illuminate\Http\Request;
@ -32,13 +31,13 @@ class ForgotPasswordController extends Controller
$this->middleware('guest'); $this->middleware('guest');
} }
protected function validateEmail(Request $request, GeneralSettings $general_settings) protected function validateEmail(Request $request)
{ {
$this->validate($request, [ $this->validate($request, [
'email' => ['required', 'string', 'email', 'max:255'], 'email' => ['required', 'string', 'email', 'max:255'],
]); ]);
if ($general_settings->recaptcha_enabled) { if (config('SETTINGS::RECAPTCHA:ENABLED') == 'true') {
$this->validate($request, [ $this->validate($request, [
'g-recaptcha-response' => 'required|recaptcha', 'g-recaptcha-response' => 'required|recaptcha',
]); ]);

View file

@ -4,7 +4,6 @@ namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider; use App\Providers\RouteServiceProvider;
use App\Settings\GeneralSettings;
use Illuminate\Foundation\Auth\AuthenticatesUsers; use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
@ -54,13 +53,13 @@ class LoginController extends Controller
return $field; return $field;
} }
public function login(Request $request, GeneralSettings $general_settings) public function login(Request $request)
{ {
$validationRules = [ $validationRules = [
$this->username() => 'required|string', $this->username() => 'required|string',
'password' => 'required|string', 'password' => 'required|string',
]; ];
if ($general_settings->recaptcha_enabled) { if (config('SETTINGS::RECAPTCHA:ENABLED') == 'true') {
$validationRules['g-recaptcha-response'] = ['required', 'recaptcha']; $validationRules['g-recaptcha-response'] = ['required', 'recaptcha'];
} }
$request->validate($validationRules); $request->validate($validationRules);

View file

@ -2,18 +2,13 @@
namespace App\Http\Controllers\Auth; namespace App\Http\Controllers\Auth;
use App\Classes\Pterodactyl;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Models\User; use App\Models\User;
use App\Notifications\ReferralNotification; use App\Notifications\ReferralNotification;
use App\Providers\RouteServiceProvider; use App\Providers\RouteServiceProvider;
use App\Traits\Referral; use App\Traits\Referral;
use Carbon\Carbon; use Carbon\Carbon;
use App\Settings\PterodactylSettings;
use App\Classes\PterodactylClient;
use App\Settings\GeneralSettings;
use App\Settings\ReferralSettings;
use App\Settings\UserSettings;
use App\Settings\WebsiteSettings;
use Illuminate\Foundation\Auth\RegistersUsers; use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
@ -25,24 +20,6 @@ use Illuminate\Validation\ValidationException;
class RegisterController extends Controller class RegisterController extends Controller
{ {
private $pterodactyl;
private $credits_display_name;
private $recaptcha_enabled;
private $website_show_tos;
private $register_ip_check;
private $initial_credits;
private $initial_server_limit;
private $referral_mode;
private $referral_reward;
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Register Controller | Register Controller
@ -68,18 +45,9 @@ class RegisterController extends Controller
* *
* @return void * @return void
*/ */
public function __construct(PterodactylSettings $ptero_settings, GeneralSettings $general_settings, WebsiteSettings $website_settings, UserSettings $user_settings, ReferralSettings $referral_settings) public function __construct()
{ {
$this->middleware('guest'); $this->middleware('guest');
$this->pterodactyl = new PterodactylClient($ptero_settings);
$this->credits_display_name = $general_settings->credits_display_name;
$this->recaptcha_enabled = $general_settings->recaptcha_enabled;
$this->website_show_tos = $website_settings->show_tos;
$this->register_ip_check = $user_settings->register_ip_check;
$this->initial_credits = $user_settings->initial_credits;
$this->initial_server_limit = $user_settings->initial_server_limit;
$this->referral_mode = $referral_settings->mode;
$this->referral_reward = $referral_settings->reward;
} }
/** /**
@ -95,14 +63,14 @@ class RegisterController extends Controller
'email' => ['required', 'string', 'email', 'max:64', 'unique:users'], 'email' => ['required', 'string', 'email', 'max:64', 'unique:users'],
'password' => ['required', 'string', 'min:8', 'confirmed'], 'password' => ['required', 'string', 'min:8', 'confirmed'],
]; ];
if ($this->recaptcha_enabled) { if (config('SETTINGS::RECAPTCHA:ENABLED') == 'true') {
$validationRules['g-recaptcha-response'] = ['required', 'recaptcha']; $validationRules['g-recaptcha-response'] = ['required', 'recaptcha'];
} }
if ($this->website_show_tos) { if (config('SETTINGS::SYSTEM:SHOW_TOS') == 'true') {
$validationRules['terms'] = ['required']; $validationRules['terms'] = ['required'];
} }
if ($this->register_ip_check) { if (config('SETTINGS::SYSTEM:REGISTER_IP_CHECK', 'true') == 'true') {
//check if ip has already made an account //check if ip has already made an account
$data['ip'] = session()->get('ip') ?? request()->ip(); $data['ip'] = session()->get('ip') ?? request()->ip();
@ -131,16 +99,15 @@ class RegisterController extends Controller
$user = User::create([ $user = User::create([
'name' => $data['name'], 'name' => $data['name'],
'email' => $data['email'], 'email' => $data['email'],
'credits' => $this->initial_credits, 'credits' => config('SETTINGS::USER:INITIAL_CREDITS', 150),
'server_limit' => $this->initial_server_limit, 'server_limit' => config('SETTINGS::USER:INITIAL_SERVER_LIMIT', 1),
'password' => Hash::make($data['password']), 'password' => Hash::make($data['password']),
'referral_code' => $this->createReferralCode(), 'referral_code' => $this->createReferralCode(),
'pterodactyl_id' => Str::uuid(),
]); ]);
$response = $this->pterodactyl->application->post('/application/users', [ $response = Pterodactyl::client()->post('/application/users', [
'external_id' => $user->pterodactyl_id, 'external_id' => App::environment('local') ? Str::random(16) : (string) $user->id,
'username' => $user->name, 'username' => $user->name,
'email' => $user->email, 'email' => $user->email,
'first_name' => $user->name, 'first_name' => $user->name,
@ -158,23 +125,24 @@ class RegisterController extends Controller
]); ]);
} }
// delete activity log for user creation where description = 'created' or 'deleted' and subject_id = user_id $user->update([
DB::table('activity_log')->where('description', 'created')->orWhere('description', 'deleted')->where('subject_id', $user->id)->delete(); 'pterodactyl_id' => $response->json()['attributes']['id'],
]);
//INCREMENT REFERRAL-USER CREDITS //INCREMENT REFERRAL-USER CREDITS
if (!empty($data['referral_code'])) { if (!empty($data['referral_code'])) {
$ref_code = $data['referral_code']; $ref_code = $data['referral_code'];
$new_user = $user->id; $new_user = $user->id;
if ($ref_user = User::query()->where('referral_code', '=', $ref_code)->first()) { if ($ref_user = User::query()->where('referral_code', '=', $ref_code)->first()) {
if ($this->referral_mode === 'sign-up' || $this->referral_mode === 'both') { if (config('SETTINGS::REFERRAL:MODE') == 'sign-up' || config('SETTINGS::REFERRAL:MODE') == 'both') {
$ref_user->increment('credits', $this->referral_reward); $ref_user->increment('credits', config('SETTINGS::REFERRAL::REWARD'));
$ref_user->notify(new ReferralNotification($ref_user->id, $new_user)); $ref_user->notify(new ReferralNotification($ref_user->id, $new_user));
//LOGS REFERRALS IN THE ACTIVITY LOG //LOGS REFERRALS IN THE ACTIVITY LOG
activity() activity()
->performedOn($user) ->performedOn($user)
->causedBy($ref_user) ->causedBy($ref_user)
->log('gained ' . $this->referral_reward . ' ' . $this->credits_display_name . ' for sign-up-referral of ' . $user->name . ' (ID:' . $user->id . ')'); ->log('gained ' . config('SETTINGS::REFERRAL::REWARD') . ' ' . config('SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME') . ' for sign-up-referral of ' . $user->name . ' (ID:' . $user->id . ')');
} }
//INSERT INTO USER_REFERRALS TABLE //INSERT INTO USER_REFERRALS TABLE
DB::table('user_referrals')->insert([ DB::table('user_referrals')->insert([

View file

@ -5,24 +5,22 @@ namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Models\DiscordUser; use App\Models\DiscordUser;
use App\Models\User; use App\Models\User;
use App\Settings\DiscordSettings;
use App\Settings\UserSettings;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Http;
use Laravel\Socialite\Facades\Socialite; use Laravel\Socialite\Facades\Socialite;
class SocialiteController extends Controller class SocialiteController extends Controller
{ {
public function redirect(DiscordSettings $discord_settings) public function redirect()
{ {
$scopes = !empty($discord_settings->bot_token) && !empty($discord_settings->guild_id) ? ['guilds.join'] : []; $scopes = ! empty(config('SETTINGS::DISCORD:BOT_TOKEN')) && ! empty(config('SETTINGS::DISCORD:GUILD_ID')) ? ['guilds.join'] : [];
return Socialite::driver('discord') return Socialite::driver('discord')
->scopes($scopes) ->scopes($scopes)
->redirect(); ->redirect();
} }
public function callback(DiscordSettings $discord_settings, UserSettings $user_settings) public function callback()
{ {
if (Auth::guest()) { if (Auth::guest()) {
return abort(500); return abort(500);
@ -31,9 +29,9 @@ class SocialiteController extends Controller
/** @var User $user */ /** @var User $user */
$user = Auth::user(); $user = Auth::user();
$discord = Socialite::driver('discord')->user(); $discord = Socialite::driver('discord')->user();
$botToken = $discord_settings->bot_token; $botToken = config('SETTINGS::DISCORD:BOT_TOKEN');
$guildId = $discord_settings->guild_id; $guildId = config('SETTINGS::DISCORD:GUILD_ID');
$roleId = $discord_settings->role_id; $roleId = config('SETTINGS::DISCORD:ROLE_ID');
//save / update discord_users //save / update discord_users
@ -51,8 +49,8 @@ class SocialiteController extends Controller
DiscordUser::create(array_merge($discord->user, ['user_id' => Auth::user()->id])); DiscordUser::create(array_merge($discord->user, ['user_id' => Auth::user()->id]));
//update user //update user
Auth::user()->increment('credits', $user_settings->credits_reward_after_verify_discord); Auth::user()->increment('credits', config('SETTINGS::USER:CREDITS_REWARD_AFTER_VERIFY_DISCORD'));
Auth::user()->increment('server_limit', $user_settings->server_limit_after_verify_discord); Auth::user()->increment('server_limit', config('SETTINGS::USER:SERVER_LIMIT_REWARD_AFTER_VERIFY_DISCORD'));
Auth::user()->update(['discord_verified_at' => now()]); Auth::user()->update(['discord_verified_at' => now()]);
} else { } else {
$user->discordUser->update($discord->user); $user->discordUser->update($discord->user);

View file

@ -4,9 +4,7 @@ namespace App\Http\Controllers;
use App\Models\PartnerDiscount; use App\Models\PartnerDiscount;
use App\Models\UsefulLink; use App\Models\UsefulLink;
use App\Settings\GeneralSettings; use Illuminate\Http\Request;
use App\Settings\WebsiteSettings;
use App\Settings\ReferralSettings;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Hash;
@ -91,7 +89,7 @@ class HomeController extends Controller
} }
/** Show the application dashboard. */ /** Show the application dashboard. */
public function index(GeneralSettings $general_settings, WebsiteSettings $website_settings, ReferralSettings $referral_settings) public function index(Request $request)
{ {
$usage = Auth::user()->creditUsage(); $usage = Auth::user()->creditUsage();
$credits = Auth::user()->Credits(); $credits = Auth::user()->Credits();
@ -122,9 +120,6 @@ class HomeController extends Controller
'numberOfReferrals' => DB::table('user_referrals')->where('referral_id', '=', Auth::user()->id)->count(), 'numberOfReferrals' => DB::table('user_referrals')->where('referral_id', '=', Auth::user()->id)->count(),
'partnerDiscount' => PartnerDiscount::where('user_id', Auth::user()->id)->first(), 'partnerDiscount' => PartnerDiscount::where('user_id', Auth::user()->id)->first(),
'myDiscount' => PartnerDiscount::getDiscount(), 'myDiscount' => PartnerDiscount::getDiscount(),
'general_settings' => $general_settings,
'website_settings' => $website_settings,
'referral_settings' => $referral_settings
]); ]);
} }
} }

View file

@ -10,23 +10,20 @@ use App\Models\TicketCategory;
use App\Models\TicketComment; use App\Models\TicketComment;
use App\Models\User; use App\Models\User;
use App\Notifications\Ticket\User\ReplyNotification; use App\Notifications\Ticket\User\ReplyNotification;
use App\Settings\LocaleSettings;
use App\Settings\PterodactylSettings;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
class TicketsController extends Controller class TicketsController extends Controller
{ {
public function index(LocaleSettings $locale_settings) public function index()
{ {
return view('moderator.ticket.index', [ $tickets = Ticket::orderBy('id', 'desc')->paginate(10);
'tickets' => Ticket::orderBy('id', 'desc')->paginate(10), $ticketcategories = TicketCategory::all();
'ticketcategories' => TicketCategory::all(),
'locale_datatables' => $locale_settings->datatables return view('moderator.ticket.index', compact('tickets', 'ticketcategories'));
]);
} }
public function show($ticket_id, PterodactylSettings $ptero_settings) public function show($ticket_id)
{ {
try { try {
$ticket = Ticket::where('ticket_id', $ticket_id)->firstOrFail(); $ticket = Ticket::where('ticket_id', $ticket_id)->firstOrFail();
@ -37,9 +34,8 @@ class TicketsController extends Controller
$ticketcomments = $ticket->ticketcomments; $ticketcomments = $ticket->ticketcomments;
$ticketcategory = $ticket->ticketcategory; $ticketcategory = $ticket->ticketcategory;
$server = Server::where('id', $ticket->server)->first(); $server = Server::where('id', $ticket->server)->first();
$pterodactyl_url = $ptero_settings->panel_url;
return view('moderator.ticket.show', compact('ticket', 'ticketcategory', 'ticketcomments', 'server', 'pterodactyl_url')); return view('moderator.ticket.show', compact('ticket', 'ticketcategory', 'ticketcomments', 'server'));
} }
public function changeStatus($ticket_id) public function changeStatus($ticket_id)
@ -168,11 +164,9 @@ class TicketsController extends Controller
->make(true); ->make(true);
} }
public function blacklist(LocaleSettings $locale_settings) public function blacklist()
{ {
return view('moderator.ticket.blacklist', [ return view('moderator.ticket.blacklist');
'locale_datatables' => $locale_settings->datatables
]);
} }
public function blacklistAdd(Request $request) public function blacklistAdd(Request $request)

View file

@ -2,12 +2,11 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Classes\PterodactylClient; use App\Classes\Pterodactyl;
use App\Models\Pterodactyl\Egg; use App\Models\Egg;
use App\Models\Pterodactyl\Location; use App\Models\Location;
use App\Models\Pterodactyl\Node; use App\Models\Node;
use App\Models\Product; use App\Models\Product;
use App\Settings\PterodactylSettings;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request; use Illuminate\Http\Request;
@ -15,13 +14,6 @@ use Illuminate\Support\Collection;
class ProductController extends Controller class ProductController extends Controller
{ {
private $pterodactyl;
public function __construct(PterodactylSettings $ptero_settings)
{
$this->pterodactyl = new PterodactylClient($ptero_settings);
}
/** /**
* @description get product locations based on selected egg * @description get product locations based on selected egg
* *
@ -68,7 +60,7 @@ class ProductController extends Controller
{ {
$nodes = $this->getNodesBasedOnEgg($request, $egg); $nodes = $this->getNodesBasedOnEgg($request, $egg);
foreach ($nodes as $key => $node) { foreach ($nodes as $key => $node) {
$pteroNode = $this->pterodactyl->getNode($node->id); $pteroNode = Pterodactyl::getNode($node->id);
if ($pteroNode['allocated_resources']['memory'] >= ($pteroNode['memory'] * ($pteroNode['memory_overallocate'] + 100) / 100) || $pteroNode['allocated_resources']['disk'] >= ($pteroNode['disk'] * ($pteroNode['disk_overallocate'] + 100) / 100)) { if ($pteroNode['allocated_resources']['memory'] >= ($pteroNode['memory'] * ($pteroNode['memory_overallocate'] + 100) / 100) || $pteroNode['allocated_resources']['disk'] >= ($pteroNode['disk'] * ($pteroNode['disk_overallocate'] + 100) / 100)) {
$nodes->forget($key); $nodes->forget($key);
} }
@ -117,7 +109,7 @@ class ProductController extends Controller
}) })
->get(); ->get();
$pteroNode = $this->pterodactyl->getNode($node->id); $pteroNode = Pterodactyl::getNode($node->id);
foreach ($products as $key => $product) { foreach ($products as $key => $product) {
if ($product->memory > ($pteroNode['memory'] * ($pteroNode['memory_overallocate'] + 100) / 100) - $pteroNode['allocated_resources']['memory'] || $product->disk > ($pteroNode['disk'] * ($pteroNode['disk_overallocate'] + 100) / 100) - $pteroNode['allocated_resources']['disk']) { if ($product->memory > ($pteroNode['memory'] * ($pteroNode['memory_overallocate'] + 100) / 100) - $pteroNode['allocated_resources']['memory'] || $product->disk > ($pteroNode['disk'] * ($pteroNode['disk_overallocate'] + 100) / 100) - $pteroNode['allocated_resources']['disk']) {
$product->doesNotFit = true; $product->doesNotFit = true;

View file

@ -2,12 +2,8 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Classes\Pterodactyl;
use App\Models\User; use App\Models\User;
use App\Settings\UserSettings;
use App\Settings\PterodactylSettings;
use App\Classes\PterodactylClient;
use App\Settings\DiscordSettings;
use App\Settings\ReferralSettings;
use Illuminate\Http\RedirectResponse; use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
@ -16,15 +12,8 @@ use Illuminate\Validation\ValidationException;
class ProfileController extends Controller class ProfileController extends Controller
{ {
private $pterodactyl;
public function __construct(PterodactylSettings $ptero_settings)
{
$this->pterodactyl = new PterodactylClient($ptero_settings);
}
/** Display a listing of the resource. */ /** Display a listing of the resource. */
public function index(UserSettings $user_settings, DiscordSettings $discord_settings, ReferralSettings $referral_settings) public function index()
{ {
switch (Auth::user()->role) { switch (Auth::user()->role) {
case 'admin': case 'admin':
@ -43,14 +32,10 @@ class ProfileController extends Controller
return view('profile.index')->with([ return view('profile.index')->with([
'user' => Auth::user(), 'user' => Auth::user(),
'credits_reward_after_verify_discord' => $user_settings->credits_reward_after_verify_discord, 'credits_reward_after_verify_discord' => config('SETTINGS::USER:CREDITS_REWARD_AFTER_VERIFY_DISCORD'),
'force_email_verification' => $user_settings->force_email_verification, 'force_email_verification' => config('SETTINGS::USER:FORCE_EMAIL_VERIFICATION'),
'force_discord_verification' => $user_settings->force_discord_verification, 'force_discord_verification' => config('SETTINGS::USER:FORCE_DISCORD_VERIFICATION'),
'badgeColor' => $badgeColor, 'badgeColor' => $badgeColor,
'discord_client_id' => $discord_settings->client_id,
'discord_client_secret' => $discord_settings->client_secret,
'referral_enabled' => $referral_settings->enabled,
'referral_allowed' => $referral_settings->allowed
]); ]);
} }
@ -96,7 +81,7 @@ class ProfileController extends Controller
//Update Users Password on Pterodactyl //Update Users Password on Pterodactyl
//Username,Mail,First and Lastname are required aswell //Username,Mail,First and Lastname are required aswell
$response = $this->pterodactyl->application->patch('/application/users/' . $user->pterodactyl_id, [ $response = Pterodactyl::client()->patch('/application/users/'.$user->pterodactyl_id, [
'password' => $request->input('new_password'), 'password' => $request->input('new_password'),
'username' => $request->input('name'), 'username' => $request->input('name'),
'first_name' => $request->input('name'), 'first_name' => $request->input('name'),
@ -140,7 +125,7 @@ class ProfileController extends Controller
} }
//update name and email on Pterodactyl //update name and email on Pterodactyl
$response = $this->pterodactyl->application->patch('/application/users/' . $user->pterodactyl_id, [ $response = Pterodactyl::client()->patch('/application/users/'.$user->pterodactyl_id, [
'username' => $request->input('name'), 'username' => $request->input('name'),
'first_name' => $request->input('name'), 'first_name' => $request->input('name'),
'last_name' => $request->input('name'), 'last_name' => $request->input('name'),

View file

@ -2,18 +2,14 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Models\Pterodactyl\Egg; use App\Classes\Pterodactyl;
use App\Models\Pterodactyl\Location; use App\Models\Egg;
use App\Models\Pterodactyl\Nest; use App\Models\Location;
use App\Models\Pterodactyl\Node; use App\Models\Nest;
use App\Models\Node;
use App\Models\Product; use App\Models\Product;
use App\Models\Server; use App\Models\Server;
use App\Notifications\ServerCreationError; use App\Notifications\ServerCreationError;
use App\Settings\UserSettings;
use App\Settings\ServerSettings;
use App\Settings\PterodactylSettings;
use App\Classes\PterodactylClient;
use App\Settings\GeneralSettings;
use Exception; use Exception;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Client\Response; use Illuminate\Http\Client\Response;
@ -24,15 +20,8 @@ use Illuminate\Support\Facades\Request as FacadesRequest;
class ServerController extends Controller class ServerController extends Controller
{ {
private $pterodactyl;
public function __construct(PterodactylSettings $ptero_settings)
{
$this->pterodactyl = new PterodactylClient($ptero_settings);
}
/** Display a listing of the resource. */ /** Display a listing of the resource. */
public function index(GeneralSettings $general_settings, PterodactylSettings $ptero_settings) public function index()
{ {
$servers = Auth::user()->servers; $servers = Auth::user()->servers;
@ -40,7 +29,7 @@ class ServerController extends Controller
foreach ($servers as $server) { foreach ($servers as $server) {
//Get server infos from ptero //Get server infos from ptero
$serverAttributes = $this->pterodactyl->getServerAttributes($server->pterodactyl_id); $serverAttributes = Pterodactyl::getServerAttributes($server->pterodactyl_id, true);
if (! $serverAttributes) { if (! $serverAttributes) {
continue; continue;
} }
@ -72,19 +61,14 @@ class ServerController extends Controller
return view('servers.index')->with([ return view('servers.index')->with([
'servers' => $servers, 'servers' => $servers,
'credits_display_name' => $general_settings->credits_display_name,
'pterodactyl_url' => $ptero_settings->panel_url,
'phpmyadmin_url' => $general_settings->phpmyadmin_url
]); ]);
} }
/** Show the form for creating a new resource. */ /** Show the form for creating a new resource. */
public function create(UserSettings $user_settings, ServerSettings $server_settings, GeneralSettings $general_settings) public function create()
{ {
$validate_configuration = $this->validateConfigurationRules($user_settings, $server_settings); if (! is_null($this->validateConfigurationRules())) {
return $this->validateConfigurationRules();
if (!is_null($validate_configuration)) {
return $validate_configuration;
} }
$productCount = Product::query()->where('disabled', '=', false)->count(); $productCount = Product::query()->where('disabled', '=', false)->count();
@ -114,16 +98,13 @@ class ServerController extends Controller
'locations' => $locations, 'locations' => $locations,
'eggs' => $eggs, 'eggs' => $eggs,
'user' => Auth::user(), 'user' => Auth::user(),
'server_creation_enabled' => $server_settings->creation_enabled,
'min_credits_to_make_server' => $user_settings->min_credits_to_make_server,
'credits_display_name' => $general_settings->credits_display_name
]); ]);
} }
/** /**
* @return null|RedirectResponse * @return null|RedirectResponse
*/ */
private function validateConfigurationRules(UserSettings $user_settings, ServerSettings $server_settings) private function validateConfigurationRules()
{ {
//limit validation //limit validation
if (Auth::user()->servers()->count() >= Auth::user()->server_limit) { if (Auth::user()->servers()->count() >= Auth::user()->server_limit) {
@ -139,31 +120,35 @@ class ServerController extends Controller
$nodeName = $node->name; $nodeName = $node->name;
// Check if node has enough memory and disk space // Check if node has enough memory and disk space
$checkResponse = $this->pterodactyl->checkNodeResources($node, $product->memory, $product->disk); $checkResponse = Pterodactyl::checkNodeResources($node, $product->memory, $product->disk);
if ($checkResponse == false) { if ($checkResponse == false) {
return redirect()->route('servers.index')->with('error', __("The node '".$nodeName."' doesn't have the required memory or disk left to allocate this product.")); return redirect()->route('servers.index')->with('error', __("The node '".$nodeName."' doesn't have the required memory or disk left to allocate this product."));
} }
// Min. Credits // Min. Credits
if (Auth::user()->credits < ($product->minimum_credits == -1 if (
? $user_settings->min_credits_to_make_server Auth::user()->credits <
: $product->minimum_credits)) { ($product->minimum_credits == -1
? 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!'); return redirect()->route('servers.index')->with('error', 'You do not have the required amount of '.CREDITS_DISPLAY_NAME.' to use this product!');
} }
} }
//Required Verification for creating an server //Required Verification for creating an server
if ($user_settings->force_email_verification && !Auth::user()->hasVerifiedEmail()) { if (config('SETTINGS::USER:FORCE_EMAIL_VERIFICATION', 'false') === 'true' && ! Auth::user()->hasVerifiedEmail()) {
return redirect()->route('profile.index')->with('error', __('You are required to verify your email address before you can create a server.')); return redirect()->route('profile.index')->with('error', __('You are required to verify your email address before you can create a server.'));
} }
//Required Verification for creating an server //Required Verification for creating an server
if (!$server_settings->creation_enabled && Auth::user()->role != 'admin') {
if (! config('SETTINGS::SYSTEM:CREATION_OF_NEW_SERVERS', 'true') && Auth::user()->role != 'admin') {
return redirect()->route('servers.index')->with('error', __('The system administrator has blocked the creation of new servers.')); return redirect()->route('servers.index')->with('error', __('The system administrator has blocked the creation of new servers.'));
} }
//Required Verification for creating an server //Required Verification for creating an server
if ($user_settings->force_discord_verification && !Auth::user()->discordUser) { if (config('SETTINGS::USER:FORCE_DISCORD_VERIFICATION', 'false') === 'true' && ! Auth::user()->discordUser) {
return redirect()->route('profile.index')->with('error', __('You are required to link your discord account before you can create a server.')); return redirect()->route('profile.index')->with('error', __('You are required to link your discord account before you can create a server.'));
} }
@ -171,15 +156,13 @@ class ServerController extends Controller
} }
/** Store a newly created resource in storage. */ /** Store a newly created resource in storage. */
public function store(Request $request, UserSettings $user_settings, ServerSettings $server_settings) public function store(Request $request)
{ {
/** @var Node $node */ /** @var Node $node */
/** @var Egg $egg */ /** @var Egg $egg */
/** @var Product $product */ /** @var Product $product */
$validate_configuration = $this->validateConfigurationRules($user_settings, $server_settings); if (! is_null($this->validateConfigurationRules())) {
return $this->validateConfigurationRules();
if (!is_null($validate_configuration)) {
return $validate_configuration;
} }
$request->validate([ $request->validate([
@ -200,13 +183,13 @@ class ServerController extends Controller
]); ]);
//get free allocation ID //get free allocation ID
$allocationId = $this->pterodactyl->getFreeAllocationId($node); $allocationId = Pterodactyl::getFreeAllocationId($node);
if (! $allocationId) { if (! $allocationId) {
return $this->noAllocationsError($server); return $this->noAllocationsError($server);
} }
//create server on pterodactyl //create server on pterodactyl
$response = $this->pterodactyl->createServer($server, $egg, $allocationId); $response = Pterodactyl::createServer($server, $egg, $allocationId);
if ($response->failed()) { if ($response->failed()) {
return $this->serverCreationFailed($response, $server); return $this->serverCreationFailed($response, $server);
} }
@ -218,7 +201,7 @@ class ServerController extends Controller
'identifier' => $serverAttributes['identifier'], 'identifier' => $serverAttributes['identifier'],
]); ]);
if ($server_settings->charge_first_hour) { if (config('SETTINGS::SYSTEM:SERVER_CREATE_CHARGE_FIRST_HOUR', 'true') == 'true') {
if ($request->user()->credits >= $server->product->getHourlyPrice()) { if ($request->user()->credits >= $server->product->getHourlyPrice()) {
$request->user()->decrement('credits', $server->product->getHourlyPrice()); $request->user()->decrement('credits', $server->product->getHourlyPrice());
} }
@ -269,12 +252,12 @@ class ServerController extends Controller
} }
/** Show Server Settings */ /** Show Server Settings */
public function show(Server $server, ServerSettings $server_settings, GeneralSettings $general_settings) public function show(Server $server)
{ {
if ($server->user_id != Auth::user()->id) { if ($server->user_id != Auth::user()->id) {
return back()->with('error', __('This is not your Server!')); return back()->with('error', __('´This is not your Server!'));
} }
$serverAttributes = $this->pterodactyl->getServerAttributes($server->pterodactyl_id); $serverAttributes = Pterodactyl::getServerAttributes($server->pterodactyl_id);
$serverRelationships = $serverAttributes['relationships']; $serverRelationships = $serverAttributes['relationships'];
$serverLocationAttributes = $serverRelationships['location']['attributes']; $serverLocationAttributes = $serverRelationships['location']['attributes'];
@ -290,7 +273,7 @@ class ServerController extends Controller
$server->name = $serverAttributes['name']; $server->name = $serverAttributes['name'];
$server->egg = $serverRelationships['egg']['attributes']['name']; $server->egg = $serverRelationships['egg']['attributes']['name'];
$pteroNode = $this->pterodactyl->getNode($serverRelationships['node']['attributes']['id']); $pteroNode = Pterodactyl::getNode($serverRelationships['node']['attributes']['id']);
$products = Product::orderBy('created_at') $products = Product::orderBy('created_at')
->whereHas('nodes', function (Builder $builder) use ($serverRelationships) { //Only show products for that node ->whereHas('nodes', function (Builder $builder) use ($serverRelationships) { //Only show products for that node
@ -309,8 +292,6 @@ class ServerController extends Controller
return view('servers.settings')->with([ return view('servers.settings')->with([
'server' => $server, 'server' => $server,
'products' => $products, 'products' => $products,
'server_enable_upgrade' => $server_settings->enable_upgrade,
'credits_display_name' => $general_settings->credits_display_name
]); ]);
} }
@ -325,7 +306,7 @@ class ServerController extends Controller
$user = Auth::user(); $user = Auth::user();
$oldProduct = Product::where('id', $server->product->id)->first(); $oldProduct = Product::where('id', $server->product->id)->first();
$newProduct = Product::where('id', $request->product_upgrade)->first(); $newProduct = Product::where('id', $request->product_upgrade)->first();
$serverAttributes = $this->pterodactyl->getServerAttributes($server->pterodactyl_id); $serverAttributes = Pterodactyl::getServerAttributes($server->pterodactyl_id);
$serverRelationships = $serverAttributes['relationships']; $serverRelationships = $serverAttributes['relationships'];
// Get node resource allocation info // Get node resource allocation info
@ -336,7 +317,7 @@ class ServerController extends Controller
// Check if node has enough memory and disk space // Check if node has enough memory and disk space
$requireMemory = $newProduct->memory - $oldProduct->memory; $requireMemory = $newProduct->memory - $oldProduct->memory;
$requiredisk = $newProduct->disk - $oldProduct->disk; $requiredisk = $newProduct->disk - $oldProduct->disk;
$checkResponse = $this->pterodactyl->checkNodeResources($node, $requireMemory, $requiredisk); $checkResponse = Pterodactyl::checkNodeResources($node, $requireMemory, $requiredisk);
if ($checkResponse == false) { if ($checkResponse == false) {
return redirect()->route('servers.index')->with('error', __("The node '".$nodeName."' doesn't have the required memory or disk left to upgrade the server.")); return redirect()->route('servers.index')->with('error', __("The node '".$nodeName."' doesn't have the required memory or disk left to upgrade the server."));
} }
@ -350,12 +331,14 @@ class ServerController extends Controller
$server->product_id = $request->product_upgrade; $server->product_id = $request->product_upgrade;
$server->update(); $server->update();
$server->allocation = $serverAttributes['allocation']; $server->allocation = $serverAttributes['allocation'];
$response = $this->pterodactyl->updateServer($server, $newProduct); $response = Pterodactyl::updateServer($server, $newProduct);
if ($response->failed()) return redirect()->route('servers.index')->with('error', __("The system was unable to update your server product. Please try again later or contact support.")); if ($response->failed()) {
return $this->serverCreationFailed($response, $server);
}
//update user balance //update user balance
$user->decrement('credits', $priceupgrade); $user->decrement('credits', $priceupgrade);
//restart the server //restart the server
$response = $this->pterodactyl->powerAction($server, 'restart'); $response = Pterodactyl::powerAction($server, 'restart');
if ($response->failed()) { if ($response->failed()) {
return redirect()->route('servers.index')->with('error', $response->json()['errors'][0]['detail']); return redirect()->route('servers.index')->with('error', $response->json()['errors'][0]['detail']);
} }

View file

@ -3,31 +3,36 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use App\Models\ShopProduct; use App\Models\ShopProduct;
use App\Settings\GeneralSettings;
use App\Settings\UserSettings;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
class StoreController extends Controller class StoreController extends Controller
{ {
/** Display a listing of the resource. */ /** Display a listing of the resource. */
public function index(UserSettings $user_settings, GeneralSettings $general_settings) public function index()
{ {
$isStoreEnabled = $general_settings->store_enabled; $isPaymentSetup = false;
if (
env('APP_ENV') == 'local' ||
config('SETTINGS::PAYMENTS:PAYPAL:SECRET') && config('SETTINGS::PAYMENTS:PAYPAL:CLIENT_ID') ||
config('SETTINGS::PAYMENTS:STRIPE:SECRET') && config('SETTINGS::PAYMENTS:STRIPE:ENDPOINT_SECRET') && config('SETTINGS::PAYMENTS:STRIPE:METHODS')
) {
$isPaymentSetup = true;
}
//Required Verification for creating an server //Required Verification for creating an server
if ($user_settings->force_email_verification && !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 purchase credits.')); return redirect()->route('profile.index')->with('error', __('You are required to verify your email address before you can purchase credits.'));
} }
//Required Verification for creating an server //Required Verification for creating an server
if ($user_settings->force_discord_verification && !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 purchase Credits')); return redirect()->route('profile.index')->with('error', __('You are required to link your discord account before you can purchase Credits'));
} }
return view('store.index')->with([ return view('store.index')->with([
'products' => ShopProduct::where('disabled', '=', false)->orderBy('type', 'asc')->orderBy('price', 'asc')->get(), 'products' => ShopProduct::where('disabled', '=', false)->orderBy('type', 'asc')->orderBy('price', 'asc')->get(),
'isStoreEnabled' => $isStoreEnabled, 'isPaymentSetup' => $isPaymentSetup,
'credits_display_name' => $general_settings->credits_display_name
]); ]);
} }
} }

View file

@ -11,9 +11,6 @@ use App\Models\User;
use App\Notifications\Ticket\Admin\AdminCreateNotification; use App\Notifications\Ticket\Admin\AdminCreateNotification;
use App\Notifications\Ticket\Admin\AdminReplyNotification; use App\Notifications\Ticket\Admin\AdminReplyNotification;
use App\Notifications\Ticket\User\CreateNotification; use App\Notifications\Ticket\User\CreateNotification;
use App\Settings\LocaleSettings;
use App\Settings\PterodactylSettings;
use App\Settings\TicketSettings;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Notification; use Illuminate\Support\Facades\Notification;
@ -21,28 +18,23 @@ use Illuminate\Support\Str;
class TicketsController extends Controller class TicketsController extends Controller
{ {
public function index(LocaleSettings $locale_settings) public function index()
{ {
return view('ticket.index', [ $tickets = Ticket::where('user_id', Auth::user()->id)->paginate(10);
'tickets' => Ticket::where('user_id', Auth::user()->id)->paginate(10), $ticketcategories = TicketCategory::all();
'ticketcategories' => TicketCategory::all(),
'locale_datatables' => $locale_settings->datatables return view('ticket.index', compact('tickets', 'ticketcategories'));
]);
} }
public function store(Request $request, TicketSettings $ticket_settings) public function store(Request $request)
{ {
$this->validate( $this->validate($request, [
$request,
[
'title' => 'required', 'title' => 'required',
'ticketcategory' => 'required', 'ticketcategory' => 'required',
'priority' => 'required', 'priority' => 'required',
'message' => 'required', 'message' => 'required',]
]
); );
$ticket = new Ticket( $ticket = new Ticket([
[
'title' => $request->input('title'), 'title' => $request->input('title'),
'user_id' => Auth::user()->id, 'user_id' => Auth::user()->id,
'ticket_id' => strtoupper(Str::random(8)), 'ticket_id' => strtoupper(Str::random(8)),
@ -50,28 +42,28 @@ class TicketsController extends Controller
'priority' => $request->input('priority'), 'priority' => $request->input('priority'),
'message' => $request->input('message'), 'message' => $request->input('message'),
'status' => 'Open', 'status' => 'Open',
'server' => $request->input('server'), 'server' => $request->input('server'),]
]
); );
$ticket->save(); $ticket->save();
$user = Auth::user(); $user = Auth::user();
switch ($ticket_settings->notify) { if (config('SETTINGS::TICKET:NOTIFY') == "all") {
case 'all':
$admin = User::where('role', 'admin')->orWhere('role', 'mod')->get(); $admin = User::where('role', 'admin')->orWhere('role', 'mod')->get();
Notification::send($admin, new AdminCreateNotification($ticket, $user)); }
case 'admin': if (config('SETTINGS::TICKET:NOTIFY') == "admin") {
$admin = User::where('role', 'admin')->get(); $admin = User::where('role', 'admin')->get();
Notification::send($admin, new AdminCreateNotification($ticket, $user)); }
case 'moderator': if (config('SETTINGS::TICKET:NOTIFY') == "moderator") {
$admin = User::where('role', 'mod')->get(); $admin = User::where('role', 'mod')->get();
Notification::send($admin, new AdminCreateNotification($ticket, $user));
} }
$user->notify(new CreateNotification($ticket)); $user->notify(new CreateNotification($ticket));
if (config('SETTINGS::TICKET:NOTIFY') != "none") {
Notification::send($admin, new AdminCreateNotification($ticket, $user));
}
return redirect()->route('ticket.index')->with('success', __('A ticket has been opened, ID: #') . $ticket->ticket_id); return redirect()->route('ticket.index')->with('success', __('A ticket has been opened, ID: #') . $ticket->ticket_id);
} }
public function show($ticket_id, PterodactylSettings $ptero_settings) public function show($ticket_id)
{ {
try { try {
$ticket = Ticket::where('ticket_id', $ticket_id)->firstOrFail(); $ticket = Ticket::where('ticket_id', $ticket_id)->firstOrFail();
@ -81,9 +73,8 @@ class TicketsController extends Controller
$ticketcomments = $ticket->ticketcomments; $ticketcomments = $ticket->ticketcomments;
$ticketcategory = $ticket->ticketcategory; $ticketcategory = $ticket->ticketcategory;
$server = Server::where('id', $ticket->server)->first(); $server = Server::where('id', $ticket->server)->first();
$pterodactyl_url = $ptero_settings->panel_url;
return view('ticket.show', compact('ticket', 'ticketcategory', 'ticketcomments', 'server', 'pterodactyl_url')); return view('ticket.show', compact('ticket', 'ticketcategory', 'ticketcomments', 'server'));
} }
public function reply(Request $request) public function reply(Request $request)
@ -179,10 +170,8 @@ class TicketsController extends Controller
return __($tickets->priority); return __($tickets->priority);
}) })
->editColumn('updated_at', function (Ticket $tickets) { ->editColumn('updated_at', function (Ticket $tickets) {
return [ return ['display' => $tickets->updated_at ? $tickets->updated_at->diffForHumans() : '',
'display' => $tickets->updated_at ? $tickets->updated_at->diffForHumans() : '', 'raw' => $tickets->updated_at ? strtotime($tickets->updated_at) : ''];
'raw' => $tickets->updated_at ? strtotime($tickets->updated_at) : ''
];
}) })
->addColumn('actions', function (Ticket $tickets) { ->addColumn('actions', function (Ticket $tickets) {
$statusButtonColor = ($tickets->status == "Closed") ? 'btn-success' : 'btn-warning'; $statusButtonColor = ($tickets->status == "Closed") ? 'btn-success' : 'btn-warning';

View file

@ -16,6 +16,8 @@ class GlobalNames
*/ */
public function handle(Request $request, Closure $next) public function handle(Request $request, Closure $next)
{ {
define('CREDITS_DISPLAY_NAME', config('SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME', 'Credits'));
$unsupported_lang_array = explode(',', config('app.unsupported_locales')); $unsupported_lang_array = explode(',', config('app.unsupported_locales'));
$unsupported_lang_array = array_map('strtolower', $unsupported_lang_array); $unsupported_lang_array = array_map('strtolower', $unsupported_lang_array);
define('UNSUPPORTED_LANGS', $unsupported_lang_array); define('UNSUPPORTED_LANGS', $unsupported_lang_array);

View file

@ -2,7 +2,6 @@
namespace App\Http\Middleware; namespace App\Http\Middleware;
use App\Settings\LocaleSettings;
use Closure; use Closure;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\App;
@ -10,12 +9,6 @@ use Illuminate\Support\Facades\Session;
class SetLocale class SetLocale
{ {
private $locale_settings;
public function __construct(LocaleSettings $locale_settings)
{
$this->locale_settings = $locale_settings;
}
/** /**
* Handle an incoming request. * Handle an incoming request.
* *
@ -26,15 +19,15 @@ class SetLocale
public function handle($request, Closure $next) public function handle($request, Closure $next)
{ {
if (Session::has('locale')) { if (Session::has('locale')) {
$locale = Session::get('locale', $this->locale_settings->default); $locale = Session::get('locale', config('SETTINGS::LOCALE:DEFAULT'));
} else { } else {
if (!$this->locale_settings->dynamic) { if (config('SETTINGS::LOCALE:DYNAMIC') !== 'true') {
$locale = $this->locale_settings->default; $locale = config('SETTINGS::LOCALE:DEFAULT');
} else { } else {
$locale = substr($request->server('HTTP_ACCEPT_LANGUAGE'), 0, 2); $locale = substr($request->server('HTTP_ACCEPT_LANGUAGE'), 0, 2);
if (! in_array($locale, explode(',', $this->locale_settings->available))) { if (! in_array($locale, explode(',', config('SETTINGS::LOCALE:AVAILABLE')))) {
$locale = $this->locale_settings->default; $locale = config('SETTINGS::LOCALE:DEFAULT');
} }
} }
} }

View file

@ -3,27 +3,13 @@
namespace App\Listeners; namespace App\Listeners;
use App\Events\PaymentEvent; use App\Events\PaymentEvent;
use App\Settings\InvoiceSettings;
use App\Traits\Invoiceable; use App\Traits\Invoiceable;
class CreateInvoice class CreateInvoice
{ {
use Invoiceable; use Invoiceable;
private $invoice_enabled;
private $invoice_settings;
/**
* Create the event listener.
*
* @return void
*/
public function __construct(InvoiceSettings $invoice_settings)
{
$this->invoice_enabled = $invoice_settings->enabled;
$this->invoice_settings = $invoice_settings;
}
/** /**
* Handle the event. * Handle the event.
* *
@ -32,9 +18,9 @@ class CreateInvoice
*/ */
public function handle(PaymentEvent $event) public function handle(PaymentEvent $event)
{ {
if ($this->invoice_enabled) { if (config('SETTINGS::INVOICE:ENABLED') == 'true') {
// create invoice using the trait // create invoice using the trait
$this->createInvoice($event->payment, $event->shopProduct, $this->invoice_settings); $this->createInvoice($event->payment, $event->shopProduct);
} }
} }
} }

View file

@ -4,24 +4,11 @@ namespace App\Listeners;
use App\Events\UserUpdateCreditsEvent; use App\Events\UserUpdateCreditsEvent;
use App\Models\Server; use App\Models\Server;
use App\Settings\UserSettings;
use Exception; use Exception;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
class UnsuspendServers implements ShouldQueue class UnsuspendServers implements ShouldQueue
{ {
private $min_credits_to_make_server;
/**
* Create the event listener.
*
* @return void
*/
public function __construct(UserSettings $user_settings)
{
$this->min_credits_to_make_server = $user_settings->min_credits_to_make_server;
}
/** /**
* Handle the event. * Handle the event.
* *
@ -32,7 +19,7 @@ class UnsuspendServers implements ShouldQueue
*/ */
public function handle(UserUpdateCreditsEvent $event) public function handle(UserUpdateCreditsEvent $event)
{ {
if ($event->user->credits > $this->min_credits_to_make_server) { if ($event->user->credits > config('SETTINGS::USER:MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER', 50)) {
/** @var Server $server */ /** @var Server $server */
foreach ($event->user->servers as $server) { foreach ($event->user->servers as $server) {
if ($server->isSuspended()) { if ($server->isSuspended()) {

View file

@ -6,36 +6,11 @@ use App\Events\PaymentEvent;
use App\Models\User; use App\Models\User;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use App\Models\PartnerDiscount; use App\Models\PartnerDiscount;
use App\Settings\GeneralSettings; use Illuminate\Contracts\Queue\ShouldQueue;
use App\Settings\ReferralSettings; use Illuminate\Queue\InteractsWithQueue;
use App\Settings\UserSettings;
class UserPayment class UserPayment
{ {
private $server_limit_after_irl_purchase;
private $referral_mode;
private $referral_percentage;
private $referral_always_give_commission;
private $credits_display_name;
/**
* Create the event listener.
*
* @return void
*/
public function __construct(UserSettings $user_settings, ReferralSettings $referral_settings, GeneralSettings $general_settings)
{
$this->server_limit_after_irl_purchase = $user_settings->server_limit_after_irl_purchase;
$this->referral_mode = $referral_settings->mode;
$this->referral_percentage = $referral_settings->percentage;
$this->referral_always_give_commission = $referral_settings->always_give_commission;
$this->credits_display_name = $general_settings->credits_display_name;
}
/** /**
* Handle the event. * Handle the event.
* *
@ -53,8 +28,8 @@ class UserPayment
} }
//update server limit //update server limit
if ($this->server_limit_after_irl_purchase !== 0 && $user->server_limit < $this->server_limit_after_irl_purchase) { if (config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE') !== 0 && $user->server_limit < config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE')) {
$user->update(['server_limit' => $this->server_limit_after_irl_purchase]); $user->update(['server_limit' => config('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE')]);
} }
//update User with bought item //update User with bought item
@ -65,17 +40,17 @@ class UserPayment
} }
//give referral commission always //give referral commission always
if (($this->referral_mode === "commission" || $this->referral_mode === "both") && $shopProduct->type == "Credits" && $this->referral_always_give_commission) { if ((config("SETTINGS::REFERRAL:MODE") == "commission" || config("SETTINGS::REFERRAL:MODE") == "both") && $shopProduct->type == "Credits" && config("SETTINGS::REFERRAL::ALWAYS_GIVE_COMMISSION") == "true") {
if ($ref_user = DB::table("user_referrals")->where('registered_user_id', '=', $user->id)->first()) { if ($ref_user = DB::table("user_referrals")->where('registered_user_id', '=', $user->id)->first()) {
$ref_user = User::findOrFail($ref_user->referral_id); $ref_user = User::findOrFail($ref_user->referral_id);
$increment = number_format($shopProduct->quantity * (PartnerDiscount::getCommission($ref_user->id, $this->referral_percentage)) / 100, 0, "", ""); $increment = number_format($shopProduct->quantity * (PartnerDiscount::getCommission($ref_user->id)) / 100, 0, "", "");
$ref_user->increment('credits', $increment); $ref_user->increment('credits', $increment);
//LOGS REFERRALS IN THE ACTIVITY LOG //LOGS REFERRALS IN THE ACTIVITY LOG
activity() activity()
->performedOn($user) ->performedOn($user)
->causedBy($ref_user) ->causedBy($ref_user)
->log('gained ' . $increment . ' ' . $this->credits_display_name . ' for commission-referral of ' . $user->name . ' (ID:' . $user->id . ')'); ->log('gained ' . $increment . ' ' . config("SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME") . ' for commission-referral of ' . $user->name . ' (ID:' . $user->id . ')');
} }
} }
//update role give Referral-reward //update role give Referral-reward
@ -83,17 +58,17 @@ class UserPayment
$user->update(['role' => 'client']); $user->update(['role' => 'client']);
//give referral commission only on first purchase //give referral commission only on first purchase
if (($this->referral_mode === "commission" || $this->referral_mode === "both") && $shopProduct->type == "Credits" && !$this->referral_always_give_commission) { if ((config("SETTINGS::REFERRAL:MODE") == "commission" || config("SETTINGS::REFERRAL:MODE") == "both") && $shopProduct->type == "Credits" && config("SETTINGS::REFERRAL::ALWAYS_GIVE_COMMISSION") == "false") {
if ($ref_user = DB::table("user_referrals")->where('registered_user_id', '=', $user->id)->first()) { if ($ref_user = DB::table("user_referrals")->where('registered_user_id', '=', $user->id)->first()) {
$ref_user = User::findOrFail($ref_user->referral_id); $ref_user = User::findOrFail($ref_user->referral_id);
$increment = number_format($shopProduct->quantity * (PartnerDiscount::getCommission($ref_user->id, $this->referral_percentage)) / 100, 0, "", ""); $increment = number_format($shopProduct->quantity * (PartnerDiscount::getCommission($ref_user->id)) / 100, 0, "", "");
$ref_user->increment('credits', $increment); $ref_user->increment('credits', $increment);
//LOGS REFERRALS IN THE ACTIVITY LOG //LOGS REFERRALS IN THE ACTIVITY LOG
activity() activity()
->performedOn($user) ->performedOn($user)
->causedBy($ref_user) ->causedBy($ref_user)
->log('gained ' . $increment . ' ' . $this->credits_display_name . ' for commission-referral of ' . $user->name . ' (ID:' . $user->id . ')'); ->log('gained ' . $increment . ' ' . config("SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME") . ' for commission-referral of ' . $user->name . ' (ID:' . $user->id . ')');
} }
} }
} }

View file

@ -2,23 +2,16 @@
namespace App\Listeners; namespace App\Listeners;
use App\Settings\UserSettings;
class Verified class Verified
{ {
private $server_limit_after_verify_email;
private $credits_reward_after_verify_email;
/** /**
* Create the event listener. * Create the event listener.
* *
* @return void * @return void
*/ */
public function __construct(UserSettings $user_settings) public function __construct()
{ {
$this->server_limit_after_verify_email = $user_settings->server_limit_after_verify_email; //
$this->credits_reward_after_verify_email = $user_settings->credits_reward_after_verify_email;
} }
/** /**
@ -30,8 +23,8 @@ class Verified
public function handle($event) public function handle($event)
{ {
if (! $event->user->email_verified_reward) { if (! $event->user->email_verified_reward) {
$event->user->increment('server_limit', $this->server_limit_after_verify_email); $event->user->increment('server_limit', config('SETTINGS::USER:SERVER_LIMIT_REWARD_AFTER_VERIFY_EMAIL'));
$event->user->increment('credits', $this->credits_reward_after_verify_email); $event->user->increment('credits', config('SETTINGS::USER:CREDITS_REWARD_AFTER_VERIFY_EMAIL'));
} }
} }
} }

View file

@ -1,14 +1,12 @@
<?php <?php
namespace App\Models\Pterodactyl; namespace App\Models;
use App\Classes\PterodactylClient; use App\Classes\Pterodactyl;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use App\Models\Pterodactyl\Nest;
use App\Models\Product;
class Egg extends Model class Egg extends Model
{ {
@ -39,9 +37,9 @@ class Egg extends Model
public static function syncEggs() public static function syncEggs()
{ {
Nest::syncNests(); Nest::syncNests();
$client = app(PterodactylClient::class);
Nest::all()->each(function (Nest $nest) use ($client) { Nest::all()->each(function (Nest $nest) {
$eggs = $client->getEggs($nest); $eggs = Pterodactyl::getEggs($nest);
foreach ($eggs as $egg) { foreach ($eggs as $egg) {
$array = []; $array = [];

View file

@ -1,8 +1,8 @@
<?php <?php
namespace App\Models\Pterodactyl; namespace App\Models;
use App\Classes\PterodactylClient; use App\Classes\Pterodactyl;
use Exception; use Exception;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
@ -33,8 +33,7 @@ class Location extends Model
*/ */
public static function syncLocations() public static function syncLocations()
{ {
$client = app(PterodactylClient::class); $locations = Pterodactyl::getLocations();
$locations = $client->getLocations();
//map response //map response
$locations = array_map(function ($val) { $locations = array_map(function ($val) {

View file

@ -1,8 +1,8 @@
<?php <?php
namespace App\Models\Pterodactyl; namespace App\Models;
use App\Classes\PterodactylClient; use App\Classes\Pterodactyl;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
@ -32,8 +32,7 @@ class Nest extends Model
public static function syncNests() public static function syncNests()
{ {
$client = app(PterodactylClient::class); $nests = Pterodactyl::getNests();
$nests = $client->getNests();
//map response //map response
$nests = array_map(function ($nest) { $nests = array_map(function ($nest) {

View file

@ -1,14 +1,13 @@
<?php <?php
namespace App\Models\Pterodactyl; namespace App\Models;
use App\Classes\PterodactylClient; use App\Classes\Pterodactyl;
use Exception; use Exception;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use App\Models\Product;
class Node extends Model class Node extends Model
{ {
@ -33,8 +32,7 @@ class Node extends Model
public static function syncNodes() public static function syncNodes()
{ {
Location::syncLocations(); Location::syncLocations();
$client = app(PterodactylClient::class); $nodes = Pterodactyl::getNodes();
$nodes = $client->getNodes();
//map response //map response
$nodes = array_map(function ($node) { $nodes = array_map(function ($node) {

View file

@ -33,7 +33,7 @@ class PartnerDiscount extends Model
return 0; return 0;
} }
public static function getCommission($user_id, $percentage) public static function getCommission($user_id)
{ {
if ($partnerDiscount = PartnerDiscount::where('user_id', $user_id)->first()) { if ($partnerDiscount = PartnerDiscount::where('user_id', $user_id)->first()) {
if ($partnerDiscount->referral_system_commission >= 0) { if ($partnerDiscount->referral_system_commission >= 0) {
@ -41,6 +41,6 @@ class PartnerDiscount extends Model
} }
} }
return $percentage; return config('SETTINGS::REFERRAL:PERCENTAGE');
} }
} }

View file

@ -9,8 +9,6 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Spatie\Activitylog\LogOptions; use Spatie\Activitylog\LogOptions;
use Spatie\Activitylog\Traits\LogsActivity; use Spatie\Activitylog\Traits\LogsActivity;
use App\Models\Pterodactyl\Egg;
use App\Models\Pterodactyl\Node;
class Product extends Model class Product extends Model
{ {

View file

@ -2,8 +2,7 @@
namespace App\Models; namespace App\Models;
use App\Classes\PterodactylClient; use App\Classes\Pterodactyl;
use App\Settings\PterodactylSettings;
use Exception; use Exception;
use GuzzleHttp\Promise\PromiseInterface; use GuzzleHttp\Promise\PromiseInterface;
use Hidehalo\Nanoid\Client; use Hidehalo\Nanoid\Client;
@ -22,9 +21,6 @@ class Server extends Model
{ {
use HasFactory; use HasFactory;
use LogsActivity; use LogsActivity;
private PterodactylClient $pterodactyl;
public function getActivitylogOptions(): LogOptions public function getActivitylogOptions(): LogOptions
{ {
return LogOptions::defaults() return LogOptions::defaults()
@ -32,7 +28,6 @@ class Server extends Model
-> logOnly(['*']) -> logOnly(['*'])
-> dontSubmitEmptyLogs(); -> dontSubmitEmptyLogs();
} }
/** /**
* @var bool * @var bool
*/ */
@ -67,12 +62,6 @@ class Server extends Model
'suspended' => 'datetime', 'suspended' => 'datetime',
]; ];
public function __construct()
{
$ptero_settings = new PterodactylSettings();
$this->pterodactyl = new PterodactylClient($ptero_settings);
}
public static function boot() public static function boot()
{ {
parent::boot(); parent::boot();
@ -84,7 +73,7 @@ class Server extends Model
}); });
static::deleting(function (Server $server) { static::deleting(function (Server $server) {
$response = $server->pterodactyl->application->delete("/application/servers/{$server->pterodactyl_id}"); $response = Pterodactyl::client()->delete("/application/servers/{$server->pterodactyl_id}");
if ($response->failed() && ! is_null($server->pterodactyl_id)) { if ($response->failed() && ! is_null($server->pterodactyl_id)) {
//only return error when it's not a 404 error //only return error when it's not a 404 error
if ($response['errors'][0]['status'] != '404') { if ($response['errors'][0]['status'] != '404') {
@ -107,7 +96,7 @@ class Server extends Model
*/ */
public function getPterodactylServer() public function getPterodactylServer()
{ {
return $this->pterodactyl->application->get("/application/servers/{$this->pterodactyl_id}"); return Pterodactyl::client()->get("/application/servers/{$this->pterodactyl_id}");
} }
/** /**
@ -115,7 +104,7 @@ class Server extends Model
*/ */
public function suspend() public function suspend()
{ {
$response = $this->pterodactyl->suspendServer($this); $response = Pterodactyl::suspendServer($this);
if ($response->successful()) { if ($response->successful()) {
$this->update([ $this->update([
@ -131,7 +120,7 @@ class Server extends Model
*/ */
public function unSuspend() public function unSuspend()
{ {
$response = $this->pterodactyl->unSuspendServer($this); $response = Pterodactyl::unSuspendServer($this);
if ($response->successful()) { if ($response->successful()) {
$this->update([ $this->update([

View file

@ -4,8 +4,48 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache;
class Settings extends Model class Settings extends Model
{ {
use HasFactory; use HasFactory;
protected $table = 'settings';
public const CACHE_TAG = 'setting';
public $primaryKey = 'key';
public $incrementing = false;
protected $keyType = 'string';
protected $fillable = [
'key',
'value',
'type',
];
public static function boot()
{
parent::boot();
static::updated(function (Settings $settings) {
Cache::forget(self::CACHE_TAG.':'.$settings->key);
});
}
/**
* @param string $key
* @param $default
* @return mixed
*/
public static function getValueByKey(string $key, $default = null)
{
return Cache::rememberForever(self::CACHE_TAG.':'.$key, function () use ($default, $key) {
$settings = self::find($key);
return $settings ? $settings->value : $default;
});
}
} }

View file

@ -2,12 +2,9 @@
namespace App\Models; namespace App\Models;
use App\Classes\Pterodactyl;
use App\Notifications\Auth\QueuedVerifyEmail; use App\Notifications\Auth\QueuedVerifyEmail;
use App\Notifications\WelcomeMessage; use App\Notifications\WelcomeMessage;
use App\Settings\GeneralSettings;
use App\Settings\UserSettings;
use App\Classes\PterodactylClient;
use App\Settings\PterodactylSettings;
use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\BelongsToMany;
@ -26,8 +23,6 @@ class User extends Authenticatable implements MustVerifyEmail
{ {
use HasFactory, Notifiable, LogsActivity, CausesActivity; use HasFactory, Notifiable, LogsActivity, CausesActivity;
private PterodactylClient $pterodactyl;
/** /**
* @var string[] * @var string[]
*/ */
@ -90,18 +85,12 @@ class User extends Authenticatable implements MustVerifyEmail
'server_limit' => 'float', 'server_limit' => 'float',
]; ];
public function __construct()
{
$ptero_settings = new PterodactylSettings();
$this->pterodactyl = new PterodactylClient($ptero_settings);
}
public static function boot() public static function boot()
{ {
parent::boot(); parent::boot();
static::created(function (User $user, GeneralSettings $general_settings, UserSettings $user_settings) { static::created(function (User $user) {
$user->notify(new WelcomeMessage($user, $general_settings, $user_settings)); $user->notify(new WelcomeMessage($user));
}); });
static::deleting(function (User $user) { static::deleting(function (User $user) {
@ -122,7 +111,7 @@ class User extends Authenticatable implements MustVerifyEmail
$user->discordUser()->delete(); $user->discordUser()->delete();
$user->pterodactyl->application->delete("/application/users/{$user->pterodactyl_id}"); Pterodactyl::client()->delete("/application/users/{$user->pterodactyl_id}");
}); });
} }
@ -195,6 +184,9 @@ class User extends Authenticatable implements MustVerifyEmail
return $this->suspended; return $this->suspended;
} }
/**
* @throws Exception
*/
public function suspend() public function suspend()
{ {
foreach ($this->servers as $server) { foreach ($this->servers as $server) {
@ -208,6 +200,9 @@ class User extends Authenticatable implements MustVerifyEmail
return $this; return $this;
} }
/**
* @throws Exception
*/
public function unSuspend() public function unSuspend()
{ {
foreach ($this->getServersWithProduct() as $server) { foreach ($this->getServersWithProduct() as $server) {
@ -235,9 +230,23 @@ class User extends Authenticatable implements MustVerifyEmail
*/ */
public function getAvatar() public function getAvatar()
{ {
//TODO loading the images to confirm they exist is causing to much load time. alternative has to be found :) maybe onerror tag on the <img tags>
// if ($this->discordUser()->exists()) {
// if(@getimagesize($this->discordUser->getAvatar())) {
// $avatar = $this->discordUser->getAvatar();
// } else {
// $avatar = "https://www.gravatar.com/avatar/" . md5(strtolower(trim($this->email)));
// }
// } else {
// $avatar = "https://www.gravatar.com/avatar/" . md5(strtolower(trim($this->email)));
// }
return 'https://www.gravatar.com/avatar/' . md5(strtolower(trim($this->email))); return 'https://www.gravatar.com/avatar/' . md5(strtolower(trim($this->email)));
} }
/**
* @return string
*/
public function creditUsage() public function creditUsage()
{ {
$usage = 0; $usage = 0;

View file

@ -3,8 +3,6 @@
namespace App\Notifications; namespace App\Notifications;
use App\Models\User; use App\Models\User;
use App\Settings\GeneralSettings;
use App\Settings\ReferralSettings;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification; use Illuminate\Notifications\Notification;
@ -17,8 +15,6 @@ class ReferralNotification extends Notification
*/ */
private $user; private $user;
private $ref_user;
/** /**
* Create a new notification instance. * Create a new notification instance.
* *
@ -47,12 +43,12 @@ class ReferralNotification extends Notification
* @param mixed $notifiable * @param mixed $notifiable
* @return array * @return array
*/ */
public function toArray($notifiable, GeneralSettings $general_settings, ReferralSettings $referral_settings) public function toArray($notifiable)
{ {
return [ return [
'title' => __('Someone registered using your Code!'), 'title' => __('Someone registered using your Code!'),
'content' => ' 'content' => '
<p>You received '. $referral_settings->reward . ' ' . $general_settings->credits_display_name . '</p> <p>You received '.config('SETTINGS::REFERRAL::REWARD').' '.config('SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME').'</p>
<p>because '.$this->ref_user->name.' registered with your Referral-Code!</p> <p>because '.$this->ref_user->name.' registered with your Referral-Code!</p>
<p>Thank you very much for supporting us!.</p> <p>Thank you very much for supporting us!.</p>
<p>'.config('app.name', 'Laravel').'</p> <p>'.config('app.name', 'Laravel').'</p>

View file

@ -3,8 +3,6 @@
namespace App\Notifications; namespace App\Notifications;
use App\Models\User; use App\Models\User;
use App\Settings\GeneralSettings;
use App\Settings\UserSettings;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Notification; use Illuminate\Notifications\Notification;
@ -18,29 +16,14 @@ class WelcomeMessage extends Notification implements ShouldQueue
*/ */
private $user; private $user;
private $credits_display_name;
private $credits_reward_after_verify_discord;
private $credits_reward_after_verify_email;
private $server_limit_after_verify_discord;
private $server_limit_after_verify_email;
/** /**
* Create a new notification instance. * Create a new notification instance.
* *
* @param User $user * @param User $user
*/ */
public function __construct(User $user, GeneralSettings $general_settings, UserSettings $user_settings) public function __construct(User $user)
{ {
$this->user = $user; $this->user = $user;
$this->credits_display_name = $general_settings->credits_display_name;
$this->credits_reward_after_verify_discord = $user_settings->credits_reward_after_verify_discord;
$this->credits_reward_after_verify_email = $user_settings->credits_reward_after_verify_email;
$this->server_limit_after_verify_discord = $user_settings->server_limit_after_verify_discord;
$this->server_limit_after_verify_email = $user_settings->server_limit_after_verify_email;
} }
/** /**
@ -57,18 +40,18 @@ class WelcomeMessage extends Notification implements ShouldQueue
public function AdditionalLines() public function AdditionalLines()
{ {
$AdditionalLine = ''; $AdditionalLine = '';
if ($this->credits_reward_after_verify_email != 0) { if (config('SETTINGS::USER:CREDITS_REWARD_AFTER_VERIFY_EMAIL') != 0) {
$AdditionalLine .= __('Verifying your e-mail address will grant you ').$this->credits_reward_after_verify_email.' '.__('additional').' '.$this->credits_display_name.'. <br />'; $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 ($this->server_limit_after_verify_email != 0) { if (config('SETTINGS::USER:SERVER_LIMIT_REWARD_AFTER_VERIFY_EMAIL') != 0) {
$AdditionalLine .= __('Verifying your e-mail will also increase your Server Limit by ').$this->server_limit_after_verify_email.'. <br />'; $AdditionalLine .= __('Verifying your e-mail will also increase your Server Limit by ').config('SETTINGS::USER:SERVER_LIMIT_REWARD_AFTER_VERIFY_EMAIL').'. <br />';
} }
$AdditionalLine .= '<br />'; $AdditionalLine .= '<br />';
if ($this->credits_reward_after_verify_discord != 0) { if (config('SETTINGS::USER:CREDITS_REWARD_AFTER_VERIFY_DISCORD') != 0) {
$AdditionalLine .= __('You can also verify your discord account to get another ').$this->credits_reward_after_verify_discord.' '.$this->credits_display_name.'. <br />'; $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 ($this->server_limit_after_verify_discord != 0) { if (config('SETTINGS::USER:SERVER_LIMIT_REWARD_AFTER_VERIFY_DISCORD') != 0) {
$AdditionalLine .= __('Verifying your Discord account will also increase your Server Limit by ').$this->server_limit_after_verify_discord.'. <br />'; $AdditionalLine .= __('Verifying your Discord account will also increase your Server Limit by ').config('SETTINGS::USER:SERVER_LIMIT_REWARD_AFTER_VERIFY_DISCORD').'. <br />';
} }
return $AdditionalLine; return $AdditionalLine;

View file

@ -2,17 +2,16 @@
namespace App\Providers; namespace App\Providers;
use App\Extensions\PaymentGateways\PayPal\PayPalSettings; use App\Models\Settings;
use App\Models\UsefulLink; use App\Models\UsefulLink;
use App\Settings\MailSettings;
use Exception; use Exception;
use Illuminate\Pagination\Paginator; use Illuminate\Pagination\Paginator;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Schema; use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\Facades\Validator; use Illuminate\Support\Facades\Validator;
use Illuminate\Support\ServiceProvider; use Illuminate\Support\ServiceProvider;
use Qirolab\Theme\Theme;
class AppServiceProvider extends ServiceProvider class AppServiceProvider extends ServiceProvider
{ {
@ -55,14 +54,6 @@ class AppServiceProvider extends ServiceProvider
return $ok; return $ok;
}); });
// Force HTTPS if APP_URL is set to https
if (config('app.url') && parse_url(config('app.url'), PHP_URL_SCHEME) === 'https') {
URL::forceScheme('https');
}
// Do not run this code if no APP_KEY is set
if (config('app.key') == null) return;
try { try {
if (Schema::hasColumn('useful_links', 'position')) { if (Schema::hasColumn('useful_links', 'position')) {
$useful_links = UsefulLink::where("position", "like", "%topbar%")->get()->sortby("id"); $useful_links = UsefulLink::where("position", "like", "%topbar%")->get()->sortby("id");
@ -72,8 +63,92 @@ class AppServiceProvider extends ServiceProvider
Log::error("Couldnt find useful_links. Probably the installation is not completet. " . $e); Log::error("Couldnt find useful_links. Probably the installation is not completet. " . $e);
} }
//only run if the installer has been executed
try {
$settings = Settings::all();
// Set all configs from database
foreach ($settings as $setting) {
config([$setting->key => $setting->value]);
}
$settings = $this->app->make(MailSettings::class); if (!file_exists(base_path('themes') . "/" . config("SETTINGS::SYSTEM:THEME"))) {
$settings->setConfig(); config(['SETTINGS::SYSTEM:THEME' => "default"]);
}
if (config('SETTINGS::SYSTEM:THEME') && config('SETTINGS::SYSTEM:THEME') !== config('theme.active')) {
Theme::set(config("SETTINGS::SYSTEM:THEME", "default"), "default");
} else {
Theme::set("default", "default");
}
// 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
// Load recaptcha package if recaptcha is enabled
if (config('SETTINGS::RECAPTCHA:ENABLED') == 'true') {
$this->app->register(\Biscolab\ReCaptcha\ReCaptchaServiceProvider::class);
}
//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');
}
try {
$stringfromfile = file(base_path() . '/.git/HEAD');
$firstLine = $stringfromfile[0]; //get the string from the array
$explodedstring = explode('/', $firstLine, 3); //seperate out by the "/" in the string
$branchname = $explodedstring[2]; //get the one that is always the branch name
} catch (Exception $e) {
$branchname = 'unknown';
Log::notice($e);
}
config(['BRANCHNAME' => $branchname]);
// Set Discord-API Config
config(['services.discord.client_id' => config('SETTINGS::DISCORD:CLIENT_ID')]);
config(['services.discord.client_secret' => config('SETTINGS::DISCORD:CLIENT_SECRET')]);
} catch (Exception $e) {
error_log('Settings Error: Could not load settings from database. The Installation probably is not done yet.');
error_log($e);
Log::error('Settings Error: Could not load settings from database. The Installation probably is not done yet.');
Log::error($e);
}
} }
} }

View file

@ -1,87 +0,0 @@
<?php
namespace App\Settings;
use Spatie\LaravelSettings\Settings;
class DiscordSettings extends Settings
{
public ?string $bot_token;
public ?string $client_id;
public ?string $client_secret;
public ?string $guild_id;
public ?string $invite_url;
public ?string $role_id;
public static function group(): string
{
return 'discord';
}
public static function encrypted(): array
{
return [
'bot_token',
'client_id',
'client_secret'
];
}
/**
* Summary of validations array
* @return array<string, string>
*/
public static function getValidations()
{
return [
'bot_token' => 'nullable|string',
'client_id' => 'nullable|string',
'client_secret' => 'nullable|string',
'guild_id' => 'nullable|string',
'invite_url' => 'nullable|string|url',
'role_id' => 'nullable|string',
];
}
/**
* Summary of optionInputData array
* Only used for the settings page
* @return array<array<'type'|'label'|'description'|'options', string|bool|float|int|array<string, string>>>
*/
public static function getOptionInputData()
{
return [
'category_icon' => 'fas fa-user-friends',
'bot_token' => [
'label' => 'Bot Token',
'type' => 'string',
'description' => 'The bot token for your Discord bot.',
],
'client_id' => [
'label' => 'Client ID',
'type' => 'string',
'description' => 'The client ID for your Discord bot.',
],
'client_secret' => [
'label' => 'Client Secret',
'type' => 'string',
'description' => 'The client secret for your Discord bot.',
],
'guild_id' => [
'label' => 'Guild ID',
'type' => 'string',
'description' => 'The guild ID for your Discord server.',
],
'invite_url' => [
'label' => 'Invite URL',
'type' => 'string',
'description' => 'The invite URL for your Discord server.',
],
'role_id' => [
'label' => 'Role ID',
'type' => 'string',
'description' => 'The role ID for your Discord server.',
],
];
}
}

View file

@ -1,138 +0,0 @@
<?php
namespace App\Settings;
use Spatie\LaravelSettings\Settings;
class GeneralSettings extends Settings
{
public bool $store_enabled;
public string $credits_display_name;
public bool $recaptcha_enabled;
public string $recaptcha_site_key;
public string $recaptcha_secret_key;
public string $phpmyadmin_url;
public bool $alert_enabled;
public string $alert_type;
public string $alert_message;
public string $theme;
//public int $initial_user_role; wait for Roles & Permissions PR.
public static function group(): string
{
return 'general';
}
public static function encrypted(): array
{
return [
'recaptcha_site_key',
'recaptcha_secret_key'
];
}
/**
* Summary of validations array
* @return array<string, string>
*/
public static function getValidations()
{
return [
'store_enabled' => 'boolean',
'credits_display_name' => 'required|string',
'recaptcha_enabled' => 'nullable|boolean',
'recaptcha_site_key' => 'nullable|string',
'recaptcha_secret_key' => 'nullable|string',
'phpmyadmin_url' => 'nullable|string',
'alert_enabled' => 'nullable|boolean',
'alert_type' => 'required|in:primary,secondary,success,danger,warning,info',
'alert_message' => 'required|string',
'theme' => 'required|in:default,BlueInfinity' // TODO: themes should be made/loaded dynamically
];
}
/**
* Summary of optionTypes
* Only used for the settings page
* @return array<array<'type'|'label'|'description'|'options', string|bool|float|int|array<string, string>>>
*/
public static function getOptionInputData()
{
return [
'category_icon' => "fas fa-cog",
'store_enabled' => [
'type' => 'boolean',
'label' => 'Enable Store',
'description' => 'Enable the store for users to purchase credits.'
],
'credits_display_name' => [
'type' => 'string',
'label' => 'Credits Display Name',
'description' => 'The name of the currency used.'
],
'initial_user_credits' => [
'type' => 'number',
'label' => 'Initial User Credits',
'description' => 'The amount of credits a user gets when they register.'
],
'initial_server_limit' => [
'type' => 'number',
'label' => 'Initial Server Limit',
'description' => 'The amount of servers a user can create when they register.'
],
'recaptcha_enabled' => [
'type' => 'boolean',
'label' => 'Enable reCAPTCHA',
'description' => 'Enable reCAPTCHA on the login page.'
],
'recaptcha_site_key' => [
'type' => 'string',
'label' => 'reCAPTCHA Site Key',
'description' => 'The site key for reCAPTCHA.'
],
'recaptcha_secret_key' => [
'type' => 'string',
'label' => 'reCAPTCHA Secret Key',
'description' => 'The secret key for reCAPTCHA.'
],
'phpmyadmin_url' => [
'type' => 'string',
'label' => 'phpMyAdmin URL',
'description' => 'The URL of your phpMyAdmin installation.'
],
'alert_enabled' => [
'type' => 'boolean',
'label' => 'Enable Alert',
'description' => 'Enable an alert to be displayed on the home page.'
],
'alert_type' => [
'type' => 'select',
'label' => 'Alert Type',
'options' => [
'primary' => 'Blue',
'secondary' => 'Grey',
'success' => 'Green',
'danger' => 'Red',
'warning' => 'Orange',
'info' => 'Cyan',
],
'description' => 'The type of alert to display.'
],
'alert_message' => [
'type' => 'string',
'label' => 'Alert Message',
'description' => 'The message to display in the alert.'
],
'theme' => [
'type' => 'select',
'label' => 'Theme',
'options' => [
'default' => 'Default',
'BlueInfinity' => 'Blue Infinity',
], // TODO: themes should be made/loaded dynamically
'description' => 'The theme to use for the site.'
],
];
}
}

View file

@ -1,92 +0,0 @@
<?php
namespace App\Settings;
use Spatie\LaravelSettings\Settings;
class InvoiceSettings extends Settings
{
public ?string $company_address;
public ?string $company_mail;
public ?string $company_name;
public ?string $company_phone;
public ?string $company_vat;
public ?string $company_website;
public bool $enabled;
public ?string $prefix;
public static function group(): string
{
return 'invoice';
}
/**
* Summary of validations array
* @return array<string, string>
*/
public static function getValidations()
{
return [
'company_address' => 'nullable|string',
'company_mail' => 'nullable|string',
'company_name' => 'nullable|string',
'company_phone' => 'nullable|string',
'company_vat' => 'nullable|string',
'company_website' => 'nullable|string',
'enabled' => 'nullable|boolean',
'prefix' => 'nullable|string',
];
}
/**
* Summary of optionTypes
* Only used for the settings page
* @return array<array<'type'|'label'|'description'|'options', string|bool|float|int|array<string, string>>>
*/
public static function getOptionInputData()
{
return [
'category_icon' => 'fas fa-file-invoice-dollar',
'company_address' => [
'label' => 'Company Address',
'type' => 'string',
'description' => 'The address of your company.',
],
'company_mail' => [
'label' => 'Company Mail',
'type' => 'string',
'description' => 'The mail of your company.',
],
'company_name' => [
'label' => 'Company Name',
'type' => 'string',
'description' => 'The name of your company.',
],
'company_phone' => [
'label' => 'Company Phone',
'type' => 'string',
'description' => 'The phone of your company.',
],
'company_vat' => [
'label' => 'Company VAT ID',
'type' => 'string',
'description' => 'The VAT ID of your company.',
],
'company_website' => [
'label' => 'Company Website',
'type' => 'string',
'description' => 'The website of your company.',
],
'enabled' => [
'label' => 'Enabled',
'type' => 'boolean',
'description' => 'Enable or disable invoices.',
],
'prefix' => [
'label' => 'Prefix',
'type' => 'string',
'description' => 'The prefix of your invoices.',
],
];
}
}

View file

@ -1,73 +0,0 @@
<?php
namespace App\Settings;
use Spatie\LaravelSettings\Settings;
class LocaleSettings extends Settings
{
public ?string $available;
public bool $clients_can_change;
public ?string $datatables;
public string $default;
public bool $dynamic;
public static function group(): string
{
return 'locale';
}
/**
* Summary of validations array
* @return array<string, string>
*/
public static function getValidations()
{
return [
'available' => 'nullable|array',
'clients_can_change' => 'nullable|boolean',
'datatables' => 'nullable|string',
'default' => 'required|in:' . implode(',', config('app.available_locales')),
'dynamic' => 'nullable|boolean',
];
}
/**
* Summary of optionTypes
* Only used for the settings page
* @return array<array<'type'|'label'|'description'|'options', string|bool|float|int|array<string, string>>>
*/
public static function getOptionInputData()
{
return [
'category_icon' => 'fas fa-globe',
'available' => [
'label' => 'Available Locales',
'type' => 'multiselect',
'description' => 'The locales that are available for the user to choose from.',
'options' => config('app.available_locales'),
],
'clients_can_change' => [
'label' => 'Clients Can Change',
'type' => 'boolean',
'description' => 'Whether clients can change their locale.',
],
'datatables' => [
'label' => 'Datatables Locale',
'type' => 'string',
'description' => 'The datatables lang-code. <br><strong>Example:</strong> en-gb, fr_fr, de_de<br>More Information: <a href="https://datatables.net/plug-ins/i18n/">https://datatables.net/plug-ins/i18n/</a>',
],
'default' => [
'label' => 'Default Locale',
'type' => 'select',
'description' => 'The default locale to use.',
'options' => config('app.available_locales'),
],
'dynamic' => [
'label' => 'Dynamic Locale',
'type' => 'boolean',
'description' => 'Whether to use the dynamic locale.',
],
];
}
}

View file

@ -1,119 +0,0 @@
<?php
namespace App\Settings;
use Spatie\LaravelSettings\Settings;
class MailSettings extends Settings
{
public ?string $mail_host;
public ?int $mail_port;
public ?string $mail_username;
public ?string $mail_password;
public ?string $mail_encryption;
public ?string $mail_from_address;
public ?string $mail_from_name;
public ?string $mail_mailer;
public bool $mail_enabled;
public static function group(): string
{
return 'mail';
}
public static function encrypted(): array
{
return [
'mail_password'
];
}
public function setConfig()
{
try {
config()->set('mail.mailers.smtp.host', $this->mail_host);
config()->set('mail.mailers.smtp.port', $this->mail_port);
config()->set('mail.mailers.smtp.encryption', $this->mail_encryption);
config()->set('mail.mailers.smtp.username', $this->mail_username);
config()->set('mail.mailers.smtp.password', $this->mail_password);
config()->set('mail.from.address', $this->mail_from_address);
config()->set('mail.from.name', $this->mail_from_name);
} catch (\Exception) {
}
}
/**
* Summary of validations array
* @return array<string, string>
*/
public static function getValidations()
{
return [
'mail_host' => 'nullable|string',
'mail_port' => 'nullable|int',
'mail_username' => 'nullable|string',
'mail_password' => 'nullable|string',
'mail_encryption' => 'nullable|string',
'mail_from_address' => 'nullable|string',
'mail_from_name' => 'nullable|string',
'mail_mailer' => 'nullable|string',
'mail_enabled' => 'nullable|boolean',
];
}
/**
* Summary of optionTypes
* Only used for the settings page
* @return array<array<'type'|'label'|'description'|'options', string|bool|float|int|array<string, string>>>
*/
public static function getOptionInputData()
{
return [
'category_icon' => 'fas fa-envelope',
'mail_host' => [
'label' => 'Mail Host',
'type' => 'string',
'description' => 'The host of your mail server.',
],
'mail_port' => [
'label' => 'Mail Port',
'type' => 'number',
'description' => 'The port of your mail server.',
],
'mail_username' => [
'label' => 'Mail Username',
'type' => 'string',
'description' => 'The username of your mail server.',
],
'mail_password' => [
'label' => 'Mail Password',
'type' => 'string',
'description' => 'The password of your mail server.',
],
'mail_encryption' => [
'label' => 'Mail Encryption',
'type' => 'string',
'description' => 'The encryption of your mail server.',
],
'mail_from_address' => [
'label' => 'Mail From Address',
'type' => 'string',
'description' => 'The from address of your mail server.',
],
'mail_from_name' => [
'label' => 'Mail From Name',
'type' => 'string',
'description' => 'The from name of your mail server.',
],
'mail_mailer' => [
'label' => 'Mail Mailer',
'type' => 'string',
'description' => 'The mailer of your mail server.',
],
'mail_enabled' => [
'label' => 'Mail Enabled',
'type' => 'boolean',
],
];
}
}

View file

@ -1,82 +0,0 @@
<?php
namespace App\Settings;
use Spatie\LaravelSettings\Settings;
class PterodactylSettings extends Settings
{
public string $admin_token;
public string $user_token;
public string $panel_url;
public int $per_page_limit;
public static function group(): string
{
return 'pterodactyl';
}
public static function encrypted(): array
{
return [
'admin_token',
'user_token'
];
}
/**
* Get url with ensured ending backslash
*
* @return string
*/
public function getUrl(): string
{
return str_ends_with($this->panel_url, '/') ? $this->panel_url : $this->panel_url . '/';
}
/**
* Summary of validations array
* @return array<string, string>
*/
public static function getValidations()
{
return [
'panel_url' => 'required|string|url',
'admin_token' => 'required|string',
'user_token' => 'required|string',
'per_page_limit' => 'required|integer|min:1|max:10000',
];
}
/**
* Summary of optionTypes
* Only used for the settings page
* @return array<array<'type'|'label'|'description'|'options', string|bool|float|int|array<string, string>>>
*/
public static function getOptionInputData()
{
return [
'category_icon' => 'fas fa-server',
'panel_url' => [
'label' => 'Panel URL',
'type' => 'string',
'description' => 'The URL to your Pterodactyl panel.',
],
'admin_token' => [
'label' => 'Admin Token',
'type' => 'string',
'description' => 'The admin user token for your Pterodactyl panel.',
],
'user_token' => [
'label' => 'User Token',
'type' => 'string',
'description' => 'The user token for your Pterodactyl panel.',
],
'per_page_limit' => [
'label' => 'Per Page Limit',
'type' => 'number',
'description' => 'The number of servers to show per page.',
],
];
}
}

View file

@ -1,87 +0,0 @@
<?php
namespace App\Settings;
use Spatie\LaravelSettings\Settings;
class ReferralSettings extends Settings
{
public string $allowed;
public bool $always_give_commission;
public bool $enabled;
public ?float $reward;
public string $mode;
public ?int $percentage;
public static function group(): string
{
return 'referral';
}
/**
* Summary of validations array
* @return array<string, string>
*/
public static function getValidations()
{
return [
'allowed' => 'required|in:Everyone,Clients',
'always_give_commission' => 'nullable|boolean',
'enabled' => 'nullable|boolean',
'reward' => 'nullable|numeric',
'mode' => 'required|in:Commission,Sign-Up,Both',
'percentage' => 'nullable|numeric',
];
}
/**
* Summary of optionTypes
* Only used for the settings page
* @return array<array<'type'|'label'|'description'|'options', string|bool|float|int|array<string, string>>>
*/
public static function getOptionInputData()
{
return [
'category_icon' => 'fas fa-user-friends',
'allowed' => [
'label' => 'Allowed',
'type' => 'select',
'description' => 'Who is allowed to see their referral-URL',
'options' => [
'everyone' => 'Everyone',
'clients' => 'Clients',
],
],
'always_give_commission' => [
'label' => 'Always Give Commission',
'type' => 'boolean',
'description' => 'Always give commission to the referrer.',
],
'enabled' => [
'label' => 'Enabled',
'type' => 'boolean',
'description' => 'Enable referral system.',
],
'reward' => [
'label' => 'Reward',
'type' => 'number',
'description' => 'Reward for the referrer.',
],
'mode' => [
'label' => 'Mode',
'type' => 'select',
'description' => 'Referral mode.',
'options' => [
'commission' => 'Commission',
'sign-up' => 'Sign-Up',
'both' => 'Both',
],
],
'percentage' => [
'label' => 'Percentage',
'type' => 'number',
'description' => 'If a referred user buys credits, the referral-user will get x% of the Credits the referred user bought.',
],
];
}
}

View file

@ -1,64 +0,0 @@
<?php
namespace App\Settings;
use Spatie\LaravelSettings\Settings;
class ServerSettings extends Settings
{
public int $allocation_limit;
public bool $creation_enabled;
public bool $enable_upgrade;
public bool $charge_first_hour;
public static function group(): string
{
return 'server';
}
/**
* Summary of validations array
* @return array<string, string>
*/
public static function getValidations()
{
return [
'allocation_limit' => 'required|integer|min:0',
'creation_enabled' => 'nullable|boolean',
'enable_upgrade' => 'nullable|boolean',
'charge_first_hour' => 'nullable|boolean',
];
}
/**
* Summary of optionTypes
* Only used for the settings page
* @return array<array<'type'|'label'|'description'|'options', string|bool|float|int|array<string, string>>>
*/
public static function getOptionInputData()
{
return [
'category_icon' => 'fas fa-server',
'allocation_limit' => [
'label' => 'Allocation Limit',
'type' => 'number',
'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.',
],
'creation_enabled' => [
'label' => 'Creation Enabled',
'type' => 'boolean',
'description' => 'Whether or not users can create servers.',
],
'enable_upgrade' => [
'label' => 'Enable Upgrade',
'type' => 'boolean',
'description' => 'Whether or not users can upgrade their servers.',
],
'charge_first_hour' => [
'label' => 'Charge First Hour',
'type' => 'boolean',
'description' => 'Whether or not the first hour of a server is charged.',
],
];
}
}

View file

@ -1,56 +0,0 @@
<?php
namespace App\Settings;
use Spatie\LaravelSettings\Settings;
class TicketSettings extends Settings
{
public bool $enabled;
public string $notify;
public static function group(): string
{
return 'ticket';
}
/**
* Summary of validations array
* @return array<string, string>
*/
public static function getValidations()
{
return [
'enabled' => 'nullable|boolean',
'notify' => 'nullable|string',
];
}
/**
* Summary of optionTypes
* Only used for the settings page
* @return array<array<'type'|'label'|'description'|'options', string|bool|float|int|array<string, string>>>
*/
public static function getOptionInputData()
{
return [
'category_icon' => 'fas fa-ticket-alt',
'enabled' => [
'label' => 'Enabled',
'type' => 'boolean',
'description' => 'Enable or disable the ticket system.',
],
'notify' => [
'label' => 'Notify',
'type' => 'select',
'description' => 'Who will receive an E-Mail when a new Ticket is created.',
'options' => [
'admin' => 'Admins',
'moderator' => 'Moderators',
'all' => 'Admins and Moderators',
'none' => 'Nobody',
],
],
];
}
}

View file

@ -1,120 +0,0 @@
<?php
namespace App\Settings;
use Spatie\LaravelSettings\Settings;
class UserSettings extends Settings
{
public float $credits_reward_after_verify_discord;
public float $credits_reward_after_verify_email;
public bool $force_discord_verification;
public bool $force_email_verification;
public float $initial_credits;
public int $initial_server_limit;
public float $min_credits_to_make_server;
public int $server_limit_after_irl_purchase;
public int $server_limit_after_verify_discord;
public int $server_limit_after_verify_email;
public bool $register_ip_check;
public bool $creation_enabled;
public static function group(): string
{
return 'user';
}
/**
* Summary of validations array
* @return array<string, string>
*/
public static function getValidations()
{
return [
'credits_reward_after_verify_discord' => 'required|numeric',
'credits_reward_after_verify_email' => 'required|numeric',
'force_discord_verification' => 'nullable|boolean',
'force_email_verification' => 'nullable|boolean',
'initial_credits' => 'required|numeric',
'initial_server_limit' => 'required|numeric',
'min_credits_to_make_server' => 'required|numeric',
'server_limit_after_irl_purchase' => 'required|numeric',
'server_limit_after_verify_discord' => 'required|numeric',
'server_limit_after_verify_email' => 'required|numeric',
'register_ip_check' => 'nullable|boolean',
'creation_enabled' => 'nullable|boolean',
];
}
/**
* Summary of optionTypes
* Only used for the settings page
* @return array<array<'type'|'label'|'description'|'options', string|boolean|number|array<string, string>>>
*/
public static function getOptionInputData()
{
return [
'category_icon' => 'fas fa-user',
'credits_reward_after_verify_discord' => [
'label' => 'Credits Reward After Verify Discord',
'type' => 'number',
'description' => 'The amount of credits a user gets after verifying their discord account.',
],
'credits_reward_after_verify_email' => [
'label' => 'Credits Reward After Verify Email',
'type' => 'number',
'description' => 'The amount of credits a user gets after verifying their email.',
],
'force_discord_verification' => [
'label' => 'Force Discord Verification',
'type' => 'boolean',
'description' => 'Force users to verify their discord account.',
],
'force_email_verification' => [
'label' => 'Force Email Verification',
'type' => 'boolean',
'description' => 'Force users to verify their email.',
],
'initial_credits' => [
'label' => 'Initial Credits',
'type' => 'number',
'description' => 'The amount of credits a user gets when they register.',
],
'initial_server_limit' => [
'label' => 'Initial Server Limit',
'type' => 'number',
'description' => 'The amount of servers a user can create when they register.',
],
'min_credits_to_make_server' => [
'label' => 'Min Credits To Make Server',
'type' => 'number',
'description' => 'The minimum amount of credits a user needs to create a server.',
],
'server_limit_after_irl_purchase' => [
'label' => 'Server Limit After IRL Purchase',
'type' => 'number',
'description' => 'The amount of servers a user can create after they purchase a server.',
],
'server_limit_after_verify_discord' => [
'label' => 'Server Limit After Verify Discord',
'type' => 'number',
'description' => 'The amount of servers a user can create after they verify their discord account.',
],
'server_limit_after_verify_email' => [
'label' => 'Server Limit After Verify Email',
'type' => 'number',
'description' => 'The amount of servers a user can create after they verify their email.',
],
'register_ip_check' => [
'label' => 'Register IP Check',
'type' => 'boolean',
'description' => 'Check if the IP a user is registering from is already in use.',
],
'creation_enabled' => [
'label' => 'Creation Enabled',
'type' => 'boolean',
'description' => 'Whether or not users can create servers.',
],
];
}
}

View file

@ -1,103 +0,0 @@
<?php
namespace App\Settings;
use Spatie\LaravelSettings\Settings;
class WebsiteSettings extends Settings
{
public bool $show_imprint;
public bool $show_privacy;
public bool $show_tos;
public bool $useful_links_enabled;
public bool $enable_login_logo;
public ?string $seo_title;
public ?string $seo_description;
public bool $motd_enabled;
public ?string $motd_message;
public static function group(): string
{
return 'website';
}
/**
* Summary of validations array
* @return array<string, string>
*/
public static function getValidations()
{
return [
'motd_enabled' => 'nullable|boolean',
'motd_message' => 'nullable|string',
'show_imprint' => 'nullable|boolean',
'show_privacy' => 'nullable|boolean',
'show_tos' => 'nullable|boolean',
'useful_links_enabled' => 'nullable|boolean',
'enable_login_logo' => 'nullable|boolean',
'seo_title' => 'nullable|string',
'seo_description' => 'nullable|string',
];
}
/**
* Summary of optionTypes
* Only used for the settings page
* @return array<array<'type'|'label'|'description'|'options', string|array<string, string>>>
*/
public static function getOptionInputData()
{
return [
'category_icon' => 'fas fa-globe',
'motd_enabled' => [
'label' => 'Enable MOTD',
'type' => 'boolean',
'description' => 'Enable the MOTD (Message of the day) on the dashboard.',
],
'motd_message' => [
'label' => 'MOTD Message',
'type' => 'textarea',
'description' => 'The message of the day.',
],
'show_imprint' => [
'label' => 'Show Imprint',
'type' => 'boolean',
'description' => 'Show the imprint on the website.',
],
'show_privacy' => [
'label' => 'Show Privacy',
'type' => 'boolean',
'description' => 'Show the privacy on the website.',
],
'show_tos' => [
'label' => 'Show TOS',
'type' => 'boolean',
'description' => 'Show the TOS on the website.',
],
'useful_links_enabled' => [
'label' => 'Enable Useful Links',
'type' => 'boolean',
'description' => 'Enable the useful links on the dashboard.',
],
'seo_title' => [
'label' => 'SEO Title',
'type' => 'string',
'description' => 'The title of the website.',
],
'seo_description' => [
'label' => 'SEO Description',
'type' => 'string',
'description' => 'The description of the website.',
],
'enable_login_logo' => [
'label' => 'Enable Login Logo',
'type' => 'boolean',
'description' => 'Enable the logo on the login page.',
],
];
}
}

View file

@ -5,34 +5,32 @@ namespace App\Traits;
use App\Models\PartnerDiscount; use App\Models\PartnerDiscount;
use App\Models\Payment; use App\Models\Payment;
use App\Models\ShopProduct; use App\Models\ShopProduct;
use App\Models\Invoice;
use App\Notifications\InvoiceNotification; use App\Notifications\InvoiceNotification;
use App\Settings\InvoiceSettings;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
use LaravelDaily\Invoices\Classes\Buyer; use LaravelDaily\Invoices\Classes\Buyer;
use LaravelDaily\Invoices\Classes\InvoiceItem; use LaravelDaily\Invoices\Classes\InvoiceItem;
use LaravelDaily\Invoices\Classes\Party; use LaravelDaily\Invoices\Classes\Party;
use LaravelDaily\Invoices\Invoice as DailyInvoice; use LaravelDaily\Invoices\Invoice;
use Symfony\Component\Intl\Currencies; use Symfony\Component\Intl\Currencies;
trait Invoiceable trait Invoiceable
{ {
public function createInvoice(Payment $payment, ShopProduct $shopProduct, InvoiceSettings $invoice_settings) public function createInvoice(Payment $payment, ShopProduct $shopProduct)
{ {
$user = $payment->user; $user = $payment->user;
//create invoice //create invoice
$lastInvoiceID = Invoice::where("invoice_name", "like", "%" . now()->format('mY') . "%")->count("id"); $lastInvoiceID = \App\Models\Invoice::where("invoice_name", "like", "%" . now()->format('mY') . "%")->count("id");
$newInvoiceID = $lastInvoiceID + 1; $newInvoiceID = $lastInvoiceID + 1;
$logoPath = storage_path('app/public/logo.png'); $logoPath = storage_path('app/public/logo.png');
$seller = new Party([ $seller = new Party([
'name' => $invoice_settings->company_name, 'name' => config("SETTINGS::INVOICE:COMPANY_NAME"),
'phone' => $invoice_settings->company_phone, 'phone' => config("SETTINGS::INVOICE:COMPANY_PHONE"),
'address' => $invoice_settings->company_address, 'address' => config("SETTINGS::INVOICE:COMPANY_ADDRESS"),
'vat' => $invoice_settings->company_vat, 'vat' => config("SETTINGS::INVOICE:COMPANY_VAT"),
'custom_fields' => [ 'custom_fields' => [
'E-Mail' => $invoice_settings->company_mail, 'E-Mail' => config("SETTINGS::INVOICE:COMPANY_MAIL"),
"Web" => $invoice_settings->company_website "Web" => config("SETTINGS::INVOICE:COMPANY_WEBSITE")
], ],
]); ]);
@ -53,7 +51,7 @@ trait Invoiceable
$notes = implode("<br>", $notes); $notes = implode("<br>", $notes);
$invoice = DailyInvoice::make() $invoice = Invoice::make()
->template('controlpanel') ->template('controlpanel')
->name(__("Invoice")) ->name(__("Invoice"))
->buyer($customer) ->buyer($customer)
@ -66,7 +64,7 @@ trait Invoiceable
->series(now()->format('mY')) ->series(now()->format('mY'))
->delimiter("-") ->delimiter("-")
->sequence($newInvoiceID) ->sequence($newInvoiceID)
->serialNumberFormat($invoice_settings->prefix . '{DELIMITER}{SERIES}{SEQUENCE}') ->serialNumberFormat(config("SETTINGS::INVOICE:PREFIX") . '{DELIMITER}{SERIES}{SEQUENCE}')
->currencyCode(strtoupper($payment->currency_code)) ->currencyCode(strtoupper($payment->currency_code))
->currencySymbol(Currencies::getSymbol(strtoupper($payment->currency_code))) ->currencySymbol(Currencies::getSymbol(strtoupper($payment->currency_code)))
->notes($notes); ->notes($notes);
@ -80,7 +78,7 @@ trait Invoiceable
$invoice->render(); $invoice->render();
Storage::disk("local")->put("invoice/" . $user->id . "/" . now()->format('Y') . "/" . $invoice->filename, $invoice->output); Storage::disk("local")->put("invoice/" . $user->id . "/" . now()->format('Y') . "/" . $invoice->filename, $invoice->output);
Invoice::create([ \App\Models\Invoice::create([
'invoice_user' => $user->id, 'invoice_user' => $user->id,
'invoice_name' => $invoice->getSerialNumber(), 'invoice_name' => $invoice->getSerialNumber(),
'payment_id' => $payment->payment_id, 'payment_id' => $payment->payment_id,

View file

@ -11,38 +11,36 @@
"php": "^8.1", "php": "^8.1",
"ext-intl": "*", "ext-intl": "*",
"biscolab/laravel-recaptcha": "^5.4", "biscolab/laravel-recaptcha": "^5.4",
"doctrine/dbal": "^3.5.3", "doctrine/dbal": "^3.1",
"guzzlehttp/guzzle": "^7.5", "guzzlehttp/guzzle": "^7.2",
"hidehalo/nanoid-php": "^1.1.12", "hidehalo/nanoid-php": "^1.1",
"kkomelin/laravel-translatable-string-exporter": "^1.18", "kkomelin/laravel-translatable-string-exporter": "^1.18",
"laravel/framework": "^9.50.2", "laravel/framework": "^9.46",
"laravel/tinker": "^2.8", "laravel/tinker": "^2.7",
"laravel/ui": "^3.4.6", "laravel/ui": "^3.3",
"laraveldaily/laravel-invoices": "^3.0.2", "laraveldaily/laravel-invoices": "^3.0",
"league/flysystem-aws-s3-v3": "^3.12.2", "league/flysystem-aws-s3-v3": "^3.0",
"paypal/paypal-checkout-sdk": "^1.0.2", "paypal/paypal-checkout-sdk": "^1.0",
"paypal/rest-api-sdk-php": "^1.14.0", "paypal/rest-api-sdk-php": "^1.14",
"predis/predis": "*", "qirolab/laravel-themer": "^2.0",
"qirolab/laravel-themer": "^2.0.2", "socialiteproviders/discord": "^4.1",
"socialiteproviders/discord": "^4.1.2", "spatie/laravel-activitylog": "^4.4",
"spatie/laravel-activitylog": "^4.7.3", "spatie/laravel-query-builder": "^5.0",
"spatie/laravel-query-builder": "^5.1.2", "spatie/laravel-validation-rules": "^3.2",
"spatie/laravel-settings": "^2.7", "stripe/stripe-php": "^7.107",
"spatie/laravel-validation-rules": "^3.2.2", "symfony/http-client": "^6.2",
"stripe/stripe-php": "^7.128", "symfony/intl": "^6.0",
"symfony/http-client": "^6.2.6", "symfony/mailgun-mailer": "^6.2",
"symfony/intl": "^6.2.5", "yajra/laravel-datatables-oracle": "^9.19"
"symfony/mailgun-mailer": "^6.2.5",
"yajra/laravel-datatables-oracle": "^9.21.2"
}, },
"require-dev": { "require-dev": {
"barryvdh/laravel-debugbar": "^3.7", "barryvdh/laravel-debugbar": "^3.6",
"fakerphp/faker": "^1.21", "fakerphp/faker": "^1.9.1",
"laravel/sail": "^1.19", "laravel/sail": "^1.15",
"mockery/mockery": "^1.5.1", "mockery/mockery": "^1.4.4",
"nunomaduro/collision": "^6.4", "nunomaduro/collision": "^6.3",
"phpunit/phpunit": "^9.6", "phpunit/phpunit": "^9.5.10",
"spatie/laravel-ignition": "^1.6" "spatie/laravel-ignition": "^1.4"
}, },
"config": { "config": {
"optimize-autoloader": true, "optimize-autoloader": true,

1493
composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -210,8 +210,9 @@ return [
App\Providers\EventServiceProvider::class, App\Providers\EventServiceProvider::class,
App\Providers\RouteServiceProvider::class, App\Providers\RouteServiceProvider::class,
Yajra\DataTables\DataTablesServiceProvider::class, Yajra\DataTables\DataTablesServiceProvider::class,
KKomelin\TranslatableStringExporter\Providers\ExporterServiceProvider::class, KKomelin\TranslatableStringExporter\Providers\ExporterServiceProvider::class,
Biscolab\ReCaptcha\ReCaptchaServiceProvider::class,
], ],
/* /*

View file

@ -93,7 +93,7 @@ return [
'from' => [ 'from' => [
'address' => env('MAIL_FROM_ADDRESS', 'hello@example.com'), 'address' => env('MAIL_FROM_ADDRESS', 'hello@example.com'),
'name' => env('MAIL_FROM_NAME', 'ControlPanel'), 'name' => env('MAIL_FROM_NAME', 'Example'),
], ],
/* /*

View file

@ -1,111 +0,0 @@
<?php
use App\Helpers\ExtensionHelper;
use App\Settings\GeneralSettings;
use App\Settings\DiscordSettings;
use App\Settings\InvoiceSettings;
use App\Settings\LocaleSettings;
use App\Settings\MailSettings;
use App\Settings\PterodactylSettings;
use App\Settings\ReferralSettings;
use App\Settings\ServerSettings;
use App\Settings\UserSettings;
use App\Settings\WebsiteSettings;
use App\Settings\TicketSettings;
return [
/*
* Each settings class used in your application must be registered, you can
* put them (manually) here.
*/
'settings' => [
GeneralSettings::class,
DiscordSettings::class,
InvoiceSettings::class,
LocaleSettings::class,
MailSettings::class,
PterodactylSettings::class,
ReferralSettings::class,
ServerSettings::class,
UserSettings::class,
WebsiteSettings::class,
TicketSettings::class,
],
/*
* The path where the settings classes will be created.
*/
'setting_class_path' => app_path('Settings'),
/*
* In these directories settings migrations will be stored and ran when migrating. A settings
* migration created via the make:settings-migration command will be stored in the first path or
* a custom defined path when running the command.
*/
'migrations_paths' => [
database_path('settings'),
...ExtensionHelper::getAllExtensionMigrations()
],
/*
* When no repository was set for a settings class the following repository
* will be used for loading and saving settings.
*/
'default_repository' => 'database',
/*
* Settings will be stored and loaded from these repositories.
*/
'repositories' => [
'database' => [
'type' => Spatie\LaravelSettings\SettingsRepositories\DatabaseSettingsRepository::class,
'model' => null,
'table' => null,
'connection' => null,
],
'redis' => [
'type' => Spatie\LaravelSettings\SettingsRepositories\RedisSettingsRepository::class,
'connection' => null,
'prefix' => null,
],
],
/*
* The contents of settings classes can be cached through your application,
* settings will be stored within a provided Laravel store and can have an
* additional prefix.
*/
'cache' => [
'enabled' => env('SETTINGS_CACHE_ENABLED', true),
'store' => 'redis',
'prefix' => 'setting',
'ttl' => null,
],
/*
* These global casts will be automatically used whenever a property within
* your settings class isn't a default PHP type.
*/
'global_casts' => [
DateTimeInterface::class => Spatie\LaravelSettings\SettingsCasts\DateTimeInterfaceCast::class,
DateTimeZone::class => Spatie\LaravelSettings\SettingsCasts\DateTimeZoneCast::class,
// Spatie\DataTransferObject\DataTransferObject::class => Spatie\LaravelSettings\SettingsCasts\DtoCast::class,
Spatie\LaravelData\Data::class => Spatie\LaravelSettings\SettingsCasts\DataCast::class,
],
/*
* The package will look for settings in these paths and automatically
* register them.
*/
'auto_discover_settings' => [
app()->path(),
],
/*
* Automatically discovered settings classes can be cached so they don't
* need to be searched each time the application boots up.
*/
'discovered_settings_cache_path' => storage_path('app/laravel-settings'),
];

View file

@ -1,45 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
// rename old settings table
Schema::table('settings', function (Blueprint $table) {
$table->rename('settings_old');
});
// create new settings table
Schema::create('settings', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->json('payload')->nullable();
$table->string('group')->index();
$table->boolean('locked');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('settings');
Schema::table('settings_old', function (Blueprint $table) {
$table->rename("settings");
});
}
};

View file

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

View file

@ -1,32 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->string('pterodactyl_id')->change();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('users', function (Blueprint $table) {
$table->integer('pterodactyl_id')->nullable->change();
});
}
};

View file

@ -2,8 +2,8 @@
namespace Database\Seeders; namespace Database\Seeders;
use Database\Seeders\Seeds\SettingsSeeder;
use Illuminate\Database\Seeder; use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Schema;
class DatabaseSeeder extends Seeder class DatabaseSeeder extends Seeder
{ {
@ -14,6 +14,8 @@ class DatabaseSeeder extends Seeder
*/ */
public function run() public function run()
{ {
// Schema::dropIfExists('settings_old'); $this->call([
SettingsSeeder::class,
]);
} }
} }

View file

@ -0,0 +1,656 @@
<?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:INITIAL_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!',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::USER:MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER',
], [
'value' => '0',
'type' => 'integer',
'description' => 'The minimum amount of credits user has to have to create a server. Can be overridden by package limits.'
]);
//credits display name
Settings::firstOrCreate([
'key' => 'SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME',
], [
'value' => 'Credits',
'type' => 'string',
'description' => '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',
'description' => 'Enables or disables the invoice feature for payments.',
]);
//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 dashboard language.',
]);
//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' => 'en',
'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' => env('PAYPAL_SECRET', ''),
'type' => 'string',
'description' => 'Your PayPal Secret-Key (https://developer.paypal.com/docs/integration/direct/rest/).',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::PAYMENTS:PAYPAL:CLIENT_ID',
], [
'value' => env('PAYPAL_CLIENT_ID', ''),
'type' => 'string',
'description' => 'Your PayPal Client_ID.',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::PAYMENTS:PAYPAL:SANDBOX_SECRET',
], [
'value' => env('PAYPAL_SANDBOX_SECRET', ''),
'type' => 'string',
'description' => 'Your PayPal SANDBOX Secret-Key used for testing.',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::PAYMENTS:PAYPAL:SANDBOX_CLIENT_ID',
], [
'value' => env('PAYPAL_SANDBOX_CLIENT_ID', ''),
'type' => 'string',
'description' => 'Your PayPal SANDBOX Client-ID used for testing.',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::PAYMENTS:STRIPE:SECRET',
], [
'value' => env('STRIPE_SECRET', ''),
'type' => 'string',
'description' => 'Your Stripe Secret-Key (https://dashboard.stripe.com/account/apikeys).',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::PAYMENTS:STRIPE:ENDPOINT_SECRET',
], [
'value' => env('STRIPE_ENDPOINT_SECRET', ''),
'type' => 'string',
'description' => 'Your Stripe endpoint secret-key.',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::PAYMENTS:STRIPE:TEST_SECRET',
], [
'value' => env('STRIPE_TEST_SECRET', ''),
'type' => 'string',
'description' => 'Your Stripe test secret-key.',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::PAYMENTS:STRIPE:ENDPOINT_TEST_SECRET',
], [
'value' => env('STRIPE_ENDPOINT_TEST_SECRET', ''),
'type' => 'string',
'description' => 'Your Stripe endpoint test secret-key.',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::PAYMENTS:STRIPE:METHODS',
], [
'value' => env('STRIPE_METHODS', 'card,sepa_debit'),
'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' => env('DISCORD_CLIENT_ID', ''),
'type' => 'string',
'description' => 'Discord API Credentials (https://discordapp.com/developers/applications/).',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::DISCORD:CLIENT_SECRET',
], [
'value' => env('DISCORD_CLIENT_SECRET', ''),
'type' => 'string',
'description' => 'Discord API Credentials (https://discordapp.com/developers/applications/).',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::DISCORD:BOT_TOKEN',
], [
'value' => env('DISCORD_BOT_TOKEN', ''),
'type' => 'string',
'description' => 'Discord API Credentials (https://discordapp.com/developers/applications/).',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::DISCORD:GUILD_ID',
], [
'value' => env('DISCORD_GUILD_ID', ''),
'type' => 'string',
'description' => 'Discord API Credentials (https://discordapp.com/developers/applications/).',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::DISCORD:ROLE_ID',
], [
'value' => env('DISCORD_ROLE_ID', ''),
'type' => 'string',
'description' => 'Discord role that will be assigned to users when they register.',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::DISCORD:INVITE_URL',
], [
'value' => env('DISCORD_INVITE_URL', ''),
'type' => 'string',
'description' => 'The invite URL to your Discord Server.',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::SYSTEM:PTERODACTYL:TOKEN',
], [
'value' => env('PTERODACTYL_TOKEN', ''),
'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' => env('PTERODACTYL_URL', ''),
'type' => 'string',
'description' => 'The URL to your Pterodactyl Panel. Must not end with a / ',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::SYSTEM:PTERODACTYL:PER_PAGE_LIMIT',
], [
'value' => 200,
'type' => 'integer',
'description' => 'The Pterodactyl API perPage limit. It is necessary to set it higher than your server count.',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::MISC:PHPMYADMIN:URL',
], [
'value' => env('PHPMYADMIN_URL', ''),
'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' => env('RECAPTCHA_SITE_KEY', '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' => env('RECAPTCHA_SECRET_KEY', '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' => env('MAIL_MAILER', 'smtp'),
'type' => 'string',
'description' => 'Selected Mailer (smtp, mailgun, sendgrid, mailtrap).',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::MAIL:HOST',
], [
'value' => env('MAIL_HOST', 'localhost'),
'type' => 'string',
'description' => 'Mailer Host Address.',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::MAIL:PORT',
], [
'value' => env('MAIL_PORT', '25'),
'type' => 'string',
'description' => 'Mailer Server Port.',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::MAIL:USERNAME',
], [
'value' => env('MAIL_USERNAME', ''),
'type' => 'string',
'description' => 'Mailer Username.',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::MAIL:PASSWORD',
], [
'value' => env('MAIL_PASSWORD', ''),
'type' => 'string',
'description' => 'Mailer Password.',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::MAIL:ENCRYPTION',
], [
'value' => env('MAIL_ENCRYPTION', 'tls'),
'type' => 'string',
'description' => 'Mailer Encryption (tls, ssl).',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::MAIL:FROM_ADDRESS',
], [
'value' => env('MAIL_FROM_ADDRESS', ''),
'type' => 'string',
'description' => 'Mailer From Address.',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::MAIL:FROM_NAME',
], [
'value' => env('APP_NAME', 'Controlpanel'),
'type' => 'string',
'description' => 'Mailer From Name.',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::REFERRAL::ENABLED',
], [
'value' => 'false',
'type' => 'string',
'description' => 'Enable or disable the referral system.',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::REFERRAL::ALWAYS_GIVE_COMMISSION',
], [
'value' => 'false',
'type' => 'string',
'description' => 'Whether referrals get percentage commission only on first purchase or on every purchase',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::REFERRAL::REWARD',
], [
'value' => 100,
'type' => 'integer',
'description' => 'Credit reward a user should receive when a user registers with his referral code',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::REFERRAL::ALLOWED',
], [
'value' => 'client',
'type' => 'string',
'description' => 'Who should be allowed to to use the referral code. all/client',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::REFERRAL:MODE',
], [
'value' => 'sign-up',
'type' => 'string',
'description' => 'Whether referrals get Credits on User-Registration or if a User buys credits',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::REFERRAL:PERCENTAGE',
], [
'value' => 100,
'type' => 'integer',
'description' => 'The Percentage value a referred user gets.',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::SYSTEM:PTERODACTYL:ADMIN_USER_TOKEN',
], [
'value' => '',
'type' => 'string',
'description' => 'The Client API Key of an Pterodactyl Admin Account.',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::SYSTEM:ENABLE_UPGRADE',
], [
'value' => 'false',
'type' => 'boolean',
'description' => 'Enables the updgrade/downgrade feature for servers.',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::SYSTEM:CREATION_OF_NEW_SERVERS',
], [
'value' => 'true',
'type' => 'boolean',
'description' => 'Enable creation of new servers',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::SYSTEM:CREATION_OF_NEW_USERS',
], [
'value' => 'true',
'type' => 'boolean',
'description' => 'Enable creation of new users',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::SYSTEM:SHOW_IMPRINT',
], [
'value' => "false",
'type' => 'boolean',
'description' => 'Enable imprint in footer.'
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::SYSTEM:SHOW_PRIVACY',
], [
'value' => "false",
'type' => 'boolean',
'description' => 'Enable privacy policy in footer.'
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::SYSTEM:SHOW_TOS',
], [
'value' => 'false',
'type' => 'boolean',
'description' => 'Enable Terms of Service in footer.',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::SYSTEM:ALERT_ENABLED',
], [
'value' => 'false',
'type' => 'boolean',
'description' => 'Enable Alerts on Homepage.',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::SYSTEM:ALERT_TYPE',
], [
'value' => 'dark',
'type' => 'text',
'description' => 'Changes the Color of the Alert.',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::SYSTEM:ALERT_MESSAGE',
], [
'value' => '',
'type' => 'text',
'description' => 'Changes the Content the Alert.',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::SYSTEM:THEME',
], [
'value' => 'default',
'type' => 'text',
'description' => 'Current active theme.',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::SYSTEM:USEFULLINKS_ENABLED',
], [
'value' => 'true',
'type' => 'boolean',
'description' => 'Enable Useful Links on Homepage.',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::SYSTEM:MOTD_ENABLED',
], [
'value' => 'true',
'type' => 'boolean',
'description' => 'Enable MOTD on Homepage.',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::SYSTEM:MOTD_MESSAGE',
], [
'value' => '<h1 style="text-align: center;"><img style="display: block; margin-left: auto; margin-right: auto;" src="https://controlpanel.gg/img/controlpanel.png" alt="" width="200" height="200"><span style="font-size: 36pt;">Controlpanel.gg</span></h1>
<p><span style="font-size: 18pt;">Thank you for using our Software</span></p>
<p><span style="font-size: 18pt;">If you have any questions, make sure to join our <a href="https://discord.com/invite/4Y6HjD2uyU" target="_blank" rel="noopener">Discord</a></span></p>
<p><span style="font-size: 10pt;">(you can change this message in the <a href="admin/settings#system">Settings</a> )</span></p>',
'type' => 'text',
'description' => 'MOTD Message.',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::SYSTEM:SEO_TITLE',
], [
'value' => 'Controlpanel.gg',
'type' => 'text',
'description' => 'The SEO Title.',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::SYSTEM:SEO_DESCRIPTION',
], [
'value' => 'Billing software for Pterodactyl Dashboard!',
'type' => 'text',
'description' => 'SEO Description.',
]);
Settings::firstOrCreate([
'key' => 'SETTINGS::TICKET:NOTIFY',
], [
'value' => 'all',
'type' => 'text',
'description' => 'Who will get a Email Notifcation on new Tickets.',
]);
}
}

View file

@ -1,139 +0,0 @@
<?php
use Spatie\LaravelSettings\Migrations\SettingsMigration;
use Illuminate\Support\Facades\DB;
class CreateGeneralSettings extends SettingsMigration
{
public function up(): void
{
$table_exists = DB::table('settings_old')->exists();
// Get the user-set configuration values from the old table.
$this->migrator->add('general.store_enabled', true);
$this->migrator->add('general.credits_display_name', $table_exists ? $this->getOldValue('SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME') : 'Credits');
$this->migrator->addEncrypted('general.recaptcha_site_key', $table_exists ? $this->getOldValue("SETTINGS::RECAPTCHA:SITE_KEY") : env('RECAPTCHA_SITE_KEY', '6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI'));
$this->migrator->addEncrypted('general.recaptcha_secret_key', $table_exists ? $this->getOldValue("SETTINGS::RECAPTCHA:SECRET_KEY") : env('RECAPTCHA_SECRET_KEY', '6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe'));
$this->migrator->add('general.recaptcha_enabled', $table_exists ? $this->getOldValue("SETTINGS::RECAPTCHA:ENABLED") : true);
$this->migrator->add('general.phpmyadmin_url', $table_exists ? $this->getOldValue("SETTINGS::MISC:PHPMYADMIN:URL") : env('PHPMYADMIN_URL', ''));
$this->migrator->add('general.alert_enabled', $table_exists ? $this->getOldValue("SETTINGS::SYSTEM:ALERT_ENABLED") : false);
$this->migrator->add('general.alert_type', $table_exists ? $this->getOldValue("SETTINGS::SYSTEM:ALERT_TYPE") : 'dark');
$this->migrator->add('general.alert_message', $table_exists ? $this->getOldValue("SETTINGS::SYSTEM:ALERT_MESSAGE") : '');
$this->migrator->add('general.theme', $table_exists ? $this->getOldValue("SETTINGS::SYSTEM:THEME") : 'default');
}
public function down(): void
{
DB::table('settings_old')->insert([
[
'key' => 'SETTINGS::SYSTEM:CREDITS_DISPLAY_NAME',
'value' => $this->getNewValue('credits_display_name'),
'type' => 'string',
'description' => 'The name of the credits on the panel.'
],
[
'key' => 'SETTINGS::SYSTEM:ALERT_ENABLED',
'value' => $this->getNewValue('alert_enabled'),
'type' => 'boolean',
'description' => 'Enable the alert at the top of the panel.'
],
[
'key' => 'SETTINGS::SYSTEM:ALERT_TYPE',
'value' => $this->getNewValue('alert_type'),
'type' => 'string',
'description' => 'The type of alert to display.'
],
[
'key' => 'SETTINGS::SYSTEM:ALERT_MESSAGE',
'value' => $this->getNewValue('alert_message'),
'type' => 'text',
'description' => 'The message to display in the alert.'
],
[
'key' => 'SETTINGS::SYSTEM:THEME',
'value' => $this->getNewValue('theme'),
'type' => 'string',
'description' => 'The theme to use for the panel.'
],
[
'key' => 'SETTINGS::RECAPTCHA:SITE_KEY',
'value' => $this->getNewValue('recaptcha_site_key'),
'type' => 'string',
'description' => 'The site key for reCAPTCHA.'
],
[
'key' => 'SETTINGS::RECAPTCHA:SECRET_KEY',
'value' => $this->getNewValue('recaptcha_secret_key'),
'type' => 'string',
'description' => 'The secret key for reCAPTCHA.'
],
[
'key' => 'SETTINGS::RECAPTCHA:ENABLED',
'value' => $this->getNewValue('recaptcha_enabled'),
'type' => 'boolean',
'description' => 'Enable reCAPTCHA on the panel.'
],
[
'key' => 'SETTINGS::MISC:PHPMYADMIN:URL',
'value' => $this->getNewValue('phpmyadmin_url'),
'type' => 'string',
'description' => 'The URL to your phpMyAdmin installation.'
],
]);
$this->migrator->delete('general.store_enabled');
$this->migrator->delete('general.credits_display_name');
$this->migrator->delete('general.recaptcha_site_key');
$this->migrator->delete('general.recaptcha_secret_key');
$this->migrator->delete('general.recaptcha_enabled');
$this->migrator->delete('general.phpmyadmin_url');
$this->migrator->delete('general.alert_enabled');
$this->migrator->delete('general.alert_type');
$this->migrator->delete('general.alert_message');
$this->migrator->delete('general.theme');
}
public function getNewValue(string $name)
{
$new_value = DB::table('settings')->where([['group', '=', 'general'], ['name', '=', $name]])->get(['payload'])->first();
// Some keys returns '""' as a value.
if ($new_value->payload === '""') {
return null;
}
// remove the quotes from the string
if (substr($new_value->payload, 0, 1) === '"' && substr($new_value->payload, -1) === '"') {
return substr($new_value->payload, 1, -1);
}
return $new_value->payload;
}
public function getOldValue(string $key)
{
// Always get the first value of the key.
$old_value = DB::table('settings_old')->where('key', '=', $key)->get(['value', 'type'])->first();
// Handle the old values to return without it being a string in all cases.
if ($old_value->type === "string" || $old_value->type === "text") {
if (is_null($old_value->value)) {
return '';
}
// Some values have the type string, but their values are boolean.
if ($old_value->value === "false" || $old_value->value === "true") {
return filter_var($old_value->value, FILTER_VALIDATE_BOOL);
}
return $old_value->value;
}
if ($old_value->type === "boolean") {
return filter_var($old_value->value, FILTER_VALIDATE_BOOL);
}
return filter_var($old_value->value, FILTER_VALIDATE_INT);
}
}

View file

@ -1,98 +0,0 @@
<?php
use Spatie\LaravelSettings\Migrations\SettingsMigration;
use Illuminate\Support\Facades\DB;
class CreatePterodactylSettings extends SettingsMigration
{
public function up(): void
{
$table_exists = DB::table('settings_old')->exists();
// Get the user-set configuration values from the old table.
$this->migrator->addEncrypted('pterodactyl.admin_token', $table_exists ? $this->getOldValue('SETTINGS::SYSTEM:PTERODACTYL:TOKEN') : env('PTERODACTYL_TOKEN', ''));
$this->migrator->addEncrypted('pterodactyl.user_token', $table_exists ? $this->getOldValue('SETTINGS::SYSTEM:PTERODACTYL:ADMIN_USER_TOKEN') : '');
$this->migrator->add('pterodactyl.panel_url', $table_exists ? $this->getOldValue('SETTINGS::SYSTEM:PTERODACTYL:URL') : env('PTERODACTYL_URL', ''));
$this->migrator->add('pterodactyl.per_page_limit', $table_exists ? $this->getOldValue('SETTINGS::SYSTEM:PTERODACTYL:PER_PAGE_LIMIT') : 200);
}
public function down(): void
{
DB::table('settings_old')->insert([
[
'key' => 'SETTINGS::SYSTEM:PTERODACTYL:TOKEN',
'value' => $this->getNewValue('admin_token'),
'type' => 'string',
'description' => 'The admin token for the Pterodactyl panel.',
],
[
'key' => 'SETTINGS::SYSTEM:PTERODACTYL:ADMIN_USER_TOKEN',
'value' => $this->getNewValue('user_token'),
'type' => 'string',
'description' => 'The user token for the Pterodactyl panel.',
],
[
'key' => 'SETTINGS::SYSTEM:PTERODACTYL:URL',
'value' => $this->getNewValue('panel_url'),
'type' => 'string',
'description' => 'The URL for the Pterodactyl panel.',
],
[
'key' => 'SETTINGS::SYSTEM:PTERODACTYL:PER_PAGE_LIMIT',
'value' => $this->getNewValue('per_page_limit'),
'type' => 'integer',
'description' => 'The number of servers to show per page.',
],
]);
$this->migrator->delete('pterodactyl.admin_token');
$this->migrator->delete('pterodactyl.user_token');
$this->migrator->delete('pterodactyl.panel_url');
$this->migrator->delete('pterodactyl.per_page_limit');
}
public function getNewValue(string $name)
{
$new_value = DB::table('settings')->where([['group', '=', 'pterodactyl'], ['name', '=', $name]])->get(['payload'])->first();
// Some keys returns '""' as a value.
if ($new_value->payload === '""') {
return null;
}
// remove the quotes from the string
if (substr($new_value->payload, 0, 1) === '"' && substr($new_value->payload, -1) === '"') {
return substr($new_value->payload, 1, -1);
}
return $new_value->payload;
}
public function getOldValue(string $key)
{
// Always get the first value of the key.
$old_value = DB::table('settings_old')->where('key', '=', $key)->get(['value', 'type'])->first();
// Handle the old values to return without it being a string in all cases.
if ($old_value->type === "string" || $old_value->type === "text") {
if (is_null($old_value->value)) {
return '';
}
// Some values have the type string, but their values are boolean.
if ($old_value->value === "false" || $old_value->value === "true") {
return filter_var($old_value->value, FILTER_VALIDATE_BOOL);
}
return $old_value->value;
}
if ($old_value->type === "boolean") {
return filter_var($old_value->value, FILTER_VALIDATE_BOOL);
}
return filter_var($old_value->value, FILTER_VALIDATE_INT);
}
}

View file

@ -1,136 +0,0 @@
<?php
use Spatie\LaravelSettings\Migrations\SettingsMigration;
use Illuminate\Support\Facades\DB;
class CreateMailSettings extends SettingsMigration
{
public function up(): void
{
$table_exists = DB::table('settings_old')->exists();
// Get the user-set configuration values from the old table.
$this->migrator->add('mail.mail_host', $table_exists ? $this->getOldValue('SETTINGS::MAIL:HOST') : env('MAIL_HOST', 'localhost'));
$this->migrator->add('mail.mail_port', $table_exists ? $this->getOldValue('SETTINGS::MAIL:PORT') : env('MAIL_PORT', 25));
$this->migrator->add('mail.mail_username', $table_exists ? $this->getOldValue('SETTINGS::MAIL:USERNAME') : env('MAIL_USERNAME', ''));
$this->migrator->addEncrypted('mail.mail_password', $table_exists ? $this->getOldValue('SETTINGS::MAIL:PASSWORD') : env('MAIL_PASSWORD', ''));
$this->migrator->add('mail.mail_encryption', $table_exists ? $this->getOldValue('SETTINGS::MAIL:ENCRYPTION') : env('MAIL_ENCRYPTION', 'tls'));
$this->migrator->add('mail.mail_from_address', $table_exists ? $this->getOldValue('SETTINGS::MAIL:FROM_ADDRESS') : env('MAIL_FROM_ADDRESS', 'example@example.com'));
$this->migrator->add('mail.mail_from_name', $table_exists ? $this->getOldValue('SETTINGS::MAIL:FROM_NAME') : env('APP_NAME', 'ControlPanel.gg'));
$this->migrator->add('mail.mail_mailer', $table_exists ? $this->getOldValue('SETTINGS::MAIL:MAILER') : env('MAIL_MAILER', 'smtp'));
$this->migrator->add('mail.mail_enabled', true);
}
public function down(): void
{
DB::table('settings_old')->insert([
[
'key' => 'SETTINGS::MAIL:HOST',
'value' => $this->getNewValue('mail_host'),
'type' => 'string',
'description' => 'The host of the mail server.',
],
[
'key' => 'SETTINGS::MAIL:PORT',
'value' => $this->getNewValue('mail_port'),
'type' => 'integer',
'description' => 'The port of the mail server.',
],
[
'key' => 'SETTINGS::MAIL:USERNAME',
'value' => $this->getNewValue('mail_username'),
'type' => 'string',
'description' => 'The username of the mail server.',
],
[
'key' => 'SETTINGS::MAIL:PASSWORD',
'value' => $this->getNewValue('mail_password'),
'type' => 'string',
'description' => 'The password of the mail server.',
],
[
'key' => 'SETTINGS::MAIL:ENCRYPTION',
'value' => $this->getNewValue('mail_encryption'),
'type' => 'string',
'description' => 'The encryption of the mail server.',
],
[
'key' => 'SETTINGS::MAIL:FROM_ADDRESS',
'value' => $this->getNewValue('mail_from_address'),
'type' => 'string',
'description' => 'The from address of the mail server.',
],
[
'key' => 'SETTINGS::MAIL:FROM_NAME',
'value' => $this->getNewValue('mail_from_name'),
'type' => 'string',
'description' => 'The from name of the mail server.',
],
[
'key' => 'SETTINGS::MAIL:MAILER',
'value' => $this->getNewValue('mail_mailer'),
'type' => 'string',
'description' => 'The mailer of the mail server.',
],
[
'key' => 'SETTINGS::MAIL:ENABLED',
'value' => $this->getNewValue('mail_enabled'),
'type' => 'boolean',
'description' => 'The enabled state of the mail server.',
],
]);
$this->migrator->delete('mail.mail_host');
$this->migrator->delete('mail.mail_port');
$this->migrator->delete('mail.mail_username');
$this->migrator->delete('mail.mail_password');
$this->migrator->delete('mail.mail_encryption');
$this->migrator->delete('mail.mail_from_address');
$this->migrator->delete('mail.mail_from_name');
$this->migrator->delete('mail.mail_mailer');
$this->migrator->delete('mail.mail_enabled');
}
public function getNewValue(string $name)
{
$new_value = DB::table('settings')->where([['group', '=', 'mail'], ['name', '=', $name]])->get(['payload'])->first();
// Some keys returns '""' as a value.
if ($new_value->payload === '""') {
return null;
}
// remove the quotes from the string
if (substr($new_value->payload, 0, 1) === '"' && substr($new_value->payload, -1) === '"') {
return substr($new_value->payload, 1, -1);
}
return $new_value->payload;
}
public function getOldValue(string $key)
{
// Always get the first value of the key.
$old_value = DB::table('settings_old')->where('key', '=', $key)->get(['value', 'type'])->first();
// Handle the old values to return without it being a string in all cases.
if ($old_value->type === "string" || $old_value->type === "text") {
if (is_null($old_value->value)) {
return '';
}
// Some values have the type string, but their values are boolean.
if ($old_value->value === "false" || $old_value->value === "true") {
return filter_var($old_value->value, FILTER_VALIDATE_BOOL);
}
return $old_value->value;
}
if ($old_value->type === "boolean") {
return filter_var($old_value->value, FILTER_VALIDATE_BOOL);
}
return filter_var($old_value->value, FILTER_VALIDATE_INT);
}
}

View file

@ -1,163 +0,0 @@
<?php
use Spatie\LaravelSettings\Migrations\SettingsMigration;
use Illuminate\Support\Facades\DB;
class CreateUserSettings extends SettingsMigration
{
public function up(): void
{
$table_exists = DB::table('settings_old')->exists();
// Get the user-set configuration values from the old table.
$this->migrator->add('user.credits_reward_after_verify_discord', $table_exists ? $this->getOldValue('SETTINGS::USER:CREDITS_REWARD_AFTER_VERIFY_DISCORD') : 250);
$this->migrator->add('user.credits_reward_after_verify_email', $table_exists ? $this->getOldValue('SETTINGS::USER:CREDITS_REWARD_AFTER_VERIFY_EMAIL') : 250);
$this->migrator->add('user.force_discord_verification', $table_exists ? $this->getOldValue('SETTINGS::USER:FORCE_DISCORD_VERIFICATION') : false);
$this->migrator->add('user.force_email_verification', $table_exists ? $this->getOldValue('SETTINGS::USER:FORCE_EMAIL_VERIFICATION') : false);
$this->migrator->add('user.initial_credits', $table_exists ? $this->getOldValue('SETTINGS::USER:INITIAL_CREDITS') : 250);
$this->migrator->add('user.initial_server_limit', $table_exists ? $this->getOldValue('SETTINGS::USER:INITIAL_SERVER_LIMIT') : 1);
$this->migrator->add('user.min_credits_to_make_server', $table_exists ? $this->getOldValue('SETTINGS::USER:MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER') : 50);
$this->migrator->add('user.server_limit_after_irl_purchase', $table_exists ? $this->getOldValue('SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE') : 10);
$this->migrator->add('user.server_limit_after_verify_discord', $table_exists ? $this->getOldValue('SETTINGS::USER:SERVER_LIMIT_REWARD_AFTER_VERIFY_DISCORD') : 2);
$this->migrator->add('user.server_limit_after_verify_email', $table_exists ? $this->getOldValue('SETTINGS::USER:SERVER_LIMIT_REWARD_AFTER_VERIFY_EMAIL') : 2);
$this->migrator->add('user.register_ip_check', $table_exists ? $this->getOldValue("SETTINGS::SYSTEM:REGISTER_IP_CHECK") : true);
$this->migrator->add('user.creation_enabled', $table_exists ? $this->getOldValue("SETTINGS::SYSTEM:CREATION_OF_NEW_USERS") : true);
}
public function down(): void
{
DB::table('settings_old')->insert([
[
'key' => 'SETTINGS::USER:CREDITS_REWARD_AFTER_VERIFY_DISCORD',
'value' => $this->getNewValue('credits_reward_after_verify_discord'),
'type' => 'integer',
'description' => 'The amount of credits that the user will receive after verifying their Discord account.',
],
[
'key' => 'SETTINGS::USER:CREDITS_REWARD_AFTER_VERIFY_EMAIL',
'value' => $this->getNewValue('credits_reward_after_verify_email'),
'type' => 'integer',
'description' => 'The amount of credits that the user will receive after verifying their email.',
],
[
'key' => 'SETTINGS::USER:FORCE_DISCORD_VERIFICATION',
'value' => $this->getNewValue('force_discord_verification'),
'type' => 'boolean',
'description' => 'If the user must verify their Discord account to use the panel.',
],
[
'key' => 'SETTINGS::USER:FORCE_EMAIL_VERIFICATION',
'value' => $this->getNewValue('force_email_verification'),
'type' => 'boolean',
'description' => 'If the user must verify their email to use the panel.',
],
[
'key' => 'SETTINGS::USER:INITIAL_CREDITS',
'value' => $this->getNewValue('initial_credits'),
'type' => 'integer',
'description' => 'The amount of credits that the user will receive when they register.',
],
[
'key' => 'SETTINGS::USER:INITIAL_SERVER_LIMIT',
'value' => $this->getNewValue('initial_server_limit'),
'type' => 'integer',
'description' => 'The amount of servers that the user will be able to create when they register.',
],
[
'key' => 'SETTINGS::USER:MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER',
'value' => $this->getNewValue('min_credits_to_make_server'),
'type' => 'integer',
'description' => 'The minimum amount of credits that the user must have to create a server.',
],
[
'key' => 'SETTINGS::USER:SERVER_LIMIT_AFTER_IRL_PURCHASE',
'value' => $this->getNewValue('server_limit_after_irl_purchase'),
'type' => 'integer',
'description' => 'The amount of servers that the user will be able to create after making a real purchase.',
],
[
'key' => 'SETTINGS::USER:SERVER_LIMIT_REWARD_AFTER_VERIFY_DISCORD',
'value' => $this->getNewValue('server_limit_after_verify_discord'),
'type' => 'integer',
'description' => 'The amount of servers that the user will be able to create after verifying their Discord account.',
],
[
'key' => 'SETTINGS::USER:SERVER_LIMIT_REWARD_AFTER_VERIFY_EMAIL',
'value' => $this->getNewValue('server_limit_after_verify_email'),
'type' => 'integer',
'description' => 'The amount of servers that the user will be able to create after verifying their email.',
],
[
'key' => 'SETTINGS::SYSTEM:REGISTER_IP_CHECK',
'value' => $this->getNewValue('register_ip_check'),
'type' => 'boolean',
'description' => 'If the user must verify their IP address to register.',
],
[
'key' => 'SETTINGS::SYSTEM:CREATION_OF_NEW_USERS',
'value' => $this->getNewValue('creation_enabled'),
'type' => 'boolean',
'description' => 'If the user can register.',
],
]);
$this->migrator->delete('user.credits_reward_after_verify_discord');
$this->migrator->delete('user.credits_reward_after_verify_email');
$this->migrator->delete('user.force_discord_verification');
$this->migrator->delete('user.force_email_verification');
$this->migrator->delete('user.initial_credits');
$this->migrator->delete('user.initial_server_limit');
$this->migrator->delete('user.min_credits_to_make_server');
$this->migrator->delete('user.server_limit_after_irl_purchase');
$this->migrator->delete('user.server_limit_after_verify_discord');
$this->migrator->delete('user.server_limit_after_verify_email');
$this->migrator->delete('user.register_ip_check');
$this->migrator->delete('user.creation_enabled');
}
public function getNewValue(string $name)
{
$new_value = DB::table('settings')->where([['group', '=', 'user'], ['name', '=', $name]])->get(['payload'])->first();
// Some keys returns '""' as a value.
if ($new_value->payload === '""') {
return null;
}
// remove the quotes from the string
if (substr($new_value->payload, 0, 1) === '"' && substr($new_value->payload, -1) === '"') {
return substr($new_value->payload, 1, -1);
}
return $new_value->payload;
}
public function getOldValue(string $key)
{
// Always get the first value of the key.
$old_value = DB::table('settings_old')->where('key', '=', $key)->get(['value', 'type'])->first();
// Handle the old values to return without it being a string in all cases.
if ($old_value->type === "string" || $old_value->type === "text") {
if (is_null($old_value->value)) {
return '';
}
// Some values have the type string, but their values are boolean.
if ($old_value->value === "false" || $old_value->value === "true") {
return filter_var($old_value->value, FILTER_VALIDATE_BOOL);
}
return $old_value->value;
}
if ($old_value->type === "boolean") {
return filter_var($old_value->value, FILTER_VALIDATE_BOOL);
}
return filter_var($old_value->value, FILTER_VALIDATE_INT);
}
}

View file

@ -1,96 +0,0 @@
<?php
use Spatie\LaravelSettings\Migrations\SettingsMigration;
use Illuminate\Support\Facades\DB;
class CreateServerSettings extends SettingsMigration
{
public function up(): void
{
$table_exists = DB::table('settings_old')->exists();
// Get the user-set configuration values from the old table.
$this->migrator->add('server.allocation_limit', $table_exists ? $this->getOldValue('SETTINGS::SERVER:ALLOCATION_LIMIT') : 200);
$this->migrator->add('server.creation_enabled', $table_exists ? $this->getOldValue('SETTINGS::SYSTEM:CREATION_OF_NEW_SERVERS') : true);
$this->migrator->add('server.enable_upgrade', $table_exists ? $this->getOldValue('SETTINGS::SYSTEM:ENABLE_UPGRADE') : false);
$this->migrator->add('server.charge_first_hour', $table_exists ? $this->getOldValue('SETTINGS::SYSTEM:SERVER_CREATE_CHARGE_FIRST_HOUR') : false);
}
public function down(): void
{
DB::table('settings_old')->insert([
[
'key' => 'SETTINGS::SERVER:ALLOCATION_LIMIT',
'value' => $this->getNewValue('allocation_limit'),
'type' => 'integer',
'description' => 'The number of servers to show per page.',
],
[
'key' => 'SETTINGS::SYSTEM:CREATION_OF_NEW_SERVERS',
'value' => $this->getNewValue('creation_enabled'),
'type' => 'boolean',
'description' => 'Whether or not users can create new servers.',
],
[
'key' => 'SETTINGS::SYSTEM:ENABLE_UPGRADE',
'value' => $this->getNewValue('enable_upgrade'),
'type' => 'boolean',
'description' => 'Whether or not users can upgrade their servers.',
],
[
'key' => 'SETTINGS::SYSTEM:SERVER_CREATE_CHARGE_FIRST_HOUR',
'value' => $this->getNewValue('charge_first_hour'),
'type' => 'boolean',
'description' => 'Whether or not to charge the user for the first hour of their server.',
],
]);
$this->migrator->delete('server.allocation_limit');
$this->migrator->delete('server.creation_enabled');
$this->migrator->delete('server.enable_upgrade');
$this->migrator->delete('server.charge_first_hour');
}
public function getNewValue(string $name)
{
$new_value = DB::table('settings')->where([['group', '=', 'server'], ['name', '=', $name]])->get(['payload'])->first();
// Some keys returns '""' as a value.
if ($new_value->payload === '""') {
return null;
}
// remove the quotes from the string
if (substr($new_value->payload, 0, 1) === '"' && substr($new_value->payload, -1) === '"') {
return substr($new_value->payload, 1, -1);
}
return $new_value->payload;
}
public function getOldValue(string $key)
{
// Always get the first value of the key.
$old_value = DB::table('settings_old')->where('key', '=', $key)->get(['value', 'type'])->first();
// Handle the old values to return without it being a string in all cases.
if ($old_value->type === "string" || $old_value->type === "text") {
if (is_null($old_value->value)) {
return '';
}
// Some values have the type string, but their values are boolean.
if ($old_value->value === "false" || $old_value->value === "true") {
return filter_var($old_value->value, FILTER_VALIDATE_BOOL);
}
return $old_value->value;
}
if ($old_value->type === "boolean") {
return filter_var($old_value->value, FILTER_VALIDATE_BOOL);
}
return filter_var($old_value->value, FILTER_VALIDATE_INT);
}
}

View file

@ -1,128 +0,0 @@
<?php
use Spatie\LaravelSettings\Migrations\SettingsMigration;
use Illuminate\Support\Facades\DB;
class CreateInvoiceSettings extends SettingsMigration
{
public function up(): void
{
$table_exists = DB::table('settings_old')->exists();
// Get the user-set configuration values from the old table.
$this->migrator->add('invoice.company_address', $table_exists ? $this->getOldValue('SETTINGS::INVOICE:COMPANY_ADDRESS') : '');
$this->migrator->add('invoice.company_mail', $table_exists ? $this->getOldValue('SETTINGS::INVOICE:COMPANY_MAIL') : '');
$this->migrator->add('invoice.company_name', $table_exists ? $this->getOldValue('SETTINGS::INVOICE:COMPANY_NAME') : '');
$this->migrator->add('invoice.company_phone', $table_exists ? $this->getOldValue('SETTINGS::INVOICE:COMPANY_PHONE') : '');
$this->migrator->add('invoice.company_vat', $table_exists ? $this->getOldValue('SETTINGS::INVOICE:COMPANY_VAT') : '');
$this->migrator->add('invoice.company_website', $table_exists ? $this->getOldValue('SETTINGS::INVOICE:COMPANY_WEBSITE') : '');
$this->migrator->add('invoice.enabled', $table_exists ? $this->getOldValue('SETTINGS::INVOICE:ENABLED') : true);
$this->migrator->add('invoice.prefix', $table_exists ? $this->getOldValue('SETTINGS::INVOICE:PREFIX') : 'INV');
}
public function down(): void
{
DB::table('settings_old')->insert([
[
'key' => 'SETTINGS::INVOICE:COMPANY_ADDRESS',
'value' => $this->getNewValue('company_address'),
'type' => 'string',
'description' => 'The address of the company.',
],
[
'key' => 'SETTINGS::INVOICE:COMPANY_MAIL',
'value' => $this->getNewValue('company_mail'),
'type' => 'string',
'description' => 'The email address of the company.',
],
[
'key' => 'SETTINGS::INVOICE:COMPANY_NAME',
'value' => $this->getNewValue('company_name'),
'type' => 'string',
'description' => 'The name of the company.',
],
[
'key' => 'SETTINGS::INVOICE:COMPANY_PHONE',
'value' => $this->getNewValue('company_phone'),
'type' => 'string',
'description' => 'The phone number of the company.',
],
[
'key' => 'SETTINGS::INVOICE:COMPANY_VAT',
'value' => $this->getNewValue('company_vat'),
'type' => 'string',
'description' => 'The VAT number of the company.',
],
[
'key' => 'SETTINGS::INVOICE:COMPANY_WEBSITE',
'value' => $this->getNewValue('company_website'),
'type' => 'string',
'description' => 'The website of the company.',
],
[
'key' => 'SETTINGS::INVOICE:ENABLED',
'value' => $this->getNewValue('enabled'),
'type' => 'boolean',
'description' => 'Enable or disable the invoice system.',
],
[
'key' => 'SETTINGS::INVOICE:PREFIX',
'value' => $this->getNewValue('prefix'),
'type' => 'string',
'description' => 'The prefix of the invoice.',
],
]);
$this->migrator->delete('invoice.company_address');
$this->migrator->delete('invoice.company_mail');
$this->migrator->delete('invoice.company_name');
$this->migrator->delete('invoice.company_phone');
$this->migrator->delete('invoice.company_vat');
$this->migrator->delete('invoice.company_website');
$this->migrator->delete('invoice.enabled');
$this->migrator->delete('invoice.prefix');
}
public function getNewValue(string $name)
{
$new_value = DB::table('settings')->where([['group', '=', 'invoice'], ['name', '=', $name]])->get(['payload'])->first();
// Some keys returns '""' as a value.
if ($new_value->payload === '""') {
return null;
}
// remove the quotes from the string
if (substr($new_value->payload, 0, 1) === '"' && substr($new_value->payload, -1) === '"') {
return substr($new_value->payload, 1, -1);
}
return $new_value->payload;
}
public function getOldValue(string $key)
{
// Always get the first value of the key.
$old_value = DB::table('settings_old')->where('key', '=', $key)->get(['value', 'type'])->first();
// Handle the old values to return without it being a string in all cases.
if ($old_value->type === "string" || $old_value->type === "text") {
if (is_null($old_value->value)) {
return '';
}
// Some values have the type string, but their values are boolean.
if ($old_value->value === "false" || $old_value->value === "true") {
return filter_var($old_value->value, FILTER_VALIDATE_BOOL);
}
return $old_value->value;
}
if ($old_value->type === "boolean") {
return filter_var($old_value->value, FILTER_VALIDATE_BOOL);
}
return filter_var($old_value->value, FILTER_VALIDATE_INT);
}
}

View file

@ -1,113 +0,0 @@
<?php
use Spatie\LaravelSettings\Migrations\SettingsMigration;
use Illuminate\Support\Facades\DB;
class CreateDiscordSettings extends SettingsMigration
{
public function up(): void
{
$table_exists = DB::table('settings_old')->exists();
// Get the user-set configuration values from the old table.
$this->migrator->addEncrypted('discord.bot_token', $table_exists ? $this->getOldValue('SETTINGS::DISCORD:BOT_TOKEN') : '');
$this->migrator->addEncrypted('discord.client_id', $table_exists ? $this->getOldValue('SETTINGS::DISCORD:CLIENT_ID') : '');
$this->migrator->addEncrypted('discord.client_secret', $table_exists ? $this->getOldValue('SETTINGS::DISCORD:CLIENT_SECRET') : '');
$this->migrator->add('discord.guild_id', $table_exists ? $this->getOldValue('SETTINGS::DISCORD:GUILD_ID') : '');
$this->migrator->add('discord.invite_url', $table_exists ? $this->getOldValue('SETTINGS::DISCORD:INVITE_URL') : '');
$this->migrator->add('discord.role_id', $table_exists ? $this->getOldValue('SETTINGS::DISCORD:ROLE_ID') : '');
}
public function down(): void
{
DB::table('settings_old')->insert([
[
'key' => 'SETTINGS::DISCORD:BOT_TOKEN',
'value' => $this->getNewValue('bot_token'),
'type' => 'string',
'description' => 'The bot token for the Discord bot.',
],
[
'key' => 'SETTINGS::DISCORD:CLIENT_ID',
'value' => $this->getNewValue('client_id'),
'type' => 'string',
'description' => 'The client ID for the Discord bot.',
],
[
'key' => 'SETTINGS::DISCORD:CLIENT_SECRET',
'value' => $this->getNewValue('client_secret'),
'type' => 'string',
'description' => 'The client secret for the Discord bot.',
],
[
'key' => 'SETTINGS::DISCORD:GUILD_ID',
'value' => $this->getNewValue('guild_id'),
'type' => 'string',
'description' => 'The guild ID for the Discord bot.',
],
[
'key' => 'SETTINGS::DISCORD:INVITE_URL',
'value' => $this->getNewValue('invite_url'),
'type' => 'string',
'description' => 'The invite URL for the Discord bot.',
],
[
'key' => 'SETTINGS::DISCORD:ROLE_ID',
'value' => $this->getNewValue('role_id'),
'type' => 'string',
'description' => 'The role ID for the Discord bot.',
]
]);
$this->migrator->delete('discord.bot_token');
$this->migrator->delete('discord.client_id');
$this->migrator->delete('discord.client_secret');
$this->migrator->delete('discord.guild_id');
$this->migrator->delete('discord.invite_url');
$this->migrator->delete('discord.role_id');
}
public function getNewValue(string $name)
{
$new_value = DB::table('settings')->where([['group', '=', 'discord'], ['name', '=', $name]])->get(['payload'])->first();
// Some keys returns '""' as a value.
if ($new_value->payload === '""') {
return null;
}
// remove the quotes from the string
if (substr($new_value->payload, 0, 1) === '"' && substr($new_value->payload, -1) === '"') {
return substr($new_value->payload, 1, -1);
}
return $new_value->payload;
}
public function getOldValue(string $key)
{
// Always get the first value of the key.
$old_value = DB::table('settings_old')->where('key', '=', $key)->get(['value', 'type'])->first();
// Handle the old values to return without it being a string in all cases.
if ($old_value->type === "string" || $old_value->type === "text") {
if (is_null($old_value->value)) {
return '';
}
// Some values have the type string, but their values are boolean.
if ($old_value->value === "false" || $old_value->value === "true") {
return filter_var($old_value->value, FILTER_VALIDATE_BOOL);
}
return $old_value->value;
}
if ($old_value->type === "boolean") {
return filter_var($old_value->value, FILTER_VALIDATE_BOOL);
}
return filter_var($old_value->value, FILTER_VALIDATE_INT);
}
}

View file

@ -1,104 +0,0 @@
<?php
use Spatie\LaravelSettings\Migrations\SettingsMigration;
use Illuminate\Support\Facades\DB;
class CreateLocaleSettings extends SettingsMigration
{
public function up(): void
{
$table_exists = DB::table('settings_old')->exists();
// Get the user-set configuration values from the old table.
$this->migrator->add('locale.available', $table_exists ? $this->getOldValue('SETTINGS::LOCALE:AVAILABLE') : '');
$this->migrator->add('locale.clients_can_change', $table_exists ? $this->getOldValue('SETTINGS::LOCALE:CLIENTS_CAN_CHANGE') : true);
$this->migrator->add('locale.datatables', $table_exists ? $this->getOldValue('SETTINGS::LOCALE:DATATABLES') : 'en-gb');
$this->migrator->add('locale.default', $table_exists ? $this->getOldValue('SETTINGS::LOCALE:DEFAULT') : 'en');
$this->migrator->add('locale.dynamic', $table_exists ? $this->getOldValue('SETTINGS::LOCALE:DYNAMIC') : false);
}
public function down(): void
{
DB::table('settings_old')->insert([
[
'key' => 'SETTINGS::LOCALE:AVAILABLE',
'value' => $this->getNewValue('available'),
'type' => 'string',
'description' => 'The available locales.',
],
[
'key' => 'SETTINGS::LOCALE:CLIENTS_CAN_CHANGE',
'value' => $this->getNewValue('clients_can_change'),
'type' => 'boolean',
'description' => 'If clients can change their locale.',
],
[
'key' => 'SETTINGS::LOCALE:DATATABLES',
'value' => $this->getNewValue('datatables'),
'type' => 'string',
'description' => 'The locale for datatables.',
],
[
'key' => 'SETTINGS::LOCALE:DEFAULT',
'value' => $this->getNewValue('default'),
'type' => 'string',
'description' => 'The default locale.',
],
[
'key' => 'SETTINGS::LOCALE:DYNAMIC',
'value' => $this->getNewValue('dynamic'),
'type' => 'boolean',
'description' => 'If the locale should be dynamic.',
],
]);
$this->migrator->delete('locale.available');
$this->migrator->delete('locale.clients_can_change');
$this->migrator->delete('locale.datatables');
$this->migrator->delete('locale.default');
$this->migrator->delete('locale.dynamic');
}
public function getNewValue(string $name)
{
$new_value = DB::table('settings')->where([['group', '=', 'locale'], ['name', '=', $name]])->get(['payload'])->first();
// Some keys returns '""' as a value.
if ($new_value->payload === '""') {
return null;
}
// remove the quotes from the string
if (substr($new_value->payload, 0, 1) === '"' && substr($new_value->payload, -1) === '"') {
return substr($new_value->payload, 1, -1);
}
return $new_value->payload;
}
public function getOldValue(string $key)
{
// Always get the first value of the key.
$old_value = DB::table('settings_old')->where('key', '=', $key)->get(['value', 'type'])->first();
// Handle the old values to return without it being a string in all cases.
if ($old_value->type === "string" || $old_value->type === "text") {
if (is_null($old_value->value)) {
return '';
}
// Some values have the type string, but their values are boolean.
if ($old_value->value === "false" || $old_value->value === "true") {
return filter_var($old_value->value, FILTER_VALIDATE_BOOL);
}
return $old_value->value;
}
if ($old_value->type === "boolean") {
return filter_var($old_value->value, FILTER_VALIDATE_BOOL);
}
return filter_var($old_value->value, FILTER_VALIDATE_INT);
}
}

View file

@ -1,112 +0,0 @@
<?php
use Spatie\LaravelSettings\Migrations\SettingsMigration;
use Illuminate\Support\Facades\DB;
class CreateReferralSettings extends SettingsMigration
{
public function up(): void
{
$table_exists = DB::table('settings_old')->exists();
// Get the user-set configuration values from the old table.
$this->migrator->add('referral.allowed', $table_exists ? $this->getOldValue('SETTINGS::REFERRAL::ALLOWED') : 'client');
$this->migrator->add('referral.always_give_commission', $table_exists ? $this->getOldValue('SETTINGS::REFERRAL::ALWAYS_GIVE_COMMISSION') : false);
$this->migrator->add('referral.enabled', $table_exists ? $this->getOldValue('SETTINGS::REFERRAL::ENABLED') : false);
$this->migrator->add('referral.reward', $table_exists ? $this->getOldValue('SETTINGS::REFERRAL::REWARD') : 100);
$this->migrator->add('referral.mode', $table_exists ? $this->getOldValue('SETTINGS::REFERRAL:MODE') : 'sign-up');
$this->migrator->add('referral.percentage', $table_exists ? $this->getOldValue('SETTINGS::REFERRAL:PERCENTAGE') : 100);
}
public function down(): void
{
DB::table('settings_old')->insert([
[
'key' => 'SETTINGS::REFERRAL::ALLOWED',
'value' => $this->getNewValue('allowed'),
'type' => 'string',
'description' => 'The allowed referral types.',
],
[
'key' => 'SETTINGS::REFERRAL::ALWAYS_GIVE_COMMISSION',
'value' => $this->getNewValue('always_give_commission'),
'type' => 'boolean',
'description' => 'Whether to always give commission to the referrer.',
],
[
'key' => 'SETTINGS::REFERRAL::ENABLED',
'value' => $this->getNewValue('enabled'),
'type' => 'boolean',
'description' => 'Whether to enable the referral system.',
],
[
'key' => 'SETTINGS::REFERRAL::REWARD',
'value' => $this->getNewValue('reward'),
'type' => 'integer',
'description' => 'The reward for the referral.',
],
[
'key' => 'SETTINGS::REFERRAL:MODE',
'value' => $this->getNewValue('mode'),
'type' => 'string',
'description' => 'The referral mode.',
],
[
'key' => 'SETTINGS::REFERRAL:PERCENTAGE',
'value' => $this->getNewValue('percentage'),
'type' => 'integer',
'description' => 'The referral percentage.',
],
]);
$this->migrator->delete('referral.allowed');
$this->migrator->delete('referral.always_give_commission');
$this->migrator->delete('referral.enabled');
$this->migrator->delete('referral.reward');
$this->migrator->delete('referral.mode');
$this->migrator->delete('referral.percentage');
}
public function getNewValue(string $name)
{
$new_value = DB::table('settings')->where([['group', '=', 'referral'], ['name', '=', $name]])->get(['payload'])->first();
// Some keys returns '""' as a value.
if ($new_value->payload === '""') {
return null;
}
// remove the quotes from the string
if (substr($new_value->payload, 0, 1) === '"' && substr($new_value->payload, -1) === '"') {
return substr($new_value->payload, 1, -1);
}
return $new_value->payload;
}
public function getOldValue(string $key)
{
// Always get the first value of the key.
$old_value = DB::table('settings_old')->where('key', '=', $key)->get(['value', 'type'])->first();
// Handle the old values to return without it being a string in all cases.
if ($old_value->type === "string" || $old_value->type === "text") {
if (is_null($old_value->value)) {
return '';
}
// Some values have the type string, but their values are boolean.
if ($old_value->value === "false" || $old_value->value === "true") {
return filter_var($old_value->value, FILTER_VALIDATE_BOOL);
}
return $old_value->value;
}
if ($old_value->type === "boolean") {
return filter_var($old_value->value, FILTER_VALIDATE_BOOL);
}
return filter_var($old_value->value, FILTER_VALIDATE_INT);
}
}

Some files were not shown because too many files have changed in this diff Show more