diff --git a/app/Http/Controllers/Admin/ConfigurationController.php b/app/Http/Controllers/Admin/ConfigurationController.php index 2facf165..d16a765e 100644 --- a/app/Http/Controllers/Admin/ConfigurationController.php +++ b/app/Http/Controllers/Admin/ConfigurationController.php @@ -112,7 +112,7 @@ class ConfigurationController extends Controller return datatables($query) ->addColumn('actions', function (Configuration $configuration) { - return ' '; + return ' '; }) ->editColumn('created_at', function (Configuration $configuration) { return $configuration->created_at ? $configuration->created_at->diffForHumans() : ''; diff --git a/app/Http/Controllers/Admin/PaymentController.php b/app/Http/Controllers/Admin/PaymentController.php index 110d2c0d..a7001427 100644 --- a/app/Http/Controllers/Admin/PaymentController.php +++ b/app/Http/Controllers/Admin/PaymentController.php @@ -141,12 +141,12 @@ class PaymentController extends Controller $user->increment('credits', $paypalProduct->quantity); //update server limit - if (Configuration::getValueByKey('SERVER_LIMIT_AFTER_IRL_PURCHASE', 10) !== 0) { - if ($user->server_limit < Configuration::getValueByKey('SERVER_LIMIT_AFTER_IRL_PURCHASE', 10)) { - $user->update(['server_limit' => 10]); + if (Configuration::getValueByKey('SERVER_LIMIT_AFTER_IRL_PURCHASE') !== 0) { + if ($user->server_limit < Configuration::getValueByKey('SERVER_LIMIT_AFTER_IRL_PURCHASE')) { + $user->update(['server_limit' => Configuration::getValueByKey('SERVER_LIMIT_AFTER_IRL_PURCHASE')]); } } - + //update role if ($user->role == 'member') { $user->update(['role' => 'client']); diff --git a/app/Http/Controllers/Admin/ProductController.php b/app/Http/Controllers/Admin/ProductController.php index 97407644..ffa6856b 100644 --- a/app/Http/Controllers/Admin/ProductController.php +++ b/app/Http/Controllers/Admin/ProductController.php @@ -3,6 +3,7 @@ namespace App\Http\Controllers\Admin; use App\Http\Controllers\Controller; +use App\Models\Configuration; use App\Models\Product; use Exception; use Illuminate\Contracts\Foundation\Application; @@ -51,6 +52,7 @@ class ProductController extends Controller "swap" => "required|numeric|max:1000000|min:0", "description" => "required|string|max:191", "disk" => "required|numeric|max:1000000|min:5", + "minimum_credits" => "required|numeric|max:1000000|min:-1", "io" => "required|numeric|max:1000000|min:0", "databases" => "required|numeric|max:1000000|min:0", "backups" => "required|numeric|max:1000000|min:0", @@ -73,7 +75,8 @@ class ProductController extends Controller public function show(Product $product) { return view('admin.products.show', [ - 'product' => $product + 'product' => $product, + 'minimum_credits' => Configuration::getValueByKey("MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER"), ]); } @@ -108,6 +111,7 @@ class ProductController extends Controller "description" => "required|string|max:191", "disk" => "required|numeric|max:1000000|min:5", "io" => "required|numeric|max:1000000|min:0", + "minimum_credits" => "required|numeric|max:1000000|min:-1", "databases" => "required|numeric|max:1000000|min:0", "backups" => "required|numeric|max:1000000|min:0", "allocations" => "required|numeric|max:1000000|min:0", @@ -125,7 +129,8 @@ class ProductController extends Controller * @param Product $product * @return RedirectResponse */ - public function disable(Request $request, Product $product) { + public function disable(Request $request, Product $product) + { $product->update(['disabled' => !$product->disabled]); return redirect()->route('admin.products.index')->with('success', 'product has been updated!'); @@ -181,12 +186,11 @@ class ProductController extends Controller ' . csrf_field() . ' ' . method_field("PATCH") . '
- - + +
'; - }) ->editColumn('created_at', function (Product $product) { return $product->created_at ? $product->created_at->diffForHumans() : ''; diff --git a/app/Http/Controllers/Admin/UserController.php b/app/Http/Controllers/Admin/UserController.php index 795ad553..50c4fc5e 100644 --- a/app/Http/Controllers/Admin/UserController.php +++ b/app/Http/Controllers/Admin/UserController.php @@ -221,6 +221,20 @@ class UserController extends Controller return redirect()->route('admin.users.notifications')->with('success', 'Notification sent!'); } + /** + * @param User $user + * @return RedirectResponse + */ + public function toggleSuspended(User $user){ + try { + !$user->isSuspended() ? $user->suspend() : $user->unSuspend(); + } catch (Exception $exception) { + return redirect()->back()->with('error', $exception->getMessage()); + } + + return redirect()->back()->with('success', 'User has been updated!'); + } + /** * * @throws Exception @@ -252,10 +266,17 @@ class UserController extends Controller return $user->last_seen ? $user->last_seen->diffForHumans() : ''; }) ->addColumn('actions', function (User $user) { + $suspendColor = $user->isSuspended() ? "btn-success" : "btn-warning"; + $suspendIcon = $user->isSuspended() ? "fa-play-circle" : "fa-pause-circle"; + $suspendText = $user->isSuspended() ? "Unsuspend" : "Suspend"; return ' +
+ ' . csrf_field() . ' + +
' . csrf_field() . ' ' . method_field("DELETE") . ' diff --git a/app/Http/Controllers/Admin/VoucherController.php b/app/Http/Controllers/Admin/VoucherController.php index 1aa2c59e..31947dbd 100644 --- a/app/Http/Controllers/Admin/VoucherController.php +++ b/app/Http/Controllers/Admin/VoucherController.php @@ -4,6 +4,7 @@ namespace App\Http\Controllers\Admin; use App\Events\UserUpdateCreditsEvent; use App\Http\Controllers\Controller; +use App\Models\User; use App\Models\Voucher; use Illuminate\Contracts\Foundation\Application; use Illuminate\Contracts\View\Factory; @@ -115,6 +116,13 @@ class VoucherController extends Controller return redirect()->back()->with('success', 'voucher has been removed!'); } + public function users(Voucher $voucher) + { + return view('admin.vouchers.users', [ + 'voucher' => $voucher + ]); + } + /** * @param Request $request * @return JsonResponse @@ -144,7 +152,7 @@ class VoucherController extends Controller ]); if ($request->user()->credits + $voucher->credits >= 99999999) throw ValidationException::withMessages([ - 'code' => "You can't redeem this voucher because you would exceed the ".CREDITS_DISPLAY_NAME." limit" + 'code' => "You can't redeem this voucher because you would exceed the " . CREDITS_DISPLAY_NAME . " limit" ]); #redeem voucher @@ -153,10 +161,27 @@ class VoucherController extends Controller event(new UserUpdateCreditsEvent($request->user())); return response()->json([ - 'success' => "{$voucher->credits} ".CREDITS_DISPLAY_NAME." have been added to your balance!" + 'success' => "{$voucher->credits} " . CREDITS_DISPLAY_NAME . " have been added to your balance!" ]); } + public function usersDataTable(Voucher $voucher) + { + $users = $voucher->users(); + + return datatables($users) + ->editColumn('name', function (User $user) { + return '' . $user->name . ''; + }) + ->addColumn('credits', function (User $user) { + return ' ' . $user->credits(); + }) + ->addColumn('last_seen', function (User $user) { + return $user->last_seen ? $user->last_seen->diffForHumans() : ''; + }) + ->rawColumns(['name', 'credits', 'last_seen']) + ->make(); + } public function dataTable() { $query = Voucher::query(); @@ -164,6 +189,7 @@ class VoucherController extends Controller return datatables($query) ->addColumn('actions', function (Voucher $voucher) { return ' + diff --git a/app/Http/Controllers/Api/NotificationController.php b/app/Http/Controllers/Api/NotificationController.php index ceecbb24..9fe61c79 100644 --- a/app/Http/Controllers/Api/NotificationController.php +++ b/app/Http/Controllers/Api/NotificationController.php @@ -6,11 +6,13 @@ use App\Http\Controllers\Controller; use App\Models\DiscordUser; use App\Models\User; use App\Notifications\DynamicNotification; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Support\Facades\Notification; use Illuminate\Support\HtmlString; +use Illuminate\Validation\ValidationException; use Spatie\ValidationRules\Rules\Delimited; class NotificationController extends Controller @@ -55,19 +57,21 @@ class NotificationController extends Controller * * @param Request $request * @return JsonResponse + * @throws ValidationException */ public function send(Request $request) { $data = $request->validate([ "via" => ["required", new Delimited("in:mail,database")], "all" => "required_without:users|boolean", - "users" => ["required_without:all", new Delimited("exists:users,id")], + "users" => ["required_without:all"], "title" => "required|string|min:1", "content" => "required|string|min:1" ]); $via = explode(",", $data["via"]); $mail = null; $database = null; + if (in_array("database", $via)) { $database = [ "title" => $data["title"], @@ -79,10 +83,28 @@ class NotificationController extends Controller ->subject($data["title"]) ->line(new HtmlString($data["content"])); } + $all = $data["all"] ?? false; - $users = $all ? User::all() : User::whereIn("id", explode(",", $data["users"]))->get(); + if ($all) { + $users = User::all(); + } else { + $userIds = explode(",", $data["users"]); + $users = User::query() + ->whereIn("id", $userIds) + ->orWhereHas('discordUser', function (Builder $builder) use ($userIds) { + $builder->whereIn('id', $userIds); + }) + ->get(); + } + + if ($users->count() == 0) { + throw ValidationException::withMessages([ + 'users' => ['No users found!'], + ]); + } + Notification::send($users, new DynamicNotification($via, $database, $mail)); - return response()->json(["message" => "Notification successfully sent."]); + return response()->json(["message" => "Notification successfully sent.", 'user_count' => $users->count()]); } /** diff --git a/app/Http/Controllers/Api/ServerController.php b/app/Http/Controllers/Api/ServerController.php index fcfa1b14..1b9468c0 100644 --- a/app/Http/Controllers/Api/ServerController.php +++ b/app/Http/Controllers/Api/ServerController.php @@ -6,11 +6,17 @@ use App\Http\Controllers\Controller; use App\Models\Server; use Exception; use Illuminate\Contracts\Pagination\LengthAwarePaginator; +use Illuminate\Database\Eloquent\Collection; +use Illuminate\Database\Eloquent\Model; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use Spatie\QueryBuilder\QueryBuilder; class ServerController extends Controller { + public const ALLOWED_INCLUDES = ['product', 'user']; + public const ALLOWED_FILTERS = ['name', 'suspended', 'identifier', 'pterodactyl_id', 'user_id', 'product_id']; + /** * Display a listing of the resource. * @@ -19,21 +25,28 @@ class ServerController extends Controller */ public function index(Request $request) { - return Server::with('product')->paginate($request->query('per_page') ?? 50); - } + $query = QueryBuilder::for(Server::class) + ->allowedIncludes(self::ALLOWED_INCLUDES) + ->allowedFilters(self::ALLOWED_FILTERS); + return $query->paginate($request->input('per_page') ?? 50); + } /** * Display the specified resource. * * @param Server $server - * @return Server + * + * @return Server|Collection|Model */ public function show(Server $server) { - return $server->load('product'); - } + $query = QueryBuilder::for(Server::class) + ->where('id', '=', $server->id) + ->allowedIncludes(self::ALLOWED_INCLUDES); + return $query->firstOrFail(); + } /** * Remove the specified resource from storage. diff --git a/app/Http/Controllers/Api/UserController.php b/app/Http/Controllers/Api/UserController.php index a5f7263c..07a7a698 100644 --- a/app/Http/Controllers/Api/UserController.php +++ b/app/Http/Controllers/Api/UserController.php @@ -2,28 +2,45 @@ namespace App\Http\Controllers\Api; +use App\Classes\Pterodactyl; use App\Events\UserUpdateCreditsEvent; use App\Http\Controllers\Controller; +use App\Models\Configuration; use App\Models\DiscordUser; use App\Models\User; use Illuminate\Contracts\Foundation\Application; +use Illuminate\Contracts\Pagination\LengthAwarePaginator; use Illuminate\Contracts\Routing\ResponseFactory; +use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Collection; +use Illuminate\Database\Eloquent\Model; use Illuminate\Http\Request; use Illuminate\Http\Response; +use Illuminate\Support\Facades\App; +use Illuminate\Support\Facades\Hash; +use Illuminate\Support\Str; use Illuminate\Validation\Rule; use Illuminate\Validation\ValidationException; +use Spatie\QueryBuilder\QueryBuilder; class UserController extends Controller { + const ALLOWED_INCLUDES = ['servers', 'notifications', 'payments', 'vouchers', 'discordUser']; + const ALLOWED_FILTERS = ['name', 'server_limit', 'email', 'pterodactyl_id', 'role', 'suspended']; + /** * Display a listing of the resource. * * @param Request $request - * @return Response + * @return LengthAwarePaginator */ public function index(Request $request) { - return User::paginate($request->query('per_page') ?? 50); + $query = QueryBuilder::for(User::class) + ->allowedIncludes(self::ALLOWED_INCLUDES) + ->allowedFilters(self::ALLOWED_FILTERS); + + return $query->paginate($request->input('per_page') ?? 50); } @@ -31,12 +48,23 @@ class UserController extends Controller * Display the specified resource. * * @param int $id - * @return User + * + * @return User|Builder|Collection|Model */ public function show(int $id) { $discordUser = DiscordUser::find($id); - return $discordUser ? $discordUser->user : User::findOrFail($id); + $user = $discordUser ? $discordUser->user : User::findOrFail($id); + + $query = QueryBuilder::for($user) + ->with('discordUser') + ->allowedIncludes(self::ALLOWED_INCLUDES) + ->where('users.id', '=', $id) + ->orWhereHas('discordUser', function (Builder $builder) use ($id) { + $builder->where('id', '=', $id); + }); + + return $query->firstOrFail(); } @@ -53,11 +81,11 @@ class UserController extends Controller $user = $discordUser ? $discordUser->user : User::findOrFail($id); $request->validate([ - "name" => "sometimes|string|min:4|max:30", - "email" => "sometimes|string|email", - "credits" => "sometimes|numeric|min:0|max:1000000", + "name" => "sometimes|string|min:4|max:30", + "email" => "sometimes|string|email", + "credits" => "sometimes|numeric|min:0|max:1000000", "server_limit" => "sometimes|numeric|min:0|max:1000000", - "role" => ['sometimes', Rule::in(['admin', 'mod', 'client', 'member'])], + "role" => ['sometimes', Rule::in(['admin', 'mod', 'client', 'member'])], ]); $user->update($request->all()); @@ -81,23 +109,23 @@ class UserController extends Controller $user = $discordUser ? $discordUser->user : User::findOrFail($id); $request->validate([ - "credits" => "sometimes|numeric|min:0|max:1000000", + "credits" => "sometimes|numeric|min:0|max:1000000", "server_limit" => "sometimes|numeric|min:0|max:1000000", ]); - if($request->credits){ - if ($user->credits + $request->credits >= 99999999) throw ValidationException::withMessages([ + if ($request->credits) { + if ($user->credits + $request->credits >= 99999999) throw ValidationException::withMessages([ 'credits' => "You can't add this amount of credits because you would exceed the credit limit" ]); event(new UserUpdateCreditsEvent($user)); $user->increment('credits', $request->credits); - } + } - if($request->server_limit){ + if ($request->server_limit) { if ($user->server_limit + $request->server_limit >= 2147483647) throw ValidationException::withMessages([ 'server_limit' => "You cannot add this amount of servers because it would exceed the server limit." ]); - $user->increment('server_limit', $request->server_limit); + $user->increment('server_limit', $request->server_limit); } return $user; @@ -117,27 +145,72 @@ class UserController extends Controller $user = $discordUser ? $discordUser->user : User::findOrFail($id); $request->validate([ - "credits" => "sometimes|numeric|min:0|max:1000000", + "credits" => "sometimes|numeric|min:0|max:1000000", "server_limit" => "sometimes|numeric|min:0|max:1000000", ]); - if($request->credits){ - if($user->credits - $request->credits < 0) throw ValidationException::withMessages([ + if ($request->credits) { + if ($user->credits - $request->credits < 0) throw ValidationException::withMessages([ 'credits' => "You can't remove this amount of credits because you would exceed the minimum credit limit" ]); $user->decrement('credits', $request->credits); - } + } - if($request->server_limit){ - if($user->server_limit - $request->server_limit < 0) throw ValidationException::withMessages([ + if ($request->server_limit) { + if ($user->server_limit - $request->server_limit < 0) throw ValidationException::withMessages([ 'server_limit' => "You cannot remove this amount of servers because it would exceed the minimum server." ]); - $user->decrement('server_limit', $request->server_limit); + $user->decrement('server_limit', $request->server_limit); } return $user; } + /** + * @throws ValidationException + */ + public function store(Request $request) + { + $request->validate([ + 'name' => ['required', 'string', 'max:30', 'min:4', 'alpha_num', 'unique:users'], + 'email' => ['required', 'string', 'email', 'max:64', 'unique:users'], + 'password' => ['required', 'string', 'min:8', 'max:191'], + ]); + + $user = User::create([ + 'name' => $request->input('name'), + 'email' => $request->input('email'), + 'credits' => Configuration::getValueByKey('INITIAL_CREDITS', 150), + 'server_limit' => Configuration::getValueByKey('INITIAL_SERVER_LIMIT', 1), + 'password' => Hash::make($request->input('password')), + ]); + + $response = Pterodactyl::client()->post('/application/users', [ + "external_id" => App::environment('local') ? Str::random(16) : (string)$user->id, + "username" => $user->name, + "email" => $user->email, + "first_name" => $user->name, + "last_name" => $user->name, + "password" => $request->input('password'), + "root_admin" => false, + "language" => "en" + ]); + + if ($response->failed()) { + $user->delete(); + throw ValidationException::withMessages([ + 'pterodactyl_error_message' => $response->toException()->getMessage(), + 'pterodactyl_error_status' => $response->toException()->getCode() + ]); + } + + $user->update([ + 'pterodactyl_id' => $response->json()['attributes']['id'] + ]); + + return $user; + } + /** * Remove the specified resource from storage. * diff --git a/app/Http/Controllers/Api/VoucherController.php b/app/Http/Controllers/Api/VoucherController.php index f7acfdd5..a094fe1d 100644 --- a/app/Http/Controllers/Api/VoucherController.php +++ b/app/Http/Controllers/Api/VoucherController.php @@ -5,20 +5,30 @@ namespace App\Http\Controllers\Api; use App\Http\Controllers\Controller; use App\Models\Voucher; 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\QueryBuilder\QueryBuilder; class VoucherController extends Controller { + const ALLOWED_INCLUDES = ['users']; + const ALLOWED_FILTERS = ['code', 'memo', 'credits', 'uses']; + /** * Display a listing of the resource. * - * @return Response + * @return LengthAwarePaginator */ public function index(Request $request) { - return Voucher::paginate($request->query('per_page') ?? 50); + $query = QueryBuilder::for(Voucher::class) + ->allowedIncludes(self::ALLOWED_INCLUDES) + ->allowedFilters(self::ALLOWED_FILTERS); + + return $query->paginate($request->input('per_page') ?? 50); } /** @@ -40,10 +50,10 @@ class VoucherController extends Controller public function store(Request $request) { $request->validate([ - 'memo' => 'nullable|string|max:191', - 'code' => 'required|string|alpha_dash|max:36|min:4|unique:vouchers', - 'uses' => 'required|numeric|max:2147483647|min:1', - 'credits' => 'required|numeric|between:0,99999999', + 'memo' => 'nullable|string|max:191', + 'code' => 'required|string|alpha_dash|max:36|min:4|unique:vouchers', + 'uses' => 'required|numeric|max:2147483647|min:1', + 'credits' => 'required|numeric|between:0,99999999', 'expires_at' => 'nullable|multiple_date_format:d-m-Y H:i:s,d-m-Y|after:now|before:10 years' ]); @@ -54,11 +64,16 @@ class VoucherController extends Controller * Display the specified resource. * * @param int $id - * @return Response + * + * @return Voucher|Collection|Model */ public function show(int $id) { - return Voucher::findOrFail($id); + $query = QueryBuilder::for(Voucher::class) + ->where('id', '=', $id) + ->allowedIncludes(self::ALLOWED_INCLUDES); + + return $query->firstOrFail(); } /** @@ -84,10 +99,10 @@ class VoucherController extends Controller $voucher = Voucher::findOrFail($id); $request->validate([ - 'memo' => 'nullable|string|max:191', - 'code' => "required|string|alpha_dash|max:36|min:4|unique:vouchers,code,{$voucher->id}", - 'uses' => 'required|numeric|max:2147483647|min:1', - 'credits' => 'required|numeric|between:0,99999999', + 'memo' => 'nullable|string|max:191', + 'code' => "required|string|alpha_dash|max:36|min:4|unique:vouchers,code,{$voucher->id}", + 'uses' => 'required|numeric|max:2147483647|min:1', + 'credits' => 'required|numeric|between:0,99999999', 'expires_at' => 'nullable|multiple_date_format:d-m-Y H:i:s,d-m-Y|after:now|before:10 years' ]); diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index bb6838f3..fa8611d4 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -1,30 +1,108 @@ middleware('auth'); } + /** + * @description Get the Background Color for the Days-Left-Box in HomeView + * + * @param float $days + * + * @return string + */ + public function getTimeLeftBoxBackground(float $days) + { + switch ($days) + { + case ($days >= 15): + return $this::TIME_LEFT_BG_SUCCESS; + break; + + case ($days >= 8 && $days <= 14): + return $this::TIME_LEFT_BG_WARNING; + break; + + case ($days <= 7): + return $this::TIME_LEFT_BG_DANGER; + break; + + default: + return $this::TIME_LEFT_BG_WARNING; + } + } + + /** + * @description Get the Text for the Days-Left-Box in HomeView + * + * @param float $days + * @param float $hours + * + * @return string + */ + public function getTimeLeftBoxText(float $days, float $hours) + { + if ($days < 1) + { + if ($hours < 1) + { + return $this::TIME_LEFT_OUT_OF_CREDITS_TEXT; + } + else + { + return strval($hours); + } + } + return strval(number_format($days, 0)); + } + /** Show the application dashboard. */ public function index(Request $request) { - $usage = 0; + $usage = Auth::user()->creditUsage(); + $credits = Auth::user()->Credits(); + $bg = ""; + $boxText = ""; + $unit = ""; + + /** Build our Time-Left-Box */ + if ($credits > 0.01 and $usage > 0) + { + $days = number_format(($credits * 30) / $usage, 2, '.', ''); + $hours = number_format($credits / ($usage / 30 / 24) , 2, '.', ''); + + $bg = $this->getTimeLeftBoxBackground($days); + $boxText = $this->getTimeLeftBoxText($days, $hours); + $unit = $days < 1 ? 'hours' : 'days'; - foreach (Auth::user()->servers as $server){ - $usage += $server->product->price; } + + + // RETURN ALL VALUES return view('home')->with([ 'useage' => $usage, - 'useful_links' => UsefulLink::all()->sortBy('id') + 'credits' => $credits, + 'useful_links' => UsefulLink::all()->sortBy('id'), + 'bg' => $bg, + 'boxText' => $boxText, + 'unit' => $unit ]); } + } + diff --git a/app/Http/Controllers/ServerController.php b/app/Http/Controllers/ServerController.php index f916c52c..d1c260cd 100644 --- a/app/Http/Controllers/ServerController.php +++ b/app/Http/Controllers/ServerController.php @@ -16,7 +16,8 @@ use Illuminate\Http\Client\Response; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; - +use Illuminate\Support\Facades\Log; +use Illuminate\Support\Facades\Request as FacadesRequest; class ServerController extends Controller { @@ -39,6 +40,7 @@ class ServerController extends Controller $query->where('disabled', '=', false); })->get(), 'nests' => Nest::where('disabled', '=', false)->get(), + 'minimum_credits' => Configuration::getValueByKey('MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER', 50) ]); } @@ -52,7 +54,7 @@ class ServerController extends Controller "description" => "nullable|max:191", "node_id" => "required|exists:nodes,id", "egg_id" => "required|exists:eggs,id", - "product_id" => "required|exists:products,id", + "product_id" => "required|exists:products,id" ]); //get required resources @@ -74,8 +76,8 @@ class ServerController extends Controller 'identifier' => $response->json()['attributes']['identifier'] ]); - if (Configuration::getValueByKey('SERVER_CREATE_CHARGE_FIRST_HOUR' , 'true') == 'true'){ - if (Auth::user()->credits >= $server->product->getHourlyPrice()){ + if (Configuration::getValueByKey('SERVER_CREATE_CHARGE_FIRST_HOUR', 'true') == 'true') { + if (Auth::user()->credits >= $server->product->getHourlyPrice()) { Auth::user()->decrement('credits', $server->product->getHourlyPrice()); } } @@ -86,15 +88,24 @@ class ServerController extends Controller /** * @return null|RedirectResponse */ - private function validateConfigurationRules(){ + private function validateConfigurationRules() + { //limit validation if (Auth::user()->servers()->count() >= Auth::user()->server_limit) { return redirect()->route('servers.index')->with('error', 'Server limit reached!'); } - //minimum credits - if (Auth::user()->credits <= Configuration::getValueByKey('MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER', 50)) { - return redirect()->route('servers.index')->with('error', "You do not have the required amount of ".CREDITS_DISPLAY_NAME." to create a new server!"); + // minimum credits + if (FacadesRequest::has("product_id")) { + $product = Product::findOrFail(FacadesRequest::input("product_id")); + if ( + Auth::user()->credits < + ($product->minimum_credits == -1 + ? Configuration::getValueByKey('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!"); + } } //Required Verification for creating an server @@ -141,7 +152,7 @@ class ServerController extends Controller * @param Server $server * @return RedirectResponse */ - private function serverCreationFailed(Response $response , Server $server) + private function serverCreationFailed(Response $response, Server $server) { $server->delete(); diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 572a8656..6454849a 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -3,6 +3,7 @@ namespace App\Http; use App\Http\Middleware\ApiAuthToken; +use App\Http\Middleware\CheckSuspended; use App\Http\Middleware\CreditsDisplayName; use App\Http\Middleware\isAdmin; use App\Http\Middleware\LastSeen; @@ -42,7 +43,7 @@ class Kernel extends HttpKernel \App\Http\Middleware\VerifyCsrfToken::class, \Illuminate\Routing\Middleware\SubstituteBindings::class, LastSeen::class, - CreditsDisplayName::class + CreditsDisplayName::class, ], 'api' => [ @@ -70,6 +71,7 @@ class Kernel extends HttpKernel 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, 'admin' => isAdmin::class, - 'api.token' => ApiAuthToken::class + 'api.token' => ApiAuthToken::class, + 'checkSuspended' => CheckSuspended::class ]; } diff --git a/app/Http/Middleware/CheckSuspended.php b/app/Http/Middleware/CheckSuspended.php new file mode 100644 index 00000000..59fcc614 --- /dev/null +++ b/app/Http/Middleware/CheckSuspended.php @@ -0,0 +1,28 @@ +check() && auth()->user()->isSuspended()) { + auth()->logout(); + + $message = 'Your account has been suspended. Please contact our support team!'; + + return redirect()->route('login')->withMessage($message); + } + return $next($request); + } +} diff --git a/app/Models/Product.php b/app/Models/Product.php index 68dc8f74..f1725da3 100644 --- a/app/Models/Product.php +++ b/app/Models/Product.php @@ -6,7 +6,6 @@ use Hidehalo\Nanoid\Client; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; -use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Spatie\Activitylog\Traits\LogsActivity; class Product extends Model @@ -17,10 +16,11 @@ class Product extends Model protected $guarded = ['id']; - public static function boot() { + public static function boot() + { parent::boot(); - static::creating(function(Product $product) { + static::creating(function (Product $product) { $client = new Client(); $product->{$product->getKeyName()} = $client->generateId($size = 21); @@ -47,6 +47,6 @@ class Product extends Model */ public function servers(): BelongsTo { - return $this->belongsTo(Server::class , 'id' , 'product_id'); + return $this->belongsTo(Server::class, 'id', 'product_id'); } } diff --git a/app/Models/User.php b/app/Models/User.php index 6dc4efc8..9c1d8568 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -59,7 +59,8 @@ class User extends Authenticatable implements MustVerifyEmail 'password', 'pterodactyl_id', 'discord_verified_at', - 'avatar' + 'avatar', + 'suspended' ]; /** @@ -79,7 +80,9 @@ class User extends Authenticatable implements MustVerifyEmail */ protected $casts = [ 'email_verified_at' => 'datetime', - 'last_seen' => 'datetime', + 'last_seen' => 'datetime', + 'credits' => 'float', + 'server_limit' => 'float', ]; /** @@ -94,13 +97,13 @@ class User extends Authenticatable implements MustVerifyEmail }); static::deleting(function (User $user) { - $user->servers()->chunk(10 , function ($servers) { + $user->servers()->chunk(10, function ($servers) { foreach ($servers as $server) { $server->delete(); } }); - $user->payments()->chunk(10 , function ($payments) { + $user->payments()->chunk(10, function ($payments) { foreach ($payments as $payment) { $payment->delete(); } @@ -114,6 +117,38 @@ class User extends Authenticatable implements MustVerifyEmail }); } + /** + * @return HasMany + */ + public function servers() + { + return $this->hasMany(Server::class); + } + + /** + * @return HasMany + */ + public function payments() + { + return $this->hasMany(Payment::class); + } + + /** + * @return BelongsToMany + */ + public function vouchers() + { + return $this->belongsToMany(Voucher::class); + } + + /** + * @return HasOne + */ + public function discordUser() + { + return $this->hasOne(DiscordUser::class); + } + /** * */ @@ -130,11 +165,67 @@ class User extends Authenticatable implements MustVerifyEmail return number_format($this->credits, 2, '.', ''); } + /** + * @return bool + */ + public function isSuspended() + { + return $this->suspended; + } + + /** + * + * @throws Exception + */ + public function suspend() + { + foreach ($this->servers as $server) { + $server->suspend(); + } + + $this->update([ + 'suspended' => true + ]); + + return $this; + } + + /** + * @throws Exception + */ + public function unSuspend() + { + foreach ($this->servers as $server) { + if ($this->credits >= $server->product->getHourlyPrice()) { + $server->unSuspend(); + } + } + + $this->update([ + 'suspended' => false + ]); + + return $this; + } + /** * @return string */ - 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 +// 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))); + } /** @@ -144,7 +235,7 @@ class User extends Authenticatable implements MustVerifyEmail { $usage = 0; - foreach ($this->Servers as $server){ + foreach ($this->Servers as $server) { $usage += $server->product->price; } @@ -154,42 +245,12 @@ class User extends Authenticatable implements MustVerifyEmail /** * @return array|string|string[] */ - public function getVerifiedStatus(){ + public function getVerifiedStatus() + { $status = ''; if ($this->hasVerifiedEmail()) $status .= 'email '; if ($this->discordUser()->exists()) $status .= 'discord'; - $status = str_replace(' ' , '/' , $status); + $status = str_replace(' ', '/', $status); return $status; } - - /** - * @return BelongsToMany - */ - public function vouchers(){ - return $this->belongsToMany(Voucher::class); - } - - /** - * @return HasOne - */ - public function discordUser(){ - return $this->hasOne(DiscordUser::class); - } - - /** - * @return HasMany - */ - public function servers() - { - return $this->hasMany(Server::class); - } - - /** - * @return HasMany - */ - public function payments() - { - return $this->hasMany(Payment::class); - } - } diff --git a/app/Models/Voucher.php b/app/Models/Voucher.php index bff3e215..81fe635a 100644 --- a/app/Models/Voucher.php +++ b/app/Models/Voucher.php @@ -31,7 +31,17 @@ class Voucher extends Model 'expires_at' ]; - protected $appends = ['used' , 'status']; + /** + * The attributes that should be cast to native types. + * + * @var array + */ + protected $casts = [ + 'credits' => 'float', + 'uses' => 'integer' + ]; + + protected $appends = ['used', 'status']; /** * @return int @@ -44,7 +54,8 @@ class Voucher extends Model /** * @return string */ - public function getStatusAttribute(){ + public function getStatusAttribute() + { return $this->getStatus(); } diff --git a/app/Notifications/WelcomeMessage.php b/app/Notifications/WelcomeMessage.php index 6f30e032..5e21542e 100644 --- a/app/Notifications/WelcomeMessage.php +++ b/app/Notifications/WelcomeMessage.php @@ -37,7 +37,26 @@ class WelcomeMessage extends Notification implements ShouldQueue { return ['database']; } + public function AdditionalLines() + { + $AdditionalLine = ""; + if(Configuration::getValueByKey('CREDITS_REWARD_AFTER_VERIFY_EMAIL') != 0) { + $AdditionalLine .= "Verifying your e-mail address will grant you ".Configuration::getValueByKey('CREDITS_REWARD_AFTER_VERIFY_EMAIL')." additional " . Configuration::getValueByKey('CREDITS_DISPLAY_NAME') . ".
"; + } + if(Configuration::getValueByKey('SERVER_LIMIT_REWARD_AFTER_VERIFY_EMAIL') != 0) { + $AdditionalLine .= "Verifying your e-mail will also increase your Server Limit by " . Configuration::getValueByKey('SERVER_LIMIT_REWARD_AFTER_VERIFY_EMAIL') . ".
"; + } + $AdditionalLine .="
"; + if(Configuration::getValueByKey('CREDITS_REWARD_AFTER_VERIFY_DISCORD') != 0) { + $AdditionalLine .= "You can also verify your discord account to get another " . Configuration::getValueByKey('CREDITS_REWARD_AFTER_VERIFY_DISCORD') . " " . Configuration::getValueByKey('CREDITS_DISPLAY_NAME') . ".
"; + } + if(Configuration::getValueByKey('SERVER_LIMIT_REWARD_AFTER_VERIFY_DISCORD') != 0) { + $AdditionalLine .= "Verifying your Discord account will also increase your Server Limit by " . Configuration::getValueByKey('SERVER_LIMIT_REWARD_AFTER_VERIFY_DISCORD') . ".
"; + } + + return $AdditionalLine; + } /** * Get the array representation of the notification. * @@ -51,7 +70,10 @@ class WelcomeMessage extends Notification implements ShouldQueue 'content' => "

Hello {$this->user->name}, Welcome to our dashboard!

Verification
-

Please verify your email address to get " . Configuration::getValueByKey('CREDITS_REWARD_AFTER_VERIFY_EMAIL') . " extra credits and increase your server limit to " . Configuration::getValueByKey('SERVER_LIMIT_REWARD_AFTER_VERIFY_EMAIL') . "
You can also verify your discord account to get another " . Configuration::getValueByKey('CREDITS_REWARD_AFTER_VERIFY_DISCORD') . " credits and to increase your server limit again with " . Configuration::getValueByKey('SERVER_LIMIT_REWARD_AFTER_VERIFY_DISCORD') . "

+

You can verify your e-mail address and link/verify your Discord account.

+

+ ".$this->AdditionalLines()." +

Information

This dashboard can be used to create and delete servers.
These servers can be used and managed on our pterodactyl panel.
If you have any questions, please join our Discord server and #create-a-ticket.

We hope you can enjoy this hosting experience and if you have any suggestions please let us know!

diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 8aa705e0..189f64bf 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -29,7 +29,6 @@ class AppServiceProvider extends ServiceProvider { Paginator::useBootstrap(); Schema::defaultStringLength(191); - QueryBuilderRequest::setArrayValueDelimiter('|'); Validator::extend('multiple_date_format', function ($attribute, $value, $parameters, $validator) { diff --git a/composer.json b/composer.json index 3edec1b4..50dc100a 100644 --- a/composer.json +++ b/composer.json @@ -23,7 +23,7 @@ "paypal/rest-api-sdk-php": "^1.14", "socialiteproviders/discord": "^4.1", "spatie/laravel-activitylog": "^3.16", - "spatie/laravel-query-builder": "^3.5", + "spatie/laravel-query-builder": "^3.6", "spatie/laravel-validation-rules": "^3.0", "yajra/laravel-datatables-oracle": "~9.0" }, diff --git a/composer.lock b/composer.lock index 14abe8de..0ff1f168 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "b3b61a46d5d4d6560d052cfda863d12c", + "content-hash": "f7ba581ff6641d3ab79d558070e99f3c", "packages": [ { "name": "asm89/stack-cors", @@ -3462,16 +3462,16 @@ }, { "name": "spatie/laravel-query-builder", - "version": "3.5.0", + "version": "3.6.0", "source": { "type": "git", "url": "https://github.com/spatie/laravel-query-builder.git", - "reference": "4e5257be24139836dc092f618d7c73bcb1c00302" + "reference": "03d8e1307dcb58b16fcc9c4947633fc60ae74802" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-query-builder/zipball/4e5257be24139836dc092f618d7c73bcb1c00302", - "reference": "4e5257be24139836dc092f618d7c73bcb1c00302", + "url": "https://api.github.com/repos/spatie/laravel-query-builder/zipball/03d8e1307dcb58b16fcc9c4947633fc60ae74802", + "reference": "03d8e1307dcb58b16fcc9c4947633fc60ae74802", "shasum": "" }, "require": { @@ -3528,7 +3528,7 @@ "type": "custom" } ], - "time": "2021-07-05T14:17:44+00:00" + "time": "2021-09-06T08:03:10+00:00" }, { "name": "spatie/laravel-validation-rules", @@ -8713,5 +8713,5 @@ "ext-intl": "*" }, "platform-dev": [], - "plugin-api-version": "2.0.0" + "plugin-api-version": "2.1.0" } diff --git a/config/app.php b/config/app.php index 592e97d2..bcb46c44 100644 --- a/config/app.php +++ b/config/app.php @@ -2,7 +2,7 @@ return [ - 'version' => '0.5', + 'version' => '0.6', /* |-------------------------------------------------------------------------- | Application Name diff --git a/config/query-builder.php b/config/query-builder.php new file mode 100644 index 00000000..e9f81270 --- /dev/null +++ b/config/query-builder.php @@ -0,0 +1,46 @@ + [ + 'include' => 'include', + + 'filter' => 'filter', + + 'sort' => 'sort', + + 'fields' => 'fields', + + 'append' => 'append', + ], + + /* + * Related model counts are included using the relationship name suffixed with this string. + * For example: GET /users?include=postsCount + */ + 'count_suffix' => 'Count', + + /* + * By default the package will throw an `InvalidFilterQuery` exception when a filter in the + * URL is not allowed in the `allowedFilters()` method. + */ + 'disable_invalid_filter_query_exception' => false, + + /* + * By default the package inspects query string of request using $request->query(). + * You can change this behavior to inspect the request body using $request->input() + * by setting this value to `body`. + * + * Possible values: `query_string`, `body` + */ + 'request_data_source' => 'query_string', +]; diff --git a/database/migrations/2021_09_26_150114_add_suspended_to_users_table.php b/database/migrations/2021_09_26_150114_add_suspended_to_users_table.php new file mode 100644 index 00000000..f3b83a55 --- /dev/null +++ b/database/migrations/2021_09_26_150114_add_suspended_to_users_table.php @@ -0,0 +1,32 @@ +boolean('suspended')->default(false); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('users', function (Blueprint $table) { + $table->dropColumn('suspended'); + }); + } +} diff --git a/database/migrations/2021_10_01_200844_add_product_minimum_credits.php b/database/migrations/2021_10_01_200844_add_product_minimum_credits.php new file mode 100644 index 00000000..162b52e8 --- /dev/null +++ b/database/migrations/2021_10_01_200844_add_product_minimum_credits.php @@ -0,0 +1,32 @@ +float('minimum_credits')->default(-1); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('products', function (Blueprint $table) { + $table->dropColumn('minimum_credits'); + }); + } +} diff --git a/resources/views/admin/activitylogs/index.blade.php b/resources/views/admin/activitylogs/index.blade.php index e3cc7946..978e8c9c 100644 --- a/resources/views/admin/activitylogs/index.blade.php +++ b/resources/views/admin/activitylogs/index.blade.php @@ -71,7 +71,10 @@ @foreach($logs as $log) - {{$log->causer ? json_decode($log->causer)->name : 'system'}} + @if($log->causer) {{json_decode($log->causer)->name}} + @else + System + @endif @switch($log->description) @@ -90,6 +93,18 @@ @endswitch {{ucfirst($log->description)}} {{ explode("\\" , $log->subject_type)[2]}} + @php $first=true @endphp + @foreach(json_decode($log->properties, true) as $properties) + @if($first) + @if(isset($properties['name'])) + " {{$properties['name']}} " + @endif + @if(isset($properties['email'])) + < {{$properties['email']}} > + @endif + @php $first=false @endphp + @endif + @endforeach diff --git a/resources/views/admin/configurations/editModel.blade.php b/resources/views/admin/configurations/editModel.blade.php index 74373383..b040c2f0 100644 --- a/resources/views/admin/configurations/editModel.blade.php +++ b/resources/views/admin/configurations/editModel.blade.php @@ -22,7 +22,6 @@ - @@ -37,16 +36,26 @@ - @endsection diff --git a/resources/views/admin/products/edit.blade.php b/resources/views/admin/products/edit.blade.php index 5b9b1a3f..dd66ae36 100644 --- a/resources/views/admin/products/edit.blade.php +++ b/resources/views/admin/products/edit.blade.php @@ -10,9 +10,10 @@
@@ -29,22 +30,28 @@
- @if($product->servers()->count() > 0) + @if ($product->servers()->count() > 0)
-

Editing the resource options will not automatically update the servers on pterodactyl's side!

-

Automatically updating resource options on pterodactyl side is on my todo list :)

+

Editing the resource options will not automatically update the servers on pterodactyl's + side!

+

Automatically updating resource options on pterodactyl side is on my + todo list :)

@endif
-
+ @csrf @method('PATCH')
- disabled) checked @endif name="disabled" class="custom-control-input custom-control-input-danger" id="switch1"> - + disabled) checked @endif name="disabled" + class="custom-control-input custom-control-input-danger" id="switch1"> +
@@ -52,78 +59,74 @@
- + @error('name') -
- {{$message}} -
+
+ {{ $message }} +
@enderror
- - + + @error('price') -
- {{$message}} -
+
+ {{ $message }} +
@enderror
- + @error('memory') -
- {{$message}} -
+
+ {{ $message }} +
@enderror
- + @error('cpu') -
- {{$message}} -
+
+ {{ $message }} +
@enderror
- + @error('swap') -
- {{$message}} -
+
+ {{ $message }} +
@enderror
- - + + @error('description') -
- {{$message}} -
+
+ {{ $message }} +
@enderror
@@ -131,65 +134,72 @@
- + @error('disk') -
- {{$message}} -
+
+ {{ $message }} +
+ @enderror +
+
+ + + @error('minimum_credits') +
+ {{ $message }} +
@enderror
- + @error('io') -
- {{$message}} -
+
+ {{ $message }} +
@enderror
- + @error('databases') -
- {{$message}} -
+
+ {{ $message }} +
@enderror
- + @error('backups') -
- {{$message}} -
+
+ {{ $message }} +
@enderror
- + @error('allocations') -
- {{$message}} -
+
+ {{ $message }} +
@enderror
@@ -210,6 +220,11 @@ + @endsection diff --git a/resources/views/admin/products/show.blade.php b/resources/views/admin/products/show.blade.php index 46d13b5d..62e6ed79 100644 --- a/resources/views/admin/products/show.blade.php +++ b/resources/views/admin/products/show.blade.php @@ -10,10 +10,10 @@
@@ -30,11 +30,15 @@
Product
- - + + {{ csrf_field() }} - {{ method_field("DELETE") }} - + {{ method_field('DELETE') }} +
@@ -47,9 +51,9 @@
- - {{$product->id}} - + + {{ $product->id }} +
@@ -60,9 +64,9 @@
- - {{$product->name}} - + + {{ $product->name }} +
@@ -73,9 +77,26 @@
- - {{$product->price}} - + + {{ $product->price }} + +
+ + + +
+
+
+ +
+
+ + @if ($product->minimum_credits == -1) + {{ $minimum_credits }} + @else + {{ $product->minimum_credits }} + @endif +
@@ -87,9 +108,9 @@
- - {{$product->memory}} - + + {{ $product->memory }} +
@@ -100,9 +121,9 @@
- - {{$product->cpu}} - + + {{ $product->cpu }} +
@@ -113,9 +134,9 @@
- - {{$product->swap}} - + + {{ $product->swap }} +
@@ -126,9 +147,9 @@
- - {{$product->disk}} - + + {{ $product->disk }} +
@@ -139,9 +160,9 @@
- - {{$product->io}} - + + {{ $product->io }} +
@@ -152,9 +173,9 @@
- - {{$product->databases}} - + + {{ $product->databases }} +
@@ -165,9 +186,9 @@
- - {{$product->allocations}} - + + {{ $product->allocations }} +
@@ -178,9 +199,9 @@
- - {{$product->created_at ? $product->created_at->diffForHumans() : ''}} - + + {{ $product->created_at ? $product->created_at->diffForHumans() : '' }} +
@@ -192,9 +213,9 @@
- - {{$product->description}} - + + {{ $product->description }} +
@@ -206,9 +227,9 @@
- - {{$product->updated_at ? $product->updated_at->diffForHumans() : ''}} - + + {{ $product->updated_at ? $product->updated_at->diffForHumans() : '' }} +
diff --git a/resources/views/admin/vouchers/show.blade.php b/resources/views/admin/vouchers/show.blade.php deleted file mode 100644 index 46d13b5d..00000000 --- a/resources/views/admin/vouchers/show.blade.php +++ /dev/null @@ -1,240 +0,0 @@ -@extends('layouts.main') - -@section('content') - -
-
-
-
-

Products

-
-
- -
-
-
-
- - - -
-
- -
-
-
Product
-
- -
- {{ csrf_field() }} - {{ method_field("DELETE") }} - -
-
-
-
-
- -
-
-
- -
-
- - {{$product->id}} - -
-
-
- -
-
-
- -
-
- - {{$product->name}} - -
-
-
- -
-
-
- -
-
- - {{$product->price}} - -
-
-
- - -
-
-
- -
-
- - {{$product->memory}} - -
-
-
- -
-
-
- -
-
- - {{$product->cpu}} - -
-
-
- -
-
-
- -
-
- - {{$product->swap}} - -
-
-
- -
-
-
- -
-
- - {{$product->disk}} - -
-
-
- -
-
-
- -
-
- - {{$product->io}} - -
-
-
- -
-
-
- -
-
- - {{$product->databases}} - -
-
-
- -
-
-
- -
-
- - {{$product->allocations}} - -
-
-
- -
-
-
- -
-
- - {{$product->created_at ? $product->created_at->diffForHumans() : ''}} - -
-
-
- - -
-
-
- -
-
- - {{$product->description}} - -
-
-
- - -
-
-
- -
-
- - {{$product->updated_at ? $product->updated_at->diffForHumans() : ''}} - -
-
-
- -
-
-
- -
-
-
Servers
-
-
- - @include('admin.servers.table' , ['filter' => '?product=' . $product->id]) - -
-
- - -
- - -
- - - - -@endsection diff --git a/resources/views/admin/vouchers/users.blade.php b/resources/views/admin/vouchers/users.blade.php new file mode 100644 index 00000000..bb5ed322 --- /dev/null +++ b/resources/views/admin/vouchers/users.blade.php @@ -0,0 +1,93 @@ +@extends('layouts.main') + +@section('content') + +
+
+
+
+

Vouchers

+
+
+ +
+
+
+
+ + + +
+
+ +
+ +
+
+
Users
+
+
+ +
+ + + + + + + + + + + + + +
IDNameEmail{{ CREDITS_DISPLAY_NAME }}Last Seen
+ +
+
+ + +
+ + +
+ + + + + + +@endsection diff --git a/resources/views/auth/login.blade.php b/resources/views/auth/login.blade.php index 420d1b85..b2f4eba6 100644 --- a/resources/views/auth/login.blade.php +++ b/resources/views/auth/login.blade.php @@ -11,6 +11,10 @@

Sign in to start your session

+ @if (session('message')) +
{{ session('message') }}
+ @endif +
@csrf @if(Session::has('error')) diff --git a/resources/views/home.blade.php b/resources/views/home.blade.php index 5c13ea05..ee44e0e4 100644 --- a/resources/views/home.blade.php +++ b/resources/views/home.blade.php @@ -38,7 +38,7 @@
- +
{{CREDITS_DISPLAY_NAME}} @@ -65,11 +65,28 @@
+ + + @if($credits > 0.01 and $useage > 0) +
+
+ + +
+ Out of {{CREDITS_DISPLAY_NAME}} in + {{$boxText}}{{$unit}} +
+
+ + @endif +
+ +
diff --git a/resources/views/mail/payment/confirmed.blade.php b/resources/views/mail/payment/confirmed.blade.php index 9e79855f..e8a30931 100644 --- a/resources/views/mail/payment/confirmed.blade.php +++ b/resources/views/mail/payment/confirmed.blade.php @@ -1,16 +1,16 @@ @component('mail::message') # Thank you for your purchase! -Your payment has been confirmed; Your credit balance has been updated. +Your payment has been confirmed; Your credit balance has been updated.
# Details ___ -### Payment ID: **{{$payment->id}}** -### Status: **{{$payment->status}}** -### Price: **{{$payment->formatCurrency()}}** -### Type: **{{$payment->type}}** -### Amount: **{{$payment->amount}}** -### Balance: **{{$payment->user->credits}}** -### User ID: **{{$payment->user_id}}** +### Payment ID: **{{$payment->id}}**
+### Status: **{{$payment->status}}**
+### Price: **{{$payment->formatCurrency()}}**
+### Type: **{{$payment->type}}**
+### Amount: **{{$payment->amount}}**
+### Balance: **{{$payment->user->credits}}**
+### User ID: **{{$payment->user_id}}**

Thanks,
diff --git a/resources/views/profile/index.blade.php b/resources/views/profile/index.blade.php index 88a6c0b5..75f2d1a0 100644 --- a/resources/views/profile/index.blade.php +++ b/resources/views/profile/index.blade.php @@ -213,6 +213,23 @@

You are verified!

+
+
+
+
+

{{$user->discordUser->username}} {{$user->discordUser->locale}}

+

{{$user->discordUser->id}} +

+
+
avatar
+
+ +
+
@endif
diff --git a/resources/views/servers/create.blade.php b/resources/views/servers/create.blade.php index 18bc00eb..a0431843 100644 --- a/resources/views/servers/create.blade.php +++ b/resources/views/servers/create.blade.php @@ -10,9 +10,10 @@
@@ -32,29 +33,29 @@
Create Server
- + @csrf
+ class="form-control @error('name') is-invalid @enderror"> @error('name') -
- Please fill out this field. -
+
+ Please fill out this field. +
@enderror
+ class="form-control @error('description') is-invalid @enderror"> @error('description') -
- Please fill out this field. -
+
+ Please fill out this field. +
@enderror
@@ -63,13 +64,13 @@
- @foreach($nests as $nest) - - @foreach($nest->eggs as $egg) - + class="custom-select @error('egg_id') is-invalid @enderror"> + + @foreach ($nests as $nest) + + @foreach ($nest->eggs as $egg) + @endforeach @endforeach @@ -100,32 +102,40 @@
@error('egg_id') -
- Please fill out this field. -
+
+ Please fill out this field. +
@enderror
@error('product_id') -
- Please fill out this field. -
+
+ Please fill out this field. +
@enderror
- +
diff --git a/resources/views/servers/index.blade.php b/resources/views/servers/index.blade.php index a8dd29e3..acef35ef 100644 --- a/resources/views/servers/index.blade.php +++ b/resources/views/servers/index.blade.php @@ -83,6 +83,14 @@ Backups {{$server->product->backups}} + + Price per Hour + {{number_format($server->product->getHourlyPrice(),2,".", "")}} {{CREDITS_DISPLAY_NAME}} + + + Price per Month + {{$server->product->getHourlyPrice()*24*30}} {{CREDITS_DISPLAY_NAME}} + diff --git a/resources/views/store/checkout.blade.php b/resources/views/store/checkout.blade.php index 8355da4e..d6401374 100644 --- a/resources/views/store/checkout.blade.php +++ b/resources/views/store/checkout.blade.php @@ -42,7 +42,7 @@
- From + To
{{config('app.name' , 'Laravel')}}
Email: {{env('PAYPAL_EMAIL' , env('MAIL_FROM_NAME'))}} @@ -50,7 +50,7 @@
- To + From
{{Auth::user()->name}}
Email: {{Auth::user()->email}} diff --git a/routes/api.php b/routes/api.php index c964be38..bf9bc7d0 100644 --- a/routes/api.php +++ b/routes/api.php @@ -20,7 +20,7 @@ use Illuminate\Support\Facades\Route; Route::middleware('api.token')->group(function () { Route::patch('/users/{user}/increment', [UserController::class, 'increment']); Route::patch('/users/{user}/decrement', [UserController::class, 'decrement']); - Route::resource('users', UserController::class)->except(['store', 'create']); + Route::resource('users', UserController::class)->except(['create']); Route::patch('/servers/{server}/suspend', [ServerController::class, 'suspend']); Route::patch('/servers/{server}/unsuspend', [ServerController::class, 'unSuspend']); diff --git a/routes/web.php b/routes/web.php index 2fad20da..ae1fa78a 100644 --- a/routes/web.php +++ b/routes/web.php @@ -40,7 +40,7 @@ Route::middleware('guest')->get('/', function () { Auth::routes(['verify' => true]); -Route::middleware('auth')->group(function () { +Route::middleware(['auth', 'checkSuspended'])->group(function () { #resend verification email Route::get('/email/verification-notification', function (Request $request) { $request->user()->sendEmailVerificationNotification(); @@ -79,6 +79,7 @@ Route::middleware('auth')->group(function () { Route::get('users/datatable', [UserController::class, 'datatable'])->name('users.datatable'); Route::get('users/notifications', [UserController::class, 'notifications'])->name('users.notifications'); Route::post('users/notifications', [UserController::class, 'notify'])->name('users.notifications'); + Route::post('users/togglesuspend/{user}', [UserController::class, 'toggleSuspended'])->name('users.togglesuspend'); Route::resource('users', UserController::class); Route::get('servers/datatable', [AdminServerController::class, 'datatable'])->name('servers.datatable'); @@ -118,6 +119,8 @@ Route::middleware('auth')->group(function () { Route::resource('usefullinks', UsefulLinkController::class); Route::get('vouchers/datatable', [VoucherController::class, 'datatable'])->name('vouchers.datatable'); + Route::get('vouchers/{voucher}/usersdatatable', [VoucherController::class, 'usersdatatable'])->name('vouchers.usersdatatable'); + Route::get('vouchers/{voucher}/users', [VoucherController::class, 'users'])->name('vouchers.users'); Route::resource('vouchers', VoucherController::class); Route::get('api/datatable', [ApplicationApiController::class, 'datatable'])->name('api.datatable');