OOM killer & Roles / Permissions API
This commit is contained in:
parent
d41d0a6e2d
commit
0899df5945
10 changed files with 251 additions and 30 deletions
|
@ -266,6 +266,7 @@ class PterodactylClient
|
|||
'docker_image' => $egg->docker_image,
|
||||
'startup' => $egg->startup,
|
||||
'environment' => $egg->getEnvironmentVariables(),
|
||||
'oom_disabled' => !$server->product->oom_killer,
|
||||
'limits' => [
|
||||
'memory' => $server->product->memory,
|
||||
'swap' => $server->product->swap,
|
||||
|
@ -378,6 +379,7 @@ class PterodactylClient
|
|||
'io' => $product->io,
|
||||
'cpu' => $product->cpu,
|
||||
'threads' => null,
|
||||
'oom_disabled' => !$server->product->oom_killer,
|
||||
'feature_limits' => [
|
||||
'databases' => $product->databases,
|
||||
'backups' => $product->backups,
|
||||
|
|
|
@ -87,6 +87,7 @@ class ProductController extends Controller
|
|||
'nodes.*' => 'required|exists:nodes,id',
|
||||
'eggs.*' => 'required|exists:eggs,id',
|
||||
'disabled' => 'nullable',
|
||||
'oom_killer' => 'nullable',
|
||||
]);
|
||||
|
||||
$disabled = ! is_null($request->input('disabled'));
|
||||
|
@ -159,6 +160,7 @@ class ProductController extends Controller
|
|||
'nodes.*' => 'required|exists:nodes,id',
|
||||
'eggs.*' => 'required|exists:eggs,id',
|
||||
'disabled' => 'nullable',
|
||||
'oom_killer' => 'nullable',
|
||||
]);
|
||||
|
||||
$disabled = ! is_null($request->input('disabled'));
|
||||
|
@ -256,6 +258,9 @@ class ProductController extends Controller
|
|||
->editColumn('minimum_credits', function (Product $product, UserSettings $user_settings) {
|
||||
return $product->minimum_credits==-1 ? $user_settings->min_credits_to_make_server : $product->minimum_credits;
|
||||
})
|
||||
->editColumn('oom_killer', function (Product $product, UserSettings $user_settings) {
|
||||
return $product->oom_killer ? __("enabled") : __("disabled");
|
||||
})
|
||||
->editColumn('created_at', function (Product $product) {
|
||||
return $product->created_at ? $product->created_at->diffForHumans() : '';
|
||||
})
|
||||
|
|
155
app/Http/Controllers/Api/RoleController.php
Normal file
155
app/Http/Controllers/Api/RoleController.php
Normal file
|
@ -0,0 +1,155 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\User;
|
||||
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Spatie\Permission\Models\Role;
|
||||
use Spatie\QueryBuilder\QueryBuilder;
|
||||
|
||||
class RoleController extends Controller
|
||||
{
|
||||
const ALLOWED_INCLUDES = ['permissions', 'users'];
|
||||
|
||||
const ALLOWED_FILTERS = ['name'];
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return LengthAwarePaginator
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$query = QueryBuilder::for(Role::class)
|
||||
->allowedIncludes(self::ALLOWED_INCLUDES)
|
||||
->allowedFilters(self::ALLOWED_FILTERS);
|
||||
|
||||
return $query->paginate($request->input('per_page') ?? 50);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'name' => 'nullable|string|max:191',
|
||||
'color' => [
|
||||
'required',
|
||||
'regex:/^#([a-f0-9]{6}|[a-f0-9]{3})$/i'
|
||||
],
|
||||
'power' => 'required',
|
||||
]);
|
||||
|
||||
$role = Role::create([
|
||||
'name' => $request->name,
|
||||
'color' => $request->color,
|
||||
'power' => $request->power,
|
||||
]);
|
||||
|
||||
if ($request->permissions) {
|
||||
$role->givePermissionTo($request->permissions);
|
||||
}
|
||||
|
||||
return $role;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param int $id
|
||||
* @return Role|Collection|Model
|
||||
*/
|
||||
public function show(int $id)
|
||||
{
|
||||
$query = QueryBuilder::for(Role::class)
|
||||
->where('id', '=', $id)
|
||||
->allowedIncludes(self::ALLOWED_INCLUDES);
|
||||
|
||||
return $query->firstOrFail();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param int $id
|
||||
* @return Response
|
||||
*/
|
||||
public function edit($id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param int $id
|
||||
* @return Response
|
||||
*/
|
||||
public function update(Request $request, int $id)
|
||||
{
|
||||
$role = Role::findOrFail($id);
|
||||
|
||||
$request->validate([
|
||||
'name' => 'nullable|string|max:191',
|
||||
'color' => [
|
||||
'required',
|
||||
'regex:/^#([a-f0-9]{6}|[a-f0-9]{3})$/i'
|
||||
],
|
||||
'power' => 'required',
|
||||
]);
|
||||
|
||||
if ($request->permissions) {
|
||||
$role->givePermissionTo($request->permissions);
|
||||
}
|
||||
|
||||
$role->update($request->all());
|
||||
//TODO PERMISSIONS?
|
||||
return $role;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param int $id
|
||||
* @return Response
|
||||
*/
|
||||
public function destroy(int $id)
|
||||
{
|
||||
$role = Role::findOrFail($id);
|
||||
|
||||
if($role->id == 1 || $role->id == 3|| $role->id == 4){ //cannot delete admin and User role
|
||||
return response()->json([
|
||||
'error' => 'Not allowed to delete Admin, Client or Member'], 400);
|
||||
}
|
||||
|
||||
$users = User::role($role)->get();
|
||||
|
||||
foreach($users as $user){
|
||||
$user->syncRoles([4]);
|
||||
}
|
||||
$role->delete();
|
||||
|
||||
return $role;
|
||||
}
|
||||
}
|
|
@ -2,16 +2,12 @@
|
|||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Classes\Pterodactyl;
|
||||
use App\Events\UserUpdateCreditsEvent;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\DiscordUser;
|
||||
use App\Models\User;
|
||||
use App\Notifications\ReferralNotification;
|
||||
use App\Traits\Referral;
|
||||
use App\Settings\PterodactylSettings;
|
||||
use App\Classes\PterodactylClient;
|
||||
use App\Settings\ReferralSettings;
|
||||
use App\Settings\UserSettings;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
||||
|
@ -31,18 +27,9 @@ use Spatie\QueryBuilder\QueryBuilder;
|
|||
|
||||
class UserController extends Controller
|
||||
{
|
||||
use Referral;
|
||||
const ALLOWED_INCLUDES = ['servers', 'notifications', 'payments', 'vouchers', 'roles', 'discordUser'];
|
||||
|
||||
const ALLOWED_INCLUDES = ['servers', 'notifications', 'payments', 'vouchers', 'discordUser'];
|
||||
|
||||
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);
|
||||
}
|
||||
const ALLOWED_FILTERS = ['name', 'server_limit', 'email', 'pterodactyl_id', 'suspended'];
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
|
@ -98,14 +85,13 @@ class UserController extends Controller
|
|||
'email' => 'sometimes|string|email',
|
||||
'credits' => 'sometimes|numeric|min:0|max:1000000',
|
||||
'server_limit' => 'sometimes|numeric|min:0|max:1000000',
|
||||
'role' => ['sometimes', Rule::in(['admin', 'moderator', 'client', 'member'])],
|
||||
]);
|
||||
|
||||
event(new UserUpdateCreditsEvent($user));
|
||||
|
||||
//Update Users Password on Pterodactyl
|
||||
//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,
|
||||
'first_name' => $request->name,
|
||||
'last_name' => $request->name,
|
||||
|
@ -213,7 +199,7 @@ class UserController extends Controller
|
|||
*
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function suspend(int $id)
|
||||
public function suspend(Request $request, int $id)
|
||||
{
|
||||
$discordUser = DiscordUser::find($id);
|
||||
$user = $discordUser ? $discordUser->user : User::findOrFail($id);
|
||||
|
@ -237,12 +223,12 @@ class UserController extends Controller
|
|||
*
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function unsuspend(int $id)
|
||||
public function unsuspend(Request $request, int $id)
|
||||
{
|
||||
$discordUser = DiscordUser::find($id);
|
||||
$user = $discordUser ? $discordUser->user : User::findOrFail($id);
|
||||
|
||||
if (!$user->isSuspended()) {
|
||||
if (! $user->isSuspended()) {
|
||||
throw ValidationException::withMessages([
|
||||
'error' => 'You cannot unsuspend an User who is not suspended.',
|
||||
]);
|
||||
|
@ -253,10 +239,25 @@ class UserController extends Controller
|
|||
return $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a unique Referral Code for User
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function createReferralCode()
|
||||
{
|
||||
$referralcode = STR::random(8);
|
||||
if (User::where('referral_code', '=', $referralcode)->exists()) {
|
||||
$this->createReferralCode();
|
||||
}
|
||||
|
||||
return $referralcode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function store(Request $request, UserSettings $user_settings, ReferralSettings $referral_settings)
|
||||
public function store(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'name' => ['required', 'string', 'max:30', 'min:4', 'alpha_num', 'unique:users'],
|
||||
|
@ -265,7 +266,7 @@ class UserController extends Controller
|
|||
]);
|
||||
|
||||
// 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([
|
||||
'error' => 'The creation of new users has been blocked by the system administrator.',
|
||||
]);
|
||||
|
@ -274,13 +275,13 @@ class UserController extends Controller
|
|||
$user = User::create([
|
||||
'name' => $request->input('name'),
|
||||
'email' => $request->input('email'),
|
||||
'credits' => $user_settings->initial_credits,
|
||||
'server_limit' => $user_settings->initial_server_limit,
|
||||
'credits' => config('SETTINGS::USER:INITIAL_CREDITS', 150),
|
||||
'server_limit' => config('SETTINGS::USER:INITIAL_SERVER_LIMIT', 1),
|
||||
'password' => Hash::make($request->input('password')),
|
||||
'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,
|
||||
'username' => $user->name,
|
||||
'email' => $user->email,
|
||||
|
@ -303,12 +304,12 @@ class UserController extends Controller
|
|||
'pterodactyl_id' => $response->json()['attributes']['id'],
|
||||
]);
|
||||
//INCREMENT REFERRAL-USER CREDITS
|
||||
if (!empty($request->input('referral_code'))) {
|
||||
if (! empty($request->input('referral_code'))) {
|
||||
$ref_code = $request->input('referral_code');
|
||||
$new_user = $user->id;
|
||||
if ($ref_user = User::query()->where('referral_code', '=', $ref_code)->first()) {
|
||||
if ($referral_settings->mode === 'register' || $referral_settings->mode === 'both') {
|
||||
$ref_user->increment('credits', $referral_settings->reward);
|
||||
if (config('SETTINGS::REFERRAL:MODE') == 'register' || config('SETTINGS::REFERRAL:MODE') == 'both') {
|
||||
$ref_user->increment('credits', config('SETTINGS::REFERRAL::REWARD'));
|
||||
$ref_user->notify(new ReferralNotification($ref_user->id, $new_user));
|
||||
}
|
||||
//INSERT INTO USER_REFERRALS TABLE
|
||||
|
|
32
database/migrations/2023_05_05_103834_oom_killer.php
Normal file
32
database/migrations/2023_05_05_103834_oom_killer.php
Normal file
|
@ -0,0 +1,32 @@
|
|||
<?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('products', function (Blueprint $table) {
|
||||
$table->boolean('oom_killer')->after("allocations")->default(false);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('products', function (Blueprint $table) {
|
||||
$table->dropColumn('oom_killer');
|
||||
});
|
||||
}
|
||||
};
|
|
@ -131,7 +131,15 @@
|
|||
</div>
|
||||
@enderror
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="checkbox" value="1" id="oom" name="oom_killer"
|
||||
class="">
|
||||
|
||||
<label for="oom_killer">{{__('OOM Killer')}} <i
|
||||
data-toggle="popover" data-trigger="hover"
|
||||
data-content="{{__('Enable or Disable the OOM Killer for this Product.')}}"
|
||||
class="fas fa-info-circle"></i></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div class="form-group">
|
||||
|
|
|
@ -139,6 +139,16 @@
|
|||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<input type="checkbox" @if($product->oom_killer) checked @endif value="1" id="oom" name="oom_killer"
|
||||
class="">
|
||||
|
||||
<label for="oom_killer">{{__('OOM Killer')}} <i
|
||||
data-toggle="popover" data-trigger="hover"
|
||||
data-content="{{__('Enable or Disable the OOM Killer for this Product.')}}"
|
||||
class="fas fa-info-circle"></i></label>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div class="form-group">
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
<th>{{__('Nodes')}}</th>
|
||||
<th>{{__('Eggs')}}</th>
|
||||
<th>{{__('Min Credits')}}</th>
|
||||
<th>{{__('OOM Killer')}}</th>
|
||||
<th>{{__('Servers')}}</th>
|
||||
<th>{{__('Created at')}}</th>
|
||||
<th>{{ __('Actions') }}</th>
|
||||
|
@ -101,6 +102,7 @@
|
|||
{data: "nodes", sortable: false},
|
||||
{data: "eggs", sortable: false},
|
||||
{data: "minimum_credits"},
|
||||
{data: "oom_killer"},
|
||||
{data: "servers", sortable: false},
|
||||
{data: "created_at"},
|
||||
{data: "actions", sortable: false}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
href="{{ \Illuminate\Support\Facades\Storage::disk('public')->exists('favicon.ico') ? asset('storage/favicon.ico') : asset('favicon.ico') }}"
|
||||
type="image/x-icon">
|
||||
|
||||
<script src="{{ asset('plugins/alpinejs/3.12.0_cdn.min.js') }}"></script>
|
||||
<script src="{{ asset('plugins/alpinejs/3.12.0_cdn.min.js') }}" defer></script>
|
||||
|
||||
{{-- <link rel="stylesheet" href="{{asset('css/adminlte.min.css')}}"> --}}
|
||||
<link rel="stylesheet" href="{{ asset('plugins/datatables/jquery.dataTables.min.css') }}">
|
||||
|
|
|
@ -201,6 +201,12 @@
|
|||
{{ __('Databases') }}</span>
|
||||
<span class="d-inline-block" x-text="product.databases"></span>
|
||||
</li>
|
||||
<li class="d-flex justify-content-between">
|
||||
<span class="d-inline-block"><i class="fas fa-skull-crossbones"></i>
|
||||
{{ __('OOM Killer') }}</span>
|
||||
<span class="d-inline-block"
|
||||
x-text="product.oom_killer == 1 ? 'enabled' : 'disabled'"></span>
|
||||
</li>
|
||||
<li class="d-flex justify-content-between">
|
||||
<span class="d-inline-block"><i class="fas fa-network-wired"></i>
|
||||
{{ __('Allocations') }}
|
||||
|
|
Loading…
Add table
Reference in a new issue