Merge branch 'dev_no-encryption' into fix_extensionHelper_OS

This commit is contained in:
IceToast 2023-05-03 15:18:31 +02:00 committed by GitHub
commit d51d5c66bf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
77 changed files with 1397 additions and 16047 deletions

View file

@ -1,5 +1,5 @@
### --- App Settings --- ###
APP_NAME=Controlpanel.gg
APP_NAME=CtrlPanel.gg
APP_ENV=production
APP_KEY=
APP_DEBUG=false
@ -64,4 +64,4 @@ MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
# Settings Cache
SETTINGS_CACHE_ENABLED=true
SETTINGS_CACHE_ENABLED=true

View file

@ -5,4 +5,4 @@ contact_links:
about: Please visit our Discord for help with your installation.
- name: ❓ General Question
url: https://discord.gg/4Y6HjD2uyU
about: Please visit our Discord for general questions about the ControlPanel.
about: Please visit our Discord for general questions about the CtrlPanel.

View file

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2021 ControlPanel.gg
Copyright (c) 2021 CtrlPanel.gg
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View file

@ -17,19 +17,19 @@
- Theme Support
- and so much more!
# ControlPanel-gg
# CtrlPanel-gg
![controlpanel](https://user-images.githubusercontent.com/67899387/214684708-739c1d21-06e8-4dec-a4f1-81533a46cc7e.png)
![ctrlpanel](https://user-images.githubusercontent.com/67899387/214684708-739c1d21-06e8-4dec-a4f1-81533a46cc7e.png)
![](https://img.shields.io/endpoint?label=v0.9%20Installations&url=https%3A%2F%2Fmarket.ctrlpanel.gg%2Fcallhome.php%3Fgetinstalls)
![](https://img.shields.io/badge/Overall%20Installations-5000%2B-green)
![](https://img.shields.io/github/stars/ControlPanel-gg/dashboard) ![](https://img.shields.io/github/forks/ControlPanel-gg/dashboard) ![](https://img.shields.io/github/tag/ControlPanel-gg/dashboard) [![Crowdin](https://badges.crowdin.net/controlpanelgg/localized.svg)](https://crowdin.com/project/controlpanelgg) ![](https://img.shields.io/github/issues/ControlPanel-gg/dashboard) ![](https://img.shields.io/github/license/ControlPanel-gg/dashboard) ![](https://img.shields.io/discord/787829714483019826)
![](https://img.shields.io/github/stars/ctrlpanel-gg/dashboard) ![](https://img.shields.io/github/forks/ctrlpanel-gg/panel) ![](https://img.shields.io/github/tag/ctrlpanel-gg/panel) [![Crowdin](https://badges.crowdin.com/project/controlpanelgg/localized.svg)](https://crowdin.com/project/controlpanelgg) ![](https://img.shields.io/github/issues/ctrlpanel-gg/panel) ![](https://img.shields.io/github/license/ctrlpanel-gg/panel) ![](https://img.shields.io/discord/787829714483019826)
## About
ControlPanel's Dashboard is a dashboard application designed to offer clients a management tool to manage their pterodactyl servers. This dashboard comes with a credit-based billing solution that credits users hourly for each server they have and suspends them if they run out of credits.
CtrlPanel's Dashboard is a dashboard application designed to offer clients a management tool to manage their pterodactyl servers. This dashboard comes with a credit-based billing solution that credits users hourly for each server they have and suspends them if they run out of credits.
This dashboard offers an easy to use and free billing solution for all starting and experienced hosting providers. This dashboard has many customisation options and added discord Oauth verification to offer a solid link between your discord server and your dashboard. You can check our [Demo here](https://demo.controlpanel.gg "Demo").
This dashboard offers an easy to use and free billing solution for all starting and experienced hosting providers. This dashboard has many customisation options and added discord Oauth verification to offer a solid link between your discord server and your dashboard. You can check our [Demo here](https://demo.CtrlPanel.gg "Demo").
### [Installation](https://ctrlpanel.gg/docs/intro "Installation")

View file

@ -32,7 +32,7 @@ class GetGithubVersion extends Command
public function handle()
{
try{
$latestVersion = Http::get('https://api.github.com/repos/controlpanel-gg/dashboard/tags')->json()[0]['name'];
$latestVersion = Http::get('https://api.github.com/repos/ctrlpanel-gg/panel/tags')->json()[0]['name'];
Storage::disk('local')->put('latestVersion', $latestVersion);
} catch (Exception $e) {
Storage::disk('local')->put('latestVersion', "unknown");

View file

@ -15,12 +15,7 @@ class MollieSettings extends Settings
return 'mollie';
}
public static function encrypted(): array
{
return [
'api_key',
];
}
public static function getOptionInputData()
{

View file

@ -6,7 +6,7 @@ class CreateMollieSettings extends SettingsMigration
{
public function up(): void
{
$this->migrator->addEncrypted('mollie.api_key', null);
$this->migrator->add('mollie.api_key', null);
$this->migrator->add('mollie.enabled', false);
}

View file

@ -87,7 +87,7 @@ class PayPalExtension extends AbstractExtension
"application_context" => [
"cancel_url" => route('payment.Cancel'),
"return_url" => route('payment.PayPalSuccess', ['payment' => $payment->id]),
'brand_name' => config('app.name', 'Controlpanel.GG'),
'brand_name' => config('app.name', 'CtrlPanel.GG'),
'shipping_preference' => 'NO_SHIPPING'
]

View file

@ -18,15 +18,7 @@ class PayPalSettings extends Settings
}
public static function encrypted(): array
{
return [
'client_id',
'client_secret',
'sandbox_client_id',
'sandbox_client_secret'
];
}
/**
* Summary of optionInputData array

View file

@ -11,10 +11,10 @@ class CreatePayPalSettings extends SettingsMigration
$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.client_id', $table_exists ? $this->getOldValue('SETTINGS::PAYMENTS:PAYPAL:CLIENT_ID') : null);
$this->migrator->add('paypal.client_secret', $table_exists ? $this->getOldValue('SETTINGS::PAYMENTS:PAYPAL:SECRET') : null);
$this->migrator->add('paypal.sandbox_client_id', $table_exists ? $this->getOldValue('SETTINGS::PAYMENTS:PAYPAL:SANDBOX_CLIENT_ID') : null);
$this->migrator->add('paypal.sandbox_client_secret', $table_exists ? $this->getOldValue('SETTINGS::PAYMENTS:PAYPAL:SANDBOX_SECRET') : null);
$this->migrator->add('paypal.enabled', false);
}

View file

@ -19,15 +19,7 @@ class StripeSettings extends Settings
return 'stripe';
}
public static function encrypted(): array
{
return [
"secret_key",
"endpoint_secret",
"test_secret_key",
"test_endpoint_secret"
];
}
public static function getOptionInputData()
{

View file

@ -9,10 +9,10 @@ class CreateStripeSettings extends SettingsMigration
{
$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.secret_key', $table_exists ? $this->getOldValue('SETTINGS::PAYMENTS:STRIPE:SECRET') : null);
$this->migrator->add('stripe.endpoint_secret', $table_exists ? $this->getOldValue('SETTINGS::PAYMENTS:STRIPE:ENDPOINT_SECRET') : null);
$this->migrator->add('stripe.test_secret_key', $table_exists ? $this->getOldValue('SETTINGS::PAYMENTS:STRIPE:TEST_SECRET') : null);
$this->migrator->add('stripe.test_endpoint_secret', $table_exists ? $this->getOldValue('SETTINGS::PAYMENTS:STRIPE:ENDPOINT_TEST_SECRET') : null);
$this->migrator->add('stripe.enabled', false);
}

View file

@ -23,6 +23,7 @@ use App\Settings\LocaleSettings;
class PaymentController extends Controller
{
const BUY_PERMISSION = 'user.shop.buy';
/**
* @return Application|Factory|View
*/
@ -41,6 +42,8 @@ class PaymentController extends Controller
*/
public function checkOut(ShopProduct $shopProduct, GeneralSettings $general_settings)
{
$this->checkPermission(self::BUY_PERMISSION);
$discount = PartnerDiscount::getDiscount();
$price = $shopProduct->price - ($shopProduct->price * $discount / 100);

View file

@ -0,0 +1,195 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\User;
use Exception;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory;
use Illuminate\Contracts\View\View;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;
class RoleController extends Controller
{
/**
* Display a listing of the resource.
*
* @param Request $request
* @return mixed
* @throws Exception
*/
public function index(Request $request)
{
//datatables
if ($request->ajax()) {
return $this->dataTableQuery();
}
$html = $this->dataTable();
return view('admin.roles.index', compact('html'));
}
/**
* Show the form for creating a new resource.
*
* @return Application|Factory|View
*/
public function create()
{
$permissions = Permission::all();
return view('admin.roles.edit', compact('permissions'));
}
/**
* Store a newly created resource in storage.
*
* @return RedirectResponse
*/
public function store(Request $request): RedirectResponse
{
$role = Role::create([
'name' => $request->name,
'color' => $request->color
]);
if ($request->permissions) {
$role->givePermissionTo($request->permissions);
}
return redirect()
->route('admin.roles.index')
->with('success', __('Role saved'));
}
/**
* Display the specified resource.
*/
public function show()
{
abort(404);
}
/**
* Show the form for editing the specified resource.
*
* @param Role $role
* @return Application|Factory|View
*/
public function edit(Role $role)
{
$permissions = Permission::all();
return view('admin.roles.edit', compact('role', 'permissions'));
}
/**
* Update the specified resource in storage.
*
* @param Role $role
* @return RedirectResponse
*/
public function update(Request $request, Role $role)
{
if ($request->permissions) {
if($role->id != 1){ //disable admin permissions change
$role->syncPermissions($request->permissions);
}
}
//if($role->id == 1 || $role->id == 3 || $role->id == 4){ //dont let the user change the names of these roles
// $role->update([
// 'color' => $request->color
// ]);
//}else{
$role->update([
'name' => $request->name,
'color' => $request->color
]);
//}
//if($role->id == 1){
// return redirect()->route('admin.roles.index')->with('success', __('Role updated. Name and Permissions of this Role cannot be changed'));
//}elseif($role->id == 4 || $role->id == 3){
// return redirect()->route('admin.roles.index')->with('success', __('Role updated. Name of this Role cannot be changed'));
// }else{
return redirect()
->route('admin.roles.index')
->with('success', __('Role saved'));
//}
}
/**
* Remove the specified resource from storage.
*
* @return RedirectResponse
*/
public function destroy(Role $role)
{
if($role->id == 1 || $role->id == 3 || $role->id == 4){ //cannot delete the hard coded roles
return back()->with("error","You cannot delete that role");
}
$users = User::role($role)->get();
foreach($users as $user){
//$user->syncRoles(['Member']);
$user->syncRoles(4);
}
$role->delete();
return redirect()
->route('admin.roles.index')
->with('success', __('Role removed'));
}
/**
* @return mixed
* @throws Exception
*/
public function dataTable()
{
$query = Role::query()->withCount(['users', 'permissions']);
return datatables($query)
->editColumn('id', function (Role $role) {
return $role->id;
})
->addColumn('actions', function (Role $role) {
return '
<a title="Edit" href="'.route("admin.roles.edit", $role).'" class="btn btn-sm btn-info"><i
class="fa fas fa-edit"></i></a>
<form class="d-inline" method="post" action="'.route("admin.roles.destroy", $role).'">
' . csrf_field() . '
' . method_field("DELETE") . '
<button title="Delete" type="submit" class="btn btn-sm btn-danger confirm"><i
class="fa fas fa-trash"></i></button>
</form>
';
})
->editColumn('name', function (Role $role) {
return "<span style=\"color: $role->color\">$role->name</span>";
})
->editColumn('usercount', function ($query) {
return $query->users_count;
})
->editColumn('permissionscount', function ($query){
return $query->permissions_count;
})
->rawColumns(['actions', 'name'])
->make(true);
}
}

View file

@ -26,6 +26,7 @@ use Illuminate\Support\HtmlString;
use Illuminate\Validation\Rule;
use Illuminate\Validation\ValidationException;
use Spatie\QueryBuilder\QueryBuilder;
use Spatie\Permission\Models\Role;
class UserController extends Controller
{
@ -108,9 +109,11 @@ class UserController extends Controller
*/
public function edit(User $user, GeneralSettings $general_settings)
{
$roles = Role::all();
return view('admin.users.edit')->with([
'user' => $user,
'credits_display_name' => $general_settings->credits_display_name
'credits_display_name' => $general_settings->credits_display_name,
'roles' => $roles
]);
}
@ -135,6 +138,11 @@ class UserController extends Controller
'referral_code' => "required|string|min:2|max:32|unique:users,referral_code,{$user->id}",
]);
//update roles
if ($request->roles) {
$user->syncRoles($request->roles);
}
if (isset($this->pterodactyl->getUser($request->input('pterodactyl_id'))['errors'])) {
throw ValidationException::withMessages([
'pterodactyl_id' => [__("User does not exists on pterodactyl's panel")],
@ -166,7 +174,7 @@ class UserController extends Controller
*/
public function destroy(User $user)
{
if ($user->role === 'admin' && User::query()->where('role', 'admin')->count() === 1) {
if ($user->hasRole("Admin") && User::query()->where('role', 'admin')->count() === 1) {
return redirect()->back()->with('error', __('You can not delete the last admin!'));
}
@ -329,22 +337,13 @@ class UserController extends Controller
';
})
->editColumn('role', function (User $user) {
switch ($user->role) {
case 'admin':
$badgeColor = 'badge-danger';
break;
case 'moderator':
$badgeColor = 'badge-info';
break;
case 'client':
$badgeColor = 'badge-success';
break;
default:
$badgeColor = 'badge-secondary';
break;
$html = '';
foreach ($user->roles as $role) {
$html .= "<span style='background-color: $role->color' class='badge'>$role->name</span>";
}
return '<span class="badge ' . $badgeColor . '">' . $user->role . '</span>';
return $html;
})
->editColumn('last_seen', function (User $user) {
return $user->last_seen ? $user->last_seen->diffForHumans() : __('Never');

View file

@ -139,6 +139,8 @@ class RegisterController extends Controller
]);
$user->syncRoles(4);
$response = $this->pterodactyl->application->post('/application/users', [
'external_id' => $user->pterodactyl_id,
'username' => $user->name,

View file

@ -2,12 +2,44 @@
namespace App\Http\Controllers;
use App\Models\User;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Support\Facades\Auth;
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
/**
* Check if user has permissions
* Abort 403 if the user doesn't have the required permission
*
* @param string $permission
* @return void
*/
public function checkPermission(string $permission)
{
/** @var User $user */
$user = Auth::user();
if (!$user->can($permission)) {
abort(403, __('User does not have the right permissions.'));
}
}
/**
* Check if user has permissions
*
* @param string $permission
* @return bool
*/
public function can(string $permission): bool
{
/** @var User $user */
$user = Auth::user();
return $user->can($permission);
}
}

View file

@ -34,7 +34,7 @@ class HomeController extends Controller
if (Storage::exists('callHome')) {
return;
}
Http::asForm()->post('https://market.controlpanel.gg/callhome.php', [
Http::asForm()->post('https://market.CtrlPanel.gg/callhome.php', [
'id' => Hash::make(URL::current()),
]);
Storage::put('callHome', 'This is only used to count the installations of cpgg.');

View file

@ -26,27 +26,12 @@ class ProfileController extends Controller
/** Display a listing of the resource. */
public function index(UserSettings $user_settings, DiscordSettings $discord_settings, ReferralSettings $referral_settings)
{
switch (Auth::user()->role) {
case 'admin':
$badgeColor = 'badge-danger';
break;
case 'mod':
$badgeColor = 'badge-info';
break;
case 'client':
$badgeColor = 'badge-success';
break;
default:
$badgeColor = 'badge-secondary';
break;
}
return view('profile.index')->with([
'user' => Auth::user(),
'credits_reward_after_verify_discord' => $user_settings->credits_reward_after_verify_discord,
'force_email_verification' => $user_settings->force_email_verification,
'force_discord_verification' => $user_settings->force_discord_verification,
'badgeColor' => $badgeColor,
'discord_client_id' => $discord_settings->client_id,
'discord_client_secret' => $discord_settings->client_secret,
'referral_enabled' => $referral_settings->enabled,
@ -57,7 +42,7 @@ class ProfileController extends Controller
public function selfDestroyUser()
{
$user = Auth::user();
if ($user->role == "admin") return back()->with("error", "You cannot delete yourself as an admin!");
if ($user->hasRole("Admin")) return back()->with("error", "You cannot delete yourself as an admin!");
$user->delete();

View file

@ -15,6 +15,7 @@ use App\Settings\PterodactylSettings;
use App\Classes\PterodactylClient;
use App\Settings\GeneralSettings;
use Exception;
use GuzzleHttp\Promise\Create;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Client\Response;
use Illuminate\Http\RedirectResponse;
@ -24,6 +25,9 @@ use Illuminate\Support\Facades\Request as FacadesRequest;
class ServerController extends Controller
{
const CREATE_PERMISSION = 'user.server.create';
const UPGRADE_PERMISSION = 'user.server.upgrade';
private $pterodactyl;
public function __construct(PterodactylSettings $ptero_settings)
@ -81,6 +85,8 @@ class ServerController extends Controller
/** Show the form for creating a new resource. */
public function create(UserSettings $user_settings, ServerSettings $server_settings, GeneralSettings $general_settings)
{
$this->checkPermission(self::CREATE_PERMISSION);
$validate_configuration = $this->validateConfigurationRules($user_settings, $server_settings);
if (!is_null($validate_configuration)) {
@ -316,6 +322,8 @@ class ServerController extends Controller
public function upgrade(Server $server, Request $request)
{
$this->checkPermission(self::UPGRADE_PERMISSION);
if ($server->user_id != Auth::user()->id) {
return redirect()->route('servers.index');
}

View file

@ -21,6 +21,8 @@ use Illuminate\Support\Str;
class TicketsController extends Controller
{
const READ_PERMISSION = 'user.ticket.read';
const WRITE_PERMISSION = 'user.ticket.write';
public function index(LocaleSettings $locale_settings)
{
return view('ticket.index', [
@ -39,6 +41,7 @@ class TicketsController extends Controller
'ticketcategory' => 'required',
'priority' => 'required',
'message' => 'required',
'g-recaptcha-response' => ['required', 'recaptcha'],
]
);
$ticket = new Ticket(
@ -73,6 +76,7 @@ class TicketsController extends Controller
public function show($ticket_id, PterodactylSettings $ptero_settings)
{
$this->checkPermission(self::READ_PERMISSION);
try {
$ticket = Ticket::where('ticket_id', $ticket_id)->firstOrFail();
} catch (Exception $e) {
@ -117,6 +121,7 @@ class TicketsController extends Controller
public function create()
{
$this->checkPermission(self::WRITE_PERMISSION);
//check in blacklist
$check = TicketBlacklist::where('user_id', Auth::user()->id)->first();
if ($check && $check->status == 'True') {

View file

@ -27,6 +27,7 @@ class Kernel extends HttpKernel
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];
/**
@ -76,5 +77,9 @@ class Kernel extends HttpKernel
'moderator' => isMod::class,
'api.token' => ApiAuthToken::class,
'checkSuspended' => CheckSuspended::class,
'role' => \Spatie\Permission\Middlewares\RoleMiddleware::class,
'permission' => \Spatie\Permission\Middlewares\PermissionMiddleware::class,
'role_or_permission' => \Spatie\Permission\Middlewares\RoleOrPermissionMiddleware::class,
];
}

View file

@ -18,7 +18,8 @@ class isAdmin
*/
public function handle(Request $request, Closure $next)
{
if (Auth::user() && Auth::user()->role == 'admin') {
//if (Auth::user() && Auth::user()->hasRole("Admin")) {
if (Auth::user() && Auth::user()->hasRole(1)) {
return $next($request);
}

View file

@ -18,7 +18,7 @@ class isMod
*/
public function handle(Request $request, Closure $next)
{
if (Auth::user() && Auth::user()->role == 'moderator' || Auth::user() && Auth::user()->role == 'admin') {
if (Auth::user() && Auth::user()->role == 'moderator' || Auth::user() && Auth::user()->hasRole("Admin")) {
return $next($request);
}

View file

@ -18,13 +18,14 @@ use Illuminate\Notifications\Notifiable;
use Spatie\Activitylog\LogOptions;
use Spatie\Activitylog\Traits\CausesActivity;
use Spatie\Activitylog\Traits\LogsActivity;
use Spatie\Permission\Traits\HasRoles;
/**
* Class User
*/
class User extends Authenticatable implements MustVerifyEmail
{
use HasFactory, Notifiable, LogsActivity, CausesActivity;
use HasFactory, Notifiable, LogsActivity, CausesActivity, HasRoles;
private PterodactylClient $pterodactyl;

View file

@ -18,14 +18,7 @@ class DiscordSettings extends Settings
return 'discord';
}
public static function encrypted(): array
{
return [
'bot_token',
'client_id',
'client_secret'
];
}
/**
* Summary of validations array

View file

@ -24,13 +24,7 @@ class GeneralSettings extends Settings
return 'general';
}
public static function encrypted(): array
{
return [
'recaptcha_site_key',
'recaptcha_secret_key'
];
}
/**
* Summary of validations array

View file

@ -21,12 +21,7 @@ class MailSettings extends Settings
return 'mail';
}
public static function encrypted(): array
{
return [
'mail_password'
];
}
public function setConfig()
{

View file

@ -16,13 +16,7 @@ class PterodactylSettings extends Settings
return 'pterodactyl';
}
public static function encrypted(): array
{
return [
'admin_token',
'user_token'
];
}
/**
* Get url with ensured ending backslash

View file

@ -26,6 +26,7 @@
"qirolab/laravel-themer": "^2.0.2",
"socialiteproviders/discord": "^4.1.2",
"spatie/laravel-activitylog": "^4.7.3",
"spatie/laravel-permission": "^5.10",
"spatie/laravel-query-builder": "^5.1.2",
"spatie/laravel-settings": "^2.7",
"spatie/laravel-validation-rules": "^3.2.2",

612
composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -17,7 +17,7 @@ return [
|
*/
'name' => env('APP_NAME', 'Controlpanel.gg'),
'name' => env('APP_NAME', 'CtrlPanel.gg'),
/*
|--------------------------------------------------------------------------

View file

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

161
config/permission.php Normal file
View file

@ -0,0 +1,161 @@
<?php
return [
'models' => [
/*
* When using the "HasPermissions" trait from this package, we need to know which
* Eloquent model should be used to retrieve your permissions. Of course, it
* is often just the "Permission" model but you may use whatever you like.
*
* The model you want to use as a Permission model needs to implement the
* `Spatie\Permission\Contracts\Permission` contract.
*/
'permission' => Spatie\Permission\Models\Permission::class,
/*
* When using the "HasRoles" trait from this package, we need to know which
* Eloquent model should be used to retrieve your roles. Of course, it
* is often just the "Role" model but you may use whatever you like.
*
* The model you want to use as a Role model needs to implement the
* `Spatie\Permission\Contracts\Role` contract.
*/
'role' => Spatie\Permission\Models\Role::class,
],
'table_names' => [
/*
* When using the "HasRoles" trait from this package, we need to know which
* table should be used to retrieve your roles. We have chosen a basic
* default value but you may easily change it to any table you like.
*/
'roles' => 'roles',
/*
* When using the "HasPermissions" trait from this package, we need to know which
* table should be used to retrieve your permissions. We have chosen a basic
* default value but you may easily change it to any table you like.
*/
'permissions' => 'permissions',
/*
* When using the "HasPermissions" trait from this package, we need to know which
* table should be used to retrieve your models permissions. We have chosen a
* basic default value but you may easily change it to any table you like.
*/
'model_has_permissions' => 'model_has_permissions',
/*
* When using the "HasRoles" trait from this package, we need to know which
* table should be used to retrieve your models roles. We have chosen a
* basic default value but you may easily change it to any table you like.
*/
'model_has_roles' => 'model_has_roles',
/*
* When using the "HasRoles" trait from this package, we need to know which
* table should be used to retrieve your roles permissions. We have chosen a
* basic default value but you may easily change it to any table you like.
*/
'role_has_permissions' => 'role_has_permissions',
],
'column_names' => [
/*
* Change this if you want to name the related pivots other than defaults
*/
'role_pivot_key' => null, //default 'role_id',
'permission_pivot_key' => null, //default 'permission_id',
/*
* Change this if you want to name the related model primary key other than
* `model_id`.
*
* For example, this would be nice if your primary keys are all UUIDs. In
* that case, name this `model_uuid`.
*/
'model_morph_key' => 'model_id',
/*
* Change this if you want to use the teams feature and your related model's
* foreign key is other than `team_id`.
*/
'team_foreign_key' => 'team_id',
],
/*
* When set to true, the method for checking permissions will be registered on the gate.
* Set this to false, if you want to implement custom logic for checking permissions.
*/
'register_permission_check_method' => true,
/*
* When set to true the package implements teams using the 'team_foreign_key'. If you want
* the migrations to register the 'team_foreign_key', you must set this to true
* before doing the migration. If you already did the migration then you must make a new
* migration to also add 'team_foreign_key' to 'roles', 'model_has_roles', and
* 'model_has_permissions'(view the latest version of package's migration file)
*/
'teams' => false,
/*
* When set to true, the required permission names are added to the exception
* message. This could be considered an information leak in some contexts, so
* the default setting is false here for optimum safety.
*/
'display_permission_in_exception' => false,
/*
* When set to true, the required role names are added to the exception
* message. This could be considered an information leak in some contexts, so
* the default setting is false here for optimum safety.
*/
'display_role_in_exception' => false,
/*
* By default wildcard permission lookups are disabled.
*/
'enable_wildcard_permission' => true,
'cache' => [
/*
* By default all permissions are cached for 24 hours to speed up performance.
* When permissions or roles are updated the cache is flushed automatically.
*/
'expiration_time' => \DateInterval::createFromDateString('24 hours'),
/*
* The cache key used to store all permissions.
*/
'key' => 'spatie.permission.cache',
/*
* You may optionally indicate a specific cache driver to use for permission and
* role caching using any of the `store` drivers listed in the cache.php config
* file. Using 'default' here means to use the `default` set in cache.php.
*/
'store' => 'default',
],
];

View file

@ -0,0 +1,92 @@
<?php
return [
'*',
/*
* Permissions for admin
*/
'admin.sidebar.read',
'admin.roles.read',
'admin.roles.write',
'admin.ticket.read',
'admin.ticket_blacklist.read',
'admin.ticket_blacklist.write',
'admin.overview.read',
'admin.overview.sync',
'admin.api.read',
'admin.api.write',
'admin.users.read',
'admin.users.write',
'admin.users.suspend',
'admin.users.write.credits',
'admin.users.write.username',
'admin.users.write.password',
'admin.users.write.role',
'admin.users.write.referal',
'admin.users.write.pterodactyl',
'admin.servers.read',
'admin.servers.write',
'admin.servers.suspend',
'admin.server.write.owner',
'admin.server.write.identifier',
'admin.server.delete',
'admin.products.read',
'admin.products.create',
'admin.products.edit',
'admin.products.delete',
'admin.store.read',
'admin.store.write',
'admin.store.disable',
'admin.voucher.read',
'admin.voucher.write',
'admin.useful_links.read',
'admin.useful_links.write',
'admin.legal.read',
'admin.legal.write',
'admin.logs.read',
/*
* Permissions for settings
*/
'settings.sidebar.read',
'settings.invoices.read',
'settings.invoices.write',
'settings.language.read',
'settings.language.write',
'settings.misc.read',
'settings.misc.write',
'settings.payment.read',
'settings.payment.write',
'settings.system.read',
'settings.system.write',
/*
* Permissions for users
*/
'user.server.create',
'user.server.upgrade',
'user.shop.buy',
'user.ticket.read',
'user.ticket.write',
'user.referral',
];

View file

@ -26,7 +26,6 @@ return new class extends Migration
public function down()
{
Schema::table('users', function (Blueprint $table) {
// make the column nullable again
$table->integer('pterodactyl_id')->nullable()->change();
});
}

View file

@ -0,0 +1,142 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
use Spatie\Permission\PermissionRegistrar;
class CreatePermissionTables extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
$tableNames = config('permission.table_names');
$columnNames = config('permission.column_names');
$teams = config('permission.teams');
if (empty($tableNames)) {
throw new \Exception('Error: config/permission.php not loaded. Run [php artisan config:clear] and try again.');
}
if ($teams && empty($columnNames['team_foreign_key'] ?? null)) {
throw new \Exception('Error: team_foreign_key on config/permission.php not loaded. Run [php artisan config:clear] and try again.');
}
Schema::create($tableNames['permissions'], function (Blueprint $table) {
$table->bigIncrements('id'); // permission id
$table->string('name'); // For MySQL 8.0 use string('name', 125);
$table->string('guard_name'); // For MySQL 8.0 use string('guard_name', 125);
$table->timestamps();
$table->unique(['name', 'guard_name']);
});
Schema::create($tableNames['roles'], function (Blueprint $table) use ($teams, $columnNames) {
$table->bigIncrements('id'); // role id
if ($teams || config('permission.testing')) { // permission.testing is a fix for sqlite testing
$table->unsignedBigInteger($columnNames['team_foreign_key'])->nullable();
$table->index($columnNames['team_foreign_key'], 'roles_team_foreign_key_index');
}
$table->string('name'); // For MySQL 8.0 use string('name', 125);
$table->string('color')->nullable()->default('#485460'); // For MySQL 8.0 use string('name', 125);
$table->string('guard_name'); // For MySQL 8.0 use string('guard_name', 125);
$table->timestamps();
if ($teams || config('permission.testing')) {
$table->unique([$columnNames['team_foreign_key'], 'name', 'guard_name']);
} else {
$table->unique(['name', 'guard_name']);
}
});
Schema::create($tableNames['model_has_permissions'], function (Blueprint $table) use ($tableNames, $columnNames, $teams) {
$table->unsignedBigInteger(PermissionRegistrar::$pivotPermission);
$table->string('model_type');
$table->unsignedBigInteger($columnNames['model_morph_key']);
$table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_permissions_model_id_model_type_index');
$table->foreign(PermissionRegistrar::$pivotPermission)
->references('id') // permission id
->on($tableNames['permissions'])
->onDelete('cascade');
if ($teams) {
$table->unsignedBigInteger($columnNames['team_foreign_key']);
$table->index($columnNames['team_foreign_key'], 'model_has_permissions_team_foreign_key_index');
$table->primary([$columnNames['team_foreign_key'], PermissionRegistrar::$pivotPermission, $columnNames['model_morph_key'], 'model_type'],
'model_has_permissions_permission_model_type_primary');
} else {
$table->primary([PermissionRegistrar::$pivotPermission, $columnNames['model_morph_key'], 'model_type'],
'model_has_permissions_permission_model_type_primary');
}
});
Schema::create($tableNames['model_has_roles'], function (Blueprint $table) use ($tableNames, $columnNames, $teams) {
$table->unsignedBigInteger(PermissionRegistrar::$pivotRole);
$table->string('model_type');
$table->unsignedBigInteger($columnNames['model_morph_key']);
$table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_roles_model_id_model_type_index');
$table->foreign(PermissionRegistrar::$pivotRole)
->references('id') // role id
->on($tableNames['roles'])
->onDelete('cascade');
if ($teams) {
$table->unsignedBigInteger($columnNames['team_foreign_key']);
$table->index($columnNames['team_foreign_key'], 'model_has_roles_team_foreign_key_index');
$table->primary([$columnNames['team_foreign_key'], PermissionRegistrar::$pivotRole, $columnNames['model_morph_key'], 'model_type'],
'model_has_roles_role_model_type_primary');
} else {
$table->primary([PermissionRegistrar::$pivotRole, $columnNames['model_morph_key'], 'model_type'],
'model_has_roles_role_model_type_primary');
}
});
Schema::create($tableNames['role_has_permissions'], function (Blueprint $table) use ($tableNames) {
$table->unsignedBigInteger(PermissionRegistrar::$pivotPermission);
$table->unsignedBigInteger(PermissionRegistrar::$pivotRole);
$table->foreign(PermissionRegistrar::$pivotPermission)
->references('id') // permission id
->on($tableNames['permissions'])
->onDelete('cascade');
$table->foreign(PermissionRegistrar::$pivotRole)
->references('id') // role id
->on($tableNames['roles'])
->onDelete('cascade');
$table->primary([PermissionRegistrar::$pivotPermission, PermissionRegistrar::$pivotRole], 'role_has_permissions_permission_id_role_id_primary');
});
app('cache')
->store(config('permission.cache.store') != 'default' ? config('permission.cache.store') : null)
->forget(config('permission.cache.key'));
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
$tableNames = config('permission.table_names');
if (empty($tableNames)) {
throw new \Exception('Error: config/permission.php not found and defaults could not be merged. Please publish the package configuration before proceeding, or drop the tables manually.');
}
Schema::drop($tableNames['role_has_permissions']);
Schema::drop($tableNames['model_has_roles']);
Schema::drop($tableNames['model_has_permissions']);
Schema::drop($tableNames['roles']);
Schema::drop($tableNames['permissions']);
}
}

View file

@ -0,0 +1,79 @@
<?php
namespace Database\Seeders;
use App\Models\User;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;
class PermissionsSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
$this->createPermissions();
$this->createRoles();
$users = User::all();
foreach($users as $user){
$user->assignRole(4);
}
$admins = User::where("role","admin")->get();
foreach($admins as $admin) {
$admin->syncRoles(1);
}
$mods = User::where("role","moderator")->get();
foreach($mods as $mod) {
$mod->syncRoles(2);
}
$clients = User::where("role","client")->get();
foreach($clients as $client) {
$client->syncRoles(3);
}
}
public function createPermissions()
{
foreach (config('permissions_web') as $name) {
Permission::findOrCreate($name);
}
}
//TODO run only once
public function createRoles()
{
$userPermissions=[
'user.server.create',
'user.server.upgrade',
'user.shop.buy',
'user.ticket.read',
'user.ticket.write',
'user.referral',
];
/** @var Role $adminRole */
$adminRole = Role::updateOrCreate(["name"=>"Admin","color"=>"#fa0000"]);
$supportRole = Role::updateOrCreate(["name"=>"Support-Team","color"=>"#00b0b3"]);
$clientRole = Role::updateOrCreate(["name"=>"Client","color"=>"#008009"]);
$userRole = Role::updateOrCreate(["name"=>"User","color"=>"#0052a3"]);
$adminRole->givePermissionTo(Permission::findByName('*'));
$userRole->syncPermissions($userPermissions);
$clientRole->syncPermissions($userPermissions);
}
}

View file

@ -12,8 +12,8 @@ class CreateGeneralSettings extends SettingsMigration
// 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_site_key', $table_exists ? $this->getOldValue("SETTINGS::RECAPTCHA:SITE_KEY") : env('RECAPTCHA_SITE_KEY', '6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI'));
$this->migrator->add('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);

View file

@ -10,8 +10,8 @@ class CreatePterodactylSettings extends SettingsMigration
$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.admin_token', $table_exists ? $this->getOldValue('SETTINGS::SYSTEM:PTERODACTYL:TOKEN') : env('PTERODACTYL_TOKEN', ''));
$this->migrator->add('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);
}

View file

@ -13,10 +13,10 @@ class CreateMailSettings extends SettingsMigration
$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_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_from_name', $table_exists ? $this->getOldValue('SETTINGS::MAIL:FROM_NAME') : env('APP_NAME', 'CtrlPanel.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);
}

View file

@ -10,9 +10,9 @@ class CreateDiscordSettings extends SettingsMigration
$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.bot_token', $table_exists ? $this->getOldValue('SETTINGS::DISCORD:BOT_TOKEN') : '');
$this->migrator->add('discord.client_id', $table_exists ? $this->getOldValue('SETTINGS::DISCORD:CLIENT_ID') : '');
$this->migrator->add('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') : '');

View file

@ -14,16 +14,13 @@ class CreateWebsiteSettings extends SettingsMigration
$this->migrator->add(
'website.motd_message',
$table_exists ? $this->getOldValue("SETTINGS::SYSTEM:MOTD_MESSAGE") :
'<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>'
'<h1 style=\"text-align: center;\"><img style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"https:\/\/ctrlpanel.gg\/img\/controlpanel.png\" alt=\"\" width=\"200\" height=\"200\"><span style=\"font-size: 36pt;\">Controlpanel.gg<\/span><\/h1>\r\n<p><span style=\"font-size: 18pt;\">Thank you for using our Software<\/span><\/p>\r\n<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>\r\n<p><span style=\"font-size: 10pt;\">(you can change this message in the <a href=\"admin\/settings#system\">Settings<\/a> )<\/span><\/p>'
);
$this->migrator->add('website.show_imprint', $table_exists ? $this->getOldValue("SETTINGS::SYSTEM:SHOW_IMPRINT") : false);
$this->migrator->add('website.show_privacy', $table_exists ? $this->getOldValue("SETTINGS::SYSTEM:SHOW_PRIVACY") : false);
$this->migrator->add('website.show_tos', $table_exists ? $this->getOldValue("SETTINGS::SYSTEM:SHOW_TOS") : false);
$this->migrator->add('website.useful_links_enabled', $table_exists ? $this->getOldValue("SETTINGS::SYSTEM:USEFULLINKS_ENABLED") : true);
$this->migrator->add('website.seo_title', $table_exists ? $this->getOldValue("SETTINGS::SYSTEM:SEO_TITLE") : 'ControlPanel.gg');
$this->migrator->add('website.seo_title', $table_exists ? $this->getOldValue("SETTINGS::SYSTEM:SEO_TITLE") : 'CtrlPanel.gg');
$this->migrator->add('website.seo_description', $table_exists ? $this->getOldValue("SETTINGS::SYSTEM:SEO_DESCRIPTION") : 'Billing software for Pterodactyl Panel.');
$this->migrator->add('website.enable_login_logo', true);
}

View file

@ -126,7 +126,7 @@
"Support server": "Discord Server",
"Documentation": "Dokumentation",
"Github": "Github",
"Support ControlPanel": "Unterstütze Controlpanel.gg",
"Support ControlPanel": "Unterstütze CtrlPanel.gg",
"Servers": "Server",
"Total": "Gesamt",
"Payments": "Zahlungen",

View file

@ -177,7 +177,7 @@
"Title": "Title",
"User": "User",
"Last updated": "Last updated",
"Controlpanel.gg": "Controlpanel.gg",
"CtrlPanel.gg": "CtrlPanel.gg",
"Version": "Version",
"Individual nodes": "Individual nodes",
"You reached the Pterodactyl perPage limit. Please make sure to set it higher than your server count.": "You reached the Pterodactyl perPage limit. Please make sure to set it higher than your server count.",
@ -654,4 +654,4 @@
"sv": "Swedish",
"sk": "Slovakish",
"hu": "Hungarian"
}
}

View file

@ -1,4 +1,7 @@
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
use PHPMailer\PHPMailer\Exception;
use PHPMailer\PHPMailer\PHPMailer;
@ -32,7 +35,7 @@ if (isset($_POST['checkDB'])) {
header('LOCATION: index.php?step=2&message=' . $e->getMessage());
exit();
}
foreach ($values as $key => $value) {
$param = $_POST[$value];
@ -76,6 +79,7 @@ if (isset($_POST['feedDB'])) {
$logs .= run_console('php artisan storage:link');
$logs .= run_console('php artisan migrate --seed --force');
$logs .= run_console('php artisan db:seed --class=ExampleItemsSeeder --force');
$logs .= run_console('php artisan db:seed --class=PermissionsSeeder --force');
wh_log($logs, 'debug');
@ -131,7 +135,7 @@ if (isset($_POST['checkSMTP'])) {
'mail_host' => $_POST['host'],
'mail_port' => $_POST['port'],
'mail_username' => $_POST['user'],
'mail_password' => encryptSettingsValue($_POST['pass']),
'mail_password' => $_POST['pass'],
'mail_encryption' => $_POST['encryption'],
'mail_from_address' => $_POST['user'],
];
@ -196,8 +200,8 @@ if (isset($_POST['checkPtero'])) {
wh_log('Pterodactyl Settings are correct', 'debug');
wh_log('Updating Database', 'debug');
$key = encryptSettingsValue($key);
$clientkey = encryptSettingsValue($clientkey);
$key = $key;
$clientkey = $clientkey;
$query1 = 'UPDATE `' . getenv('DB_DATABASE') . "`.`settings` SET `payload` = '" . json_encode($url) . "' WHERE (`name` = 'panel_url' AND `group` = 'pterodactyl')";
$query2 = 'UPDATE `' . getenv('DB_DATABASE') . "`.`settings` SET `payload` = '" . json_encode($key) . "' WHERE (`name` = 'admin_token' AND `group` = 'pterodactyl')";
@ -234,10 +238,10 @@ if (isset($_POST['createUser'])) {
$repass = $_POST['repass'];
$key = $db->query('SELECT `payload` FROM `' . getenv('DB_DATABASE') . "`.`settings` WHERE `name` = 'admin_token' AND `group` = 'pterodactyl'")->fetch_assoc();
$key = encryptSettingsValue($key['value']);
$key = removeQuotes($key['payload']);
$pterobaseurl = $db->query('SELECT `payload` FROM `' . getenv('DB_DATABASE') . "`.`settings` WHERE `name` = 'panel_url' AND `group` = 'pterodactyl'")->fetch_assoc();
$pteroURL = $pterobaseurl['value'] . '/api/application/users/' . $pteroID;
$pteroURL = removeQuotes($pterobaseurl['payload']) . '/api/application/users/' . $pteroID;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $pteroURL);
@ -264,7 +268,7 @@ if (isset($_POST['createUser'])) {
$name = $result['attributes']['username'];
$pass = password_hash($pass, PASSWORD_DEFAULT);
$pteroURL = $pterobaseurl['value'] . '/api/application/users/' . $pteroID;
$pteroURL = removeQuotes($pterobaseurl['payload']) . '/api/application/users/' . $pteroID;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $pteroURL);
@ -272,7 +276,7 @@ if (isset($_POST['createUser'])) {
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Accept: application/json',
'Content-Type: application/json',
'Authorization: Bearer ' . $key['value'],
'Authorization: Bearer ' . $key,
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, [
'email' => $mail,
@ -291,13 +295,14 @@ if (isset($_POST['createUser'])) {
}
$random = generateRandomString();
$query1 = 'INSERT INTO `' . getenv('DB_DATABASE') . "`.`users` (`name`, `role`, `credits`, `server_limit`, `pterodactyl_id`, `email`, `password`, `created_at`, `referral_code`) VALUES ('$name', 'admin', '250', '1', '$pteroID', '$mail', '$pass', CURRENT_TIMESTAMP, '$random')";
if ($db->query($query1)) {
$query1 = 'INSERT INTO `' . getenv('DB_DATABASE') . "`.`users` (`name`, `role`, `credits`, `server_limit`, `pterodactyl_id`, `email`, `password`, `created_at`, `referral_code`) VALUES ('$name', 'admin', '250', '1', '$pteroID', '$mail', '$pass', CURRENT_TIMESTAMP, '$random')";
$query2 = "INSERT INTO `" . getenv('DB_DATABASE') . "`.`model_has_roles` (`role_id`, `model_type`, `model_id`) VALUES ('1', 'App\\\Models\\\User', '1')";
if ($db->query($query1) && $db->query($query2)) {
wh_log('Created user with Email ' . $mail . ' and pterodactyl ID ' . $pteroID, 'info');
header('LOCATION: index.php?step=7');
} else {
wh_log($db->error, 'error');
header('LOCATION: index.php?step=6&message=Something went wrong when communicating with the Database');
}
}
}

View file

@ -150,6 +150,10 @@ function checkExtensions(): array
return $not_ok;
}
function removeQuotes($string){
return str_replace('"', "", $string);
}
/**
* Sets the environment variable into the env file
* @param string $envKey The environment key to set or modify

View file

@ -9,7 +9,7 @@ function cardStart($title, $subtitle = null)
{
return "
<div class='flex flex-col gap-4 sm:w-auto w-full sm:min-w-[550px] my-6'>
<h1 class='text-center font-bold text-3xl'>ControlPanel.gg Installation</h1>
<h1 class='text-center font-bold text-3xl'>CtrlPanel.gg Installation</h1>
<div class='border-4 border-[#2E373B] bg-[#242A2E] rounded-2xl p-6 pt-3 mx-2'>
<h2 class='text-xl text-center mb-2'>$title</h2>"
. (isset($subtitle) ? "<p class='text-neutral-400 mb-1'>$subtitle</p>" : "");
@ -19,7 +19,7 @@ function cardStart($title, $subtitle = null)
<html>
<head>
<title>Controlpanel.gg installer Script</title>
<title>CtrlPanel.gg installer Script</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="/install/styles.css" rel="stylesheet">
@ -68,7 +68,7 @@ function cardStart($title, $subtitle = null)
// Getting started
if (!isset($_GET['step']) || $_GET['step'] == 1) {
?>
<?php echo cardStart($title = "Mandatory Checks before Installation", $subtitle = "This installer will lead you through the most crucial Steps of Controlpanel.gg's setup"); ?>
<?php echo cardStart($title = "Mandatory Checks before Installation", $subtitle = "This installer will lead you through the most crucial Steps of CtrlPanel.gg's setup"); ?>
<ul class="list-none mb-2">
@ -327,7 +327,7 @@ function cardStart($title, $subtitle = null)
<div class="flex flex-col mb-3">
<label for="url">Pterodactyl URL</label>
<input id="url" name="url" type="text" required value="https://ptero.example.com" class="px-2 py-1 bg-[#1D2125] border-2 focus:border-sky-500 box-border rounded-md border-transparent outline-none">
<input id="url" name="url" type="text" required placeholder="https://ptero.example.com" class="px-2 py-1 bg-[#1D2125] border-2 focus:border-sky-500 box-border rounded-md border-transparent outline-none">
</div>
</div>
<div class="form-group">

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

File diff suppressed because one or more lines are too long

View file

@ -13,6 +13,7 @@ use App\Http\Controllers\Admin\OverViewController;
use App\Http\Controllers\Admin\PartnerController;
use App\Http\Controllers\Admin\PaymentController;
use App\Http\Controllers\Admin\ProductController;
use App\Http\Controllers\Admin\RoleController;
use App\Http\Controllers\Admin\ServerController as AdminServerController;
use App\Http\Controllers\Admin\SettingsController;
use App\Http\Controllers\Admin\ShopProductController;
@ -117,7 +118,9 @@ Route::middleware(['auth', 'checkSuspended'])->group(function () {
//admin
Route::prefix('admin')->name('admin.')->middleware('admin')->group(function () {
//Roles
Route::get('roles/datatable', [RoleController::class, 'datatable'])->name('roles.datatable');
Route::resource('roles', RoleController::class);
//overview
Route::get('legal', [OverViewController::class, 'index'])->name('overview.index');

View file

@ -199,7 +199,7 @@
src="{{ \Illuminate\Support\Facades\Storage::disk('public')->exists('icon.png') ? asset('storage/icon.png') : asset('images/controlpanel_logo.png') }}"
alt="{{ config('app.name', 'Laravel') }} Logo" class="brand-image img-circle"
style="opacity: .8">
<span class="brand-text font-weight-light">{{ config('app.name', 'Controlpanel.gg') }}</span>
<span class="brand-text font-weight-light">{{ config('app.name', 'CtrlPanel.gg') }}</span>
</a>
<!-- Sidebar -->
@ -253,7 +253,7 @@
</li>
@endif
@if ((Auth::user()->role == 'admin' || Auth::user()->role == 'moderator') && config('SETTINGS::TICKET:ENABLED'))
@if ((Auth::user()->hasRole("Admin") || Auth::user()->role == 'moderator') && config('SETTINGS::TICKET:ENABLED'))
<li class="nav-header">{{ __('Moderation') }}</li>
<li class="nav-item">
@ -272,7 +272,7 @@
</li>
@endif
@if (Auth::user()->role == 'admin')
@if (Auth::user()->hasRole("Admin"))
<li class="nav-header">{{ __('Administration') }}</li>
<li class="nav-item">
@ -441,7 +441,7 @@
<strong>Copyright &copy; 2021-{{ date('Y') }} <a
href="{{ url('/') }}">{{ env('APP_NAME', 'Laravel') }}</a>.</strong>
All rights
reserved. Powered by <a href="https://controlpanel.gg">ControlPanel</a>. | Theme by <a href="https://2icecube.de/cpgg">2IceCube</a>
reserved. Powered by <a href="https://CtrlPanel.gg">ControlPanel</a>. | Theme by <a href="https://2icecube.de/cpgg">2IceCube</a>
@if (!str_contains(config('BRANCHNAME'), 'main') && !str_contains(config('BRANCHNAME'), 'unknown'))
Version <b>{{ config('app')['version'] }} - {{ config('BRANCHNAME') }}</b>
@endif

View file

@ -33,7 +33,7 @@
@else
<div class="callout callout-danger">
<h4>{{ __('No recent activity from cronjobs')}}</h4>
<p>{{ __('Are cronjobs running?')}} <a class="text-primary" target="_blank" href="https://controlpanel.gg/docs/Installation/getting-started#crontab-configuration">{{ __('Check the docs for it here')}}</a></p>
<p>{{ __('Are cronjobs running?')}} <a class="text-primary" target="_blank" href="https://CtrlPanel.gg/docs/Installation/getting-started#crontab-configuration">{{ __('Check the docs for it here')}}</a></p>
</div>
@endif

View file

@ -23,7 +23,7 @@
<b><i class="fas fa-shield-alt"></i> {{__("Version Outdated:")}}</b></br>
{{__("You are running on")}} v{{config("app.version")}}-{{config("BRANCHNAME")}}.
{{__("The latest Version is")}} v{{Storage::get('latestVersion')}}</br>
<a href="https://controlpanel.gg/docs/Installation/updating">{{__("Consider updating now")}}</a>
<a href="https://CtrlPanel.gg/docs/Installation/updating">{{__("Consider updating now")}}</a>
</div>
@endif
</section>
@ -39,7 +39,7 @@
class="fab fa-discord mr-2"></i> {{__('Support server')}}</a>
</div>
<div class="col-md-3">
<a href="https://controlpanel.gg/docs/intro" class="btn btn-dark btn-block px-3"><i
<a href="https://CtrlPanel.gg/docs/intro" class="btn btn-dark btn-block px-3"><i
class="fas fa-link mr-2"></i> {{__('Documentation')}}</a>
</div>
<div class="col-md-3">
@ -47,8 +47,8 @@
class="fab fa-github mr-2"></i> {{__('Github')}}</a>
</div>
<div class="col-md-3">
<a href="https://controlpanel.gg/docs/Contributing/donating" class="btn btn-dark btn-block px-3"><i
class="fas fa-money-bill mr-2"></i> {{__('Support ControlPanel')}}</a>
<a href="https://CtrlPanel.gg/docs/Contributing/donating" class="btn btn-dark btn-block px-3"><i
class="fas fa-money-bill mr-2"></i> {{__('Support CtrlPanel')}}</a>
</div>
</div>
@ -199,7 +199,7 @@
<div class="card-header">
<div class="d-flex justify-content-between">
<div class="card-title ">
<span><i class="fas fa-server mr-2"></i>{{__('Controlpanel.gg')}}</span>
<span><i class="fas fa-server mr-2"></i>{{__('CtrlPanel.gg')}}</span>
</div>
</div>
<div class="card-body py-1">
@ -227,7 +227,7 @@
<p class="mb-2">
{{ __('You reached the Pterodactyl perPage limit. Please make sure to set it higher than your server count.') }}<br>
{{ __('You can do that in settings.') }}<br><br>
{{ __('Note') }}: {{ __('If this error persists even after changing the limit, it might mean a server was deleted on Pterodactyl, but not on ControlPanel. Try clicking the button below.') }}
{{ __('Note') }}: {{ __('If this error persists even after changing the limit, it might mean a server was deleted on Pterodactyl, but not on CtrlPanel. Try clicking the button below.') }}
</p>
<a href="{{route('admin.servers.sync')}}" class="btn btn-primary btn-md"><i
class="fas fa-sync mr-2"></i>{{__('Sync servers')}}</a>

View file

@ -0,0 +1,54 @@
@extends('layouts.main')
@section('content')
<div class="main py-4">
<div class="card card-body border-0 shadow table-wrapper table-responsive">
<h2 class="mb-4 h5">{{ isset($role) ? __('Edit role') : __('Create role') }}</h2>
<form method="post"
action="{{isset($role) ? route('admin.roles.update', $role->id) : route('admin.roles.store')}}">
@csrf
@isset($role)
@method('PATCH')
@endisset
<div class="row">
<div class="col-lg-6">
<x-input.text label="{{(__('Name'))}}"
name="name"
value="{{ isset($role) ? $role->name : null}}"/>
<x-input.text label="{{(__('Badge color'))}}"
type="color"
name="color"
value="{{ isset($role) ? $role->color : null}}"/>
</div>
<div class="col-lg-6">
<x-input.select
label="{{(__('Permissions'))}}"
name="permissions"
style="height: 200px"
multiple>
@foreach($permissions as $permission)
<option @if(isset($role) && $role->permissions->contains($permission)) selected
@endif value="{{$permission->id}}">{{$permission->name}}</option>
@endforeach
</x-input.select>
</div>
</div>
<div class="form-group d-flex justify-content-end mt-3">
<button name="submit" type="submit" class="btn btn-primary">{{__('Submit')}}</button>
</div>
</form>
</div>
</div>
@endsection

View file

@ -0,0 +1,60 @@
@extends('layouts.main')
@section('content')
<div class="main py-4">
@can('admin.roles.write')
<div class="d-flex justify-content-end my-3">
<a href="{{route('admin.roles.create')}}" class="btn btn-primary"><i
class="fa fas fa-shield-alt pe-2"></i>{{__('Create role')}}</a>
</div>
@endcan
<div class="card card-body border-0 shadow table-wrapper table-responsive">
<h2 class="mb-4 h5">{{ __('Roles') }}</h2>
<div class="card-body table-responsive">
<table id="datatable" class="table table-striped">
<thead>
<tr>
<th>{{__("ID")}}</th>
<th>{{__("Name")}}</th>
<th>{{__("User count")}}</th>
<th>{{__("Permissions count")}}</th>
<th>{{__("Actions")}}</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
</div>
@endsection
<script>
document.addEventListener("DOMContentLoaded", function () {
$('#datatable').DataTable({
language: {
url: '//cdn.datatables.net/plug-ins/1.11.3/i18n/{{config("SETTINGS::LOCALE:DATATABLES")}}.json'
},
processing: true,
serverSide: true, //increases loading times too much? change back to "true" if it does
stateSave: true,
ajax: "{{route('admin.roles.datatable')}}",
columns: [
{data: 'id'},
{data: 'name'},
{data: 'usercount'},
{data: 'permissionscount'},
{data: 'actions' , sortable : false},
],
fnDrawCallback: function( oSettings ) {
$('[data-toggle="popover"]').popover();
}
});
});
</script>

View file

@ -43,7 +43,7 @@
<div class="form-group">
<label for="identifier">{{ __('Server identifier') }}
<i data-toggle="popover" data-trigger="hover"
data-content="{{ __('Change the server identifier on controlpanel to match a pterodactyl server.') }}"
data-content="{{ __('Change the server identifier on CtrlPanel to match a pterodactyl server.') }}"
class="fas fa-info-circle"></i>
</label>
<input value="{{ $server->identifier }}" id="identifier" name="identifier"
@ -59,7 +59,7 @@
<div class="form-group">
<label for="user_id">{{ __('Server owner') }}
<i data-toggle="popover" data-trigger="hover"
data-content="{{ __('Change the current server owner on controlpanel and pterodactyl.') }}"
data-content="{{ __('Change the current server owner on CtrlPanel and pterodactyl.') }}"
class="fas fa-info-circle"></i>
</label>
<select name="user_id" id="user_id" class="form-control">

View file

@ -159,6 +159,32 @@
</div>
</div>
@endforeach
<!-- TODO: Display this only on the General tab
<div class="row">
<div class="col-4 d-flex align-items-center">
<label for="recaptcha_preview">{{__("ReCAPTCHA Preview")}}</label>
</div>
<div class="col-8">
<div class="w-100">
<div class="input-group mb-3">
{!! htmlScriptTagJsApi() !!}
{!! htmlFormSnippet() !!}
@error('g-recaptcha-response')
<span class="text-danger" role="alert">
<small><strong>{{ $message }}</strong></small>
</span>
@enderror
</div>
</div>
</div>
</div>
-->
<div class="row">
<div class="col-12 d-flex align-items-center justify-content-end">
<button type="submit"

View file

@ -97,25 +97,15 @@
<div class="form-group">
<label for="role">{{__('Role')}}</label>
<div>
<select id="role" name="role"
<select id="roles" name="roles"
class="custom-select @error('role') is-invalid @enderror"
required="required">
<option @if($user->role == 'admin') selected @endif class="text-danger"
value="admin">
{{__(' Administrator')}}
</option>
<option @if($user->role == 'moderator') selected @endif class="text-info" value="moderator">
{{__('Moderator')}}
</option>
<option @if($user->role == 'client') selected @endif class="text-success"
value="client">
{{__('Client')}}
</option>
<option @if($user->role == 'member') selected @endif class="text-secondary"
value="member">
{{__('Member')}}
</option>
</select>
@foreach($roles as $role)
<option style="color: {{$role->color}}"
@if(isset($user) && $user->roles->contains($role)) selected
@endif value="{{$role->id}}">{{$role->name}}</option>
@endforeach
</select>
</div>
</div>
<div class="form-group">

View file

@ -76,7 +76,7 @@
<div class="col-lg-8">
<span style="max-width: 250px;"
class="d-inline-block text-truncate badge
@if ($user->role == 'admin') badge-danger
@if ($user->hasRole("Admin")) badge-danger
@elseif ($user->role == 'moderator')
badge-info
@elseif ($user->role == 'client')

View file

@ -9,9 +9,9 @@
<div class="card-header text-center">
<a href="{{ route('welcome') }}" class="h1 mb-2"><b
class="mr-1">{{ config('app.name', 'Laravel') }}</b></a>
@if ($website_settings->enable_login_logo)
@if ($website_settings->enable_login_logo)
<img src="{{ \Illuminate\Support\Facades\Storage::disk('public')->exists('logo.png') ? asset('storage/logo.png') : asset('images/controlpanel_logo.png') }}"
alt="{{ config('app.name', 'Controlpanel.gg') }} Logo" style="opacity: .8; max-width:100%; height: 150px; margin-top: 10px;">
alt="{{ config('app.name', 'CtrlPanel.gg') }} Logo" style="opacity: .8; max-width:100%; height: 150px; margin-top: 10px;">
@endif
</div>
<div class="card-body pt-0">

View file

@ -18,7 +18,7 @@
</section>
<!-- END CONTENT HEADER -->
@if (!file_exists(base_path() . '/install.lock') && Auth::User()->role == 'admin')
@if (!file_exists(base_path() . '/install.lock') && Auth::User()->hasRole("Admin"))
<div class="callout callout-danger">
<h4>{{ __('The installer is not locked!') }}</h4>
<p>{{ __('please create a file called "install.lock" in your dashboard Root directory. Otherwise no settings will be loaded!') }}
@ -135,12 +135,12 @@
</div>
<!-- /.card-header -->
<div class="card-body">
@foreach ($useful_links as $useful_link)
@foreach ($useful_links_dashboard as $useful_link)
<div class="alert alert-dismissible">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<h5>
<a class="alert-link text-decoration-none" target="__blank"
href="{{ $useful_link->link }}">
href="{{ $useful_link->link }}">
<i class="{{ $useful_link->icon }} mr-2"></i>{{ $useful_link->title }}
</a>
</h5>
@ -150,22 +150,7 @@
</div>
<!-- /.card-body -->
</div>
<!-- /.card-header -->
<div class="card-body">
@foreach ($useful_links_dashboard as $useful_link)
<div class="alert alert-dismissible">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<h5>
<a class="alert-link text-decoration-none" target="__blank"
href="{{ $useful_link->link }}">
<i class="{{ $useful_link->icon }} mr-2"></i>{{ $useful_link->title }}
</a>
</h5>
{!! $useful_link->description !!}
</div>
@endforeach
</div>
<!-- /.card-body -->
</div>
@endif

View file

@ -18,7 +18,7 @@
</li>
<li>
<p><strong>Company</strong> (referred to as either &quot;the Company&quot;, &quot;We&quot;, &quot;Us&quot; or
&quot;Our&quot; in this Agreement) refers to controlpanel.</p>
&quot;Our&quot; in this Agreement) refers to CtrlPanel.</p>
</li>
<li>
<p><strong>Cookies</strong> are small files that are placed on Your computer, mobile device or any other device
@ -49,7 +49,7 @@
Service or from the Service infrastructure itself (for example, the duration of a page visit).</p>
</li>
<li>
<p><strong>Website</strong> refers to controlpanel, accessible from <a href="controlpanel"
<p><strong>Website</strong> refers to CtrlPanel, accessible from <a href="controlpanel"
rel="external nofollow noopener" target="_blank">controlpanel</a></p>
</li>
<li>

View file

@ -18,10 +18,10 @@
href="{{ \Illuminate\Support\Facades\Storage::disk('public')->exists('favicon.ico') ? asset('storage/favicon.ico') : asset('favicon.ico') }}"
type="image/x-icon">
<script defer src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"></script>
<script src="{{ asset('plugins/alpinejs/3.12.0_cdn.min.js') }}"></script>
{{-- <link rel="stylesheet" href="{{asset('css/adminlte.min.css')}}"> --}}
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/bs4/dt-1.10.24/datatables.min.css" />
<link rel="stylesheet" href="{{ asset('plugins/datatables/jquery.dataTables.min.css') }}">
{{-- summernote --}}
<link rel="stylesheet" href="{{ asset('plugins/summernote/summernote-bs4.min.css') }}">
@ -204,7 +204,7 @@
src="{{ \Illuminate\Support\Facades\Storage::disk('public')->exists('icon.png') ? asset('storage/icon.png') : asset('images/controlpanel_logo.png') }}"
alt="{{ config('app.name', 'Laravel') }} Logo" class="brand-image img-circle"
style="opacity: .8">
<span class="brand-text font-weight-light">{{ config('app.name', 'Controlpanel.gg') }}</span>
<span class="brand-text font-weight-light">{{ config('app.name', 'CtrlPanel.gg') }}</span>
</a>
<!-- Sidebar -->
@ -246,6 +246,7 @@
@endif
@php($ticket_enabled = app(App\Settings\TicketSettings::class)->enabled)
@if ($ticket_enabled)
@canany(["user.ticket.read", "user.ticket.write"])
<li class="nav-item">
<a href="{{ route('ticket.index') }}"
class="nav-link @if (Request::routeIs('ticket.*')) active @endif">
@ -253,9 +254,10 @@
<p>{{ __('Support Ticket') }}</p>
</a>
</li>
@endcanany
@endif
@if ((Auth::user()->role == 'admin' || Auth::user()->role == 'moderator') && $ticket_enabled)
@if ((Auth::user()->hasRole(1) || Auth::user()->role == 'moderator') && $ticket_enabled)
<li class="nav-header">{{ __('Moderation') }}</li>
<li class="nav-item">
@ -274,7 +276,7 @@
</li>
@endif
@if (Auth::user()->role == 'admin')
@if (Auth::user()->hasRole(1))
<li class="nav-header">{{ __('Administration') }}</li>
<li class="nav-item">
@ -285,6 +287,13 @@
</a>
</li>
<li class="nav-item">
<a href="{{ route('admin.roles.index') }}"
class="nav-link @if (Request::routeIs('admin.roles.*')) active @endif">
<i class="nav-icon fa fa-user-check"></i>
<p>{{ __('Role Management') }}</p>
</a>
</li>
<li class="nav-item">
<a href="{{ route('admin.settings.index') }}"
@ -443,7 +452,7 @@
<strong>Copyright &copy; 2021-{{ date('Y') }} <a
href="{{ url('/') }}">{{ env('APP_NAME', 'Laravel') }}</a>.</strong>
All rights
reserved. Powered by <a href="https://controlpanel.gg">ControlPanel</a>.
reserved. Powered by <a href="https://CtrlPanel.gg">CtrlPanel</a>.
@if (!str_contains(config('BRANCHNAME'), 'main') && !str_contains(config('BRANCHNAME'), 'unknown'))
Version <b>{{ config('app')['version'] }} - {{ config('BRANCHNAME') }}</b>
@endif
@ -472,9 +481,9 @@
<!-- ./wrapper -->
<!-- Scripts -->
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@10.14.1/dist/sweetalert2.all.min.js"></script>
<script src="{{ asset('plugins/sweetalert2/sweetalert2.all.min.js') }}"></script>
<script type="text/javascript" src="https://cdn.datatables.net/v/bs4/dt-1.10.24/datatables.min.js"></script>
<script src="{{ asset('plugins/datatables/jquery.dataTables.min.js') }}"></script>
<!-- Summernote -->
<script src="{{ asset('plugins/summernote/summernote-bs4.min.js') }}"></script>
<!-- select2 -->

View file

@ -118,7 +118,7 @@
<span class="badge badge-success"> Client </span>
@elseif ($ticket->user->role === "moderator")
<span class="badge badge-info"> Moderator </span>
@elseif ($ticket->user->role === "admin")
@elseif ($ticket->user->hasRole("Admin"))
<span class="badge badge-danger"> Admin </span>
@endif
</h5>
@ -141,7 +141,7 @@
<span class="badge badge-success"> Client </span>
@elseif ($ticketcomment->user->role === "moderator")
<span class="badge badge-info"> Moderator </span>
@elseif ($ticketcomment->user->role === "admin")
@elseif ($ticketcomment->user->hasRole("Admin"))
<span class="badge badge-danger"> Admin </span>
@endif
</h5>

View file

@ -101,7 +101,7 @@
</div>
@if($referral_enabled)
@if(($referral_allowed === "client" && $user->role != "member") || $referral_allowed === "everyone")
@can("user.referral")
<div class="mt-1">
<span class="badge badge-success"><i
class="fa fa-user-check mr-2"></i>
@ -112,14 +112,16 @@
@else
<span class="badge badge-warning"><i
class="fa fa-user-check mr-2"></i>
{{_("Make a purchase to reveal your referral-URL")}}</span>
@endif
{{_("You can not see your Referral Code")}}</span>
@endcan
</div>
@endif
</div>
<div class="text-center text-sm-right"><span
class="badge {{$badgeColor}}">{{ $user->role }}</span>
<div class="text-center text-sm-right">
@foreach ($user->roles as $role)
<span style='background-color: {{$role->color}}' class='badge'>{{$role->name}}</span>
@endforeach
<div class="text-muted">
<small>{{ $user->created_at->isoFormat('LL') }}</small>
</div>

View file

@ -45,7 +45,7 @@
<div class="alert alert-danger p-2 m-2">
<h5><i class="icon fas fa-exclamation-circle"></i>{{ __('Error!') }}</h5>
<p class="pl-4">
@if (Auth::user()->role == 'admin')
@if (Auth::user()->hasRole("Admin"))
{{ __('Make sure to link your products to nodes and eggs.') }} <br>
{{ __('There has to be at least 1 valid product for server creation') }}
<a href="{{ route('admin.overview.sync') }}">{{ __('Sync now') }}</a>

View file

@ -27,17 +27,17 @@
<!-- CUSTOM CONTENT -->
<div class="d-flex justify-content-md-start justify-content-center mb-3 ">
<a @if (Auth::user()->Servers->count() >= Auth::user()->server_limit)
disabled="disabled" title="Server limit reached!"
@endif href="{{ route('servers.create') }}"
class="btn
@if (Auth::user()->Servers->count() >= Auth::user()->server_limit) disabled
@endif btn-primary"><i
class="fa fa-plus mr-2"></i>
<a @if (Auth::user()->Servers->count() >= Auth::user()->server_limit) disabled="disabled" title="Server limit reached!" @endif
@cannot("user.server.create") disabled="disabled" title="No Permission!" @endcannot
href="{{ route('servers.create') }}" class="btn
@if (Auth::user()->Servers->count() >= Auth::user()->server_limit) disabled @endif
@cannot("user.server.create") disabled @endcannot
btn-primary">
<i class="fa fa-plus mr-2"></i>
{{ __('Create Server') }}
</a>
@if (Auth::user()->Servers->count() > 0 && !empty($phpmyadmin_url))
<a
<a
href="{{ $phpmyadmin_url }}" target="_blank"
class="btn btn-secondary ml-2"><i title="manage"
class="fas fa-database mr-2"></i><span>{{ __('Database') }}</span>

View file

@ -222,7 +222,7 @@
<div class="card-footer">
<div class="col-md-12 text-center">
<!-- Upgrade Button trigger modal -->
@if($server_enable_upgrade)
@if($server_enable_upgrade && Auth::user()->can("user.server.upgrade"))
<button type="button" data-toggle="modal" data-target="#UpgradeModal{{ $server->id }}" target="__blank"
class="btn btn-info btn-md">
<i class="fas fa-upload mr-2"></i>

View file

@ -61,7 +61,7 @@
{{ $product->display }}
</td>
<td><a href="{{ route('checkout', $product->id) }}"
class="btn btn-info">{{ __('Purchase') }}</a>
class="btn btn-info @cannot('user.shop.buy') disabled @endcannot">{{ __('Purchase') }}</a>
</td>
</tr>
@endforeach

View file

@ -90,6 +90,17 @@
</span>
@endif
</div>
@if (app(App\Settings\GeneralSettings::class)->recaptcha_enabled)
<div class="input-group mb-3">
{!! htmlScriptTagJsApi() !!}
{!! htmlFormSnippet() !!}
@error('g-recaptcha-response')
<span class="text-danger" role="alert">
<small><strong>{{ $message }}</strong></small>
</span>
@enderror
</div>
@endif
</div>
<div class="card-footer">
<button type="submit" class="btn btn-primary ticket-once">

View file

@ -30,8 +30,8 @@
<div class="card-header">
<div class="d-flex justify-content-between">
<h5 class="card-title"><i class="fas fa-ticket-alt mr-2"></i>{{__('My Ticket')}}</h5>
<a href="{{route('ticket.new')}}" class="btn btn-sm btn-primary"><i
class="fas fa-plus mr-1"></i>{{__('New Ticket')}}</a>
<a href="{{route('ticket.new')}}" class="btn btn-sm btn-primary @cannot("user.ticket.write")) disabled @endcannot">
<i class="fas fa-plus mr-1"></i>{{__('New Ticket')}}</a>
</div>
</div>
<div class="card-body table-responsive">

View file

@ -118,7 +118,7 @@
<span class="badge badge-success"> Client </span>
@elseif ($ticket->user->role === "moderator")
<span class="badge badge-info"> Moderator </span>
@elseif ($ticket->user->role === "admin")
@elseif ($ticket->user->hasRole("Admin"))
<span class="badge badge-danger"> Admin </span>
@endif
</h5>
@ -142,7 +142,7 @@
<span class="badge badge-success"> Client </span>
@elseif ($ticketcomment->user->role === "moderator")
<span class="badge badge-info"> Moderator </span>
@elseif ($ticketcomment->user->role === "admin")
@elseif ($ticketcomment->user->hasRole("Admin"))
<span class="badge badge-danger"> Admin </span>
@endif
</h5>