Merge branch 'development' into feature/extendable_payment_gateways
This commit is contained in:
commit
c468e53fad
13 changed files with 44 additions and 32 deletions
|
@ -4,13 +4,13 @@
|
||||||
- Stripe Integration
|
- Stripe Integration
|
||||||
- Referral System
|
- Referral System
|
||||||
- Ticket System
|
- Ticket System
|
||||||
- Upgrade/Downgrade Server Ressources
|
- Upgrade/Downgrade Server Resources
|
||||||
- Store (credit system with hourly billing and invoices)
|
- Store (credit system with hourly billing and invoices)
|
||||||
- Email Verification
|
- Email Verification
|
||||||
- Audit Log
|
- Audit Log
|
||||||
- Admin Dashboard
|
- Admin Dashboard
|
||||||
- User/Server Management
|
- User/Server Management
|
||||||
- Customizable server plans
|
- Customisable server plans
|
||||||
- Vouchers
|
- Vouchers
|
||||||
- and so much more!
|
- and so much more!
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
namespace App\Http\Controllers\Auth;
|
namespace App\Http\Controllers\Auth;
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Models\User;
|
|
||||||
use App\Providers\RouteServiceProvider;
|
use App\Providers\RouteServiceProvider;
|
||||||
use Illuminate\Foundation\Auth\AuthenticatesUsers;
|
use Illuminate\Foundation\Auth\AuthenticatesUsers;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
|
|
@ -12,7 +12,6 @@ use Illuminate\Foundation\Auth\RegistersUsers;
|
||||||
use Illuminate\Support\Facades\App;
|
use Illuminate\Support\Facades\App;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Hash;
|
use Illuminate\Support\Facades\Hash;
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
use Illuminate\Support\Facades\Validator;
|
use Illuminate\Support\Facades\Validator;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
use Illuminate\Validation\ValidationException;
|
use Illuminate\Validation\ValidationException;
|
||||||
|
|
|
@ -9,7 +9,6 @@ use App\Models\Nest;
|
||||||
use App\Models\Node;
|
use App\Models\Node;
|
||||||
use App\Models\Product;
|
use App\Models\Product;
|
||||||
use App\Models\Server;
|
use App\Models\Server;
|
||||||
use App\Models\Settings;
|
|
||||||
use App\Notifications\ServerCreationError;
|
use App\Notifications\ServerCreationError;
|
||||||
use Exception;
|
use Exception;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
|
|
@ -11,7 +11,6 @@ use App\Listeners\Verified;
|
||||||
use Illuminate\Auth\Events\Registered;
|
use Illuminate\Auth\Events\Registered;
|
||||||
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
|
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
|
||||||
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
|
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
|
||||||
use Illuminate\Support\Facades\Event;
|
|
||||||
use SocialiteProviders\Manager\SocialiteWasCalled;
|
use SocialiteProviders\Manager\SocialiteWasCalled;
|
||||||
|
|
||||||
class EventServiceProvider extends ServiceProvider
|
class EventServiceProvider extends ServiceProvider
|
||||||
|
|
|
@ -22,7 +22,6 @@ class UserFactory extends Factory
|
||||||
'email_verified_at' => $this->faker->dateTimeBetween('-30 days', now()),
|
'email_verified_at' => $this->faker->dateTimeBetween('-30 days', now()),
|
||||||
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
|
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
|
||||||
'remember_token' => Str::random(10),
|
'remember_token' => Str::random(10),
|
||||||
'email_verified' => true,
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -324,7 +324,7 @@
|
||||||
"System": "System",
|
"System": "System",
|
||||||
"Show Terms of Service": "Show Terms of Service",
|
"Show Terms of Service": "Show Terms of Service",
|
||||||
"Show the TOS link in the footer of every page. <br> Edit the content in \"resources\/views\/information\/tos-content.blade.php\"": "Show the TOS link in the footer of every page. <br> Edit the content in \"resources\/views\/information\/tos-content.blade.php\"",
|
"Show the TOS link in the footer of every page. <br> Edit the content in \"resources\/views\/information\/tos-content.blade.php\"": "Show the TOS link in the footer of every page. <br> Edit the content in \"resources\/views\/information\/tos-content.blade.php\"",
|
||||||
"Show imprint": "Show imprint",
|
"Show Imprint": "Show Imprint",
|
||||||
"Show the imprint link in the footer of every page. <br> Edit the content in \"resources\/views\/information\/imprint-content.blade.php\"": "Show the imprint link in the footer of every page. <br> Edit the content in \"resources\/views\/information\/imprint-content.blade.php\"",
|
"Show the imprint link in the footer of every page. <br> Edit the content in \"resources\/views\/information\/imprint-content.blade.php\"": "Show the imprint link in the footer of every page. <br> Edit the content in \"resources\/views\/information\/imprint-content.blade.php\"",
|
||||||
"Show Privacy Policy": "Show Privacy Policy",
|
"Show Privacy Policy": "Show Privacy Policy",
|
||||||
"Show the privacy policy link in the footer of every page. <br> Edit the content in \"resources\/views\/information\/privacy-content.blade.php\"": "Show the privacy policy link in the footer of every page. <br> Edit the content in \"resources\/views\/information\/privacy-content.blade.php\"",
|
"Show the privacy policy link in the footer of every page. <br> Edit the content in \"resources\/views\/information\/privacy-content.blade.php\"": "Show the privacy policy link in the footer of every page. <br> Edit the content in \"resources\/views\/information\/privacy-content.blade.php\"",
|
||||||
|
@ -535,6 +535,7 @@
|
||||||
"MB": "MB",
|
"MB": "MB",
|
||||||
"MySQL": "MySQL",
|
"MySQL": "MySQL",
|
||||||
"ports": "ports",
|
"ports": "ports",
|
||||||
|
"to create this server": "to create this server",
|
||||||
"Server can´t fit on this node": "Server can´t fit on this node",
|
"Server can´t fit on this node": "Server can´t fit on this node",
|
||||||
"Not enough": "Not enough",
|
"Not enough": "Not enough",
|
||||||
"Create server": "Create server",
|
"Create server": "Create server",
|
||||||
|
|
|
@ -4,7 +4,7 @@ $required_extentions = ['openssl', 'gd', 'mysql', 'PDO', 'mbstring', 'tokenizer'
|
||||||
|
|
||||||
$requirements = [
|
$requirements = [
|
||||||
'minPhp' => '8.1',
|
'minPhp' => '8.1',
|
||||||
'maxPhp' => '8.1.9', // This version is not supported
|
'maxPhp' => '8.2', // This version is not supported
|
||||||
'mysql' => '5.7.22',
|
'mysql' => '5.7.22',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@
|
||||||
|
|
||||||
<div class="info-box-content">
|
<div class="info-box-content">
|
||||||
<span class="info-box-text">{{__('Servers')}}</span>
|
<span class="info-box-text">{{__('Servers')}}</span>
|
||||||
<span class="info-box-number">{{$counters['servers']->total}}</span>
|
<span class="info-box-number">{{$counters['servers']->active}}/{{$counters['servers']->total}}</span>
|
||||||
</div>
|
</div>
|
||||||
<!-- /.info-box-content -->
|
<!-- /.info-box-content -->
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -58,7 +58,7 @@
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="partner_discount">{{__('Partner discount')}}
|
<label for="partner_discount">{{__('Partner discount')}}
|
||||||
<i data-toggle="popover" data-trigger="hover"
|
<i data-toggle="popover" data-trigger="hover"
|
||||||
data-content="{{__('The discount in percent given to the partner at checkout.')}}"
|
data-content="{{__('The discount in percent given to the partner when purchasing credits.')}}"
|
||||||
class="fas fa-info-circle"></i>
|
class="fas fa-info-circle"></i>
|
||||||
</label>
|
</label>
|
||||||
<input value="{{old('partner_discount')}}" placeholder="{{__('Discount in percent')}}" id="partner_discount" name="partner_discount"
|
<input value="{{old('partner_discount')}}" placeholder="{{__('Discount in percent')}}" id="partner_discount" name="partner_discount"
|
||||||
|
@ -75,7 +75,7 @@
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="registered_user_discount">{{__('Registered user discount')}}
|
<label for="registered_user_discount">{{__('Registered user discount')}}
|
||||||
<i data-toggle="popover" data-trigger="hover"
|
<i data-toggle="popover" data-trigger="hover"
|
||||||
data-content="{{__('The discount in percent given to all users registered using the partners referral link.')}}"
|
data-content="{{__('The discount in percent given to all users registered using the partners referral link when purchasing credits.')}}"
|
||||||
class="fas fa-info-circle"></i>
|
class="fas fa-info-circle"></i>
|
||||||
</label>
|
</label>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
<input value="true" id="show-imprint" name="show-imprint"
|
<input value="true" id="show-imprint" name="show-imprint"
|
||||||
{{ config('SETTINGS::SYSTEM:SHOW_IMPRINT') == 'true' ? 'checked' : '' }}
|
{{ config('SETTINGS::SYSTEM:SHOW_IMPRINT') == 'true' ? 'checked' : '' }}
|
||||||
type="checkbox">
|
type="checkbox">
|
||||||
<label for="show-imprint">{{ __('Show imprint') }} </label>
|
<label for="show-imprint">{{ __('Show Imprint') }} </label>
|
||||||
</div>
|
</div>
|
||||||
<i data-toggle="popover" data-trigger="hover" data-html="true"
|
<i data-toggle="popover" data-trigger="hover" data-html="true"
|
||||||
data-content="{{ __('Show the imprint link in the footer of every page. <br> Edit the content in <b>'.Qirolab\Theme\Theme::path($path = "views").'/resources/views/information/imprint-content.blade.php</b>') }}"
|
data-content="{{ __('Show the imprint link in the footer of every page. <br> Edit the content in <b>'.Qirolab\Theme\Theme::path($path = "views").'/resources/views/information/imprint-content.blade.php</b>') }}"
|
||||||
|
|
|
@ -77,7 +77,7 @@
|
||||||
url: '//cdn.datatables.net/plug-ins/1.11.3/i18n/{{config("SETTINGS::LOCALE:DATATABLES")}}.json'
|
url: '//cdn.datatables.net/plug-ins/1.11.3/i18n/{{config("SETTINGS::LOCALE:DATATABLES")}}.json'
|
||||||
},
|
},
|
||||||
processing: true,
|
processing: true,
|
||||||
serverSide: false, //increases loading times too much? change back to "true" if it does
|
serverSide: true, //why was this set to false before? increased loadingtimes by 10 seconds
|
||||||
stateSave: true,
|
stateSave: true,
|
||||||
ajax: "{{route('admin.users.datatable')}}",
|
ajax: "{{route('admin.users.datatable')}}",
|
||||||
order: [[ 11, "asc" ]],
|
order: [[ 11, "asc" ]],
|
||||||
|
|
|
@ -26,7 +26,8 @@
|
||||||
<section x-data="serverApp()" class="content">
|
<section x-data="serverApp()" class="content">
|
||||||
<div class="container-xxl">
|
<div class="container-xxl">
|
||||||
<!-- FORM -->
|
<!-- FORM -->
|
||||||
<form action="{{ route('servers.store') }}" method="post" class="row justify-content-center">
|
<form action="{{ route('servers.store') }}" x-on:submit="submitClicked = true" method="post"
|
||||||
|
class="row justify-content-center">
|
||||||
@csrf
|
@csrf
|
||||||
<div class="col-xl-6 col-lg-8 col-md-8 col-sm-10">
|
<div class="col-xl-6 col-lg-8 col-md-8 col-sm-10">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
|
@ -34,10 +35,10 @@
|
||||||
<div class="card-title"><i class="fas fa-cogs mr-2"></i>{{ __('Server configuration') }}
|
<div class="card-title"><i class="fas fa-cogs mr-2"></i>{{ __('Server configuration') }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@if (!config("SETTINGS::SYSTEM:CREATION_OF_NEW_SERVERS"))
|
@if (!config('SETTINGS::SYSTEM:CREATION_OF_NEW_SERVERS'))
|
||||||
<div class="alert alert-warning p-2 m-2">
|
<div class="alert alert-warning p-2 m-2">
|
||||||
The creation of new servers has been disabled for regular users, enable it again
|
The creation of new servers has been disabled for regular users, enable it again
|
||||||
<a href="{{route('admin.settings.system')}}">{{ __('here') }}</a>.
|
<a href="{{ route('admin.settings.system') }}">{{ __('here') }}</a>.
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
@if ($productCount === 0 || $nodeCount === 0 || count($nests) === 0 || count($eggs) === 0)
|
@if ($productCount === 0 || $nodeCount === 0 || count($nests) === 0 || count($eggs) === 0)
|
||||||
|
@ -47,7 +48,7 @@
|
||||||
@if (Auth::user()->role == 'admin')
|
@if (Auth::user()->role == 'admin')
|
||||||
{{ __('Make sure to link your products to nodes and eggs.') }} <br>
|
{{ __('Make sure to link your products to nodes and eggs.') }} <br>
|
||||||
{{ __('There has to be at least 1 valid product for server creation') }}
|
{{ __('There has to be at least 1 valid product for server creation') }}
|
||||||
<a href="{{route('admin.overview.sync')}}">{{ __('Sync now') }}</a>
|
<a href="{{ route('admin.overview.sync') }}">{{ __('Sync now') }}</a>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
</p>
|
</p>
|
||||||
|
@ -102,8 +103,8 @@
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="nest">{{ __('Software / Games') }}</label>
|
<label for="nest">{{ __('Software / Games') }}</label>
|
||||||
<select class="custom-select" required name="nest" id="nest" x-model="selectedNest"
|
<select class="custom-select" required name="nest" id="nest"
|
||||||
@change="setEggs();">
|
x-model="selectedNest" @change="setEggs();">
|
||||||
<option selected disabled hidden value="null">
|
<option selected disabled hidden value="null">
|
||||||
{{ count($nests) > 0 ? __('Please select software ...') : __('---') }}
|
{{ count($nests) > 0 ? __('Please select software ...') : __('---') }}
|
||||||
</option>
|
</option>
|
||||||
|
@ -134,8 +135,8 @@
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="node">{{ __('Node') }}</label>
|
<label for="node">{{ __('Node') }}</label>
|
||||||
<select name="node" required id="node" x-model="selectedNode" :disabled="!fetchedLocations"
|
<select name="node" required id="node" x-model="selectedNode"
|
||||||
@change="fetchProducts();" class="custom-select">
|
:disabled="!fetchedLocations" @change="fetchProducts();" class="custom-select">
|
||||||
<option x-text="getNodeInputText()" disabled selected hidden value="null">
|
<option x-text="getNodeInputText()" disabled selected hidden value="null">
|
||||||
</option>
|
</option>
|
||||||
|
|
||||||
|
@ -206,11 +207,19 @@
|
||||||
({{ __('ports') }})</span>
|
({{ __('ports') }})</span>
|
||||||
<span class="d-inline-block" x-text="product.allocations"></span>
|
<span class="d-inline-block" x-text="product.allocations"></span>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="d-flex justify-content-between">
|
||||||
|
<span class="d-inline-block"><i class="fa fa-coins"></i>
|
||||||
|
{{ __('Required') }} {{ CREDITS_DISPLAY_NAME }}
|
||||||
|
{{ __('to create this server') }}</span>
|
||||||
|
<span class="d-inline-block"
|
||||||
|
x-text="product.minimum_credits === -1 ? {{ config('SETTINGS::USER:MINIMUM_REQUIRED_CREDITS_TO_MAKE_SERVER') }} : product.minimum_credit"></span>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-2 mb-2">
|
<div class="mt-2 mb-2">
|
||||||
<span class="card-text text-muted">{{ __('Description') }}</span>
|
<span class="card-text text-muted">{{ __('Description') }}</span>
|
||||||
<p class="card-text" style="white-space:pre-wrap" x-text="product.description"></p>
|
<p class="card-text" style="white-space:pre-wrap"
|
||||||
|
x-text="product.description"></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-auto border rounded border-secondary">
|
<div class="mt-auto border rounded border-secondary">
|
||||||
|
@ -222,13 +231,18 @@
|
||||||
x-text="product.price + ' {{ CREDITS_DISPLAY_NAME }}'"></span>
|
x-text="product.price + ' {{ CREDITS_DISPLAY_NAME }}'"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div x-data="{ buttonDisabled: false }">
|
<div>
|
||||||
<button type="submit" x-model="selectedProduct" name="product"
|
<input type="hidden" name="product" x-model="selectedProduct">
|
||||||
:disabled="product.minimum_credits > user.credits||product.doesNotFit == true"
|
</div>
|
||||||
:class="product.minimum_credits > user.credits ? 'disabled' : ''"
|
<div>
|
||||||
class="btn btn-primary btn-block mt-2" @click="setProduct(product.id)"
|
<button type="submit" x-model="selectedProduct" name="product"
|
||||||
x-text=" product.doesNotFit == true? '{{ __("Server cant fit on this Node") }}' : (product.minimum_credits > user.credits ? '{{ __('Not enough') }} {{ CREDITS_DISPLAY_NAME }}!' : '{{ __('Create server') }}')">
|
:disabled="product.minimum_credits > user.credits || product.doesNotFit == true ||
|
||||||
</button>
|
submitClicked"
|
||||||
|
:class="product.minimum_credits > user.credits || product.doesNotFit == true ||
|
||||||
|
submitClicked ? 'disabled' : ''"
|
||||||
|
class="btn btn-primary btn-block mt-2" @click="setProduct(product.id);"
|
||||||
|
x-text=" product.doesNotFit == true ? '{{ __('Server cant fit on this Node') }}' : (product.minimum_credits > user.credits ? '{{ __('Not enough') }} {{ CREDITS_DISPLAY_NAME }}!' : '{{ __('Create server') }}')">
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -246,7 +260,6 @@
|
||||||
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
function serverApp() {
|
function serverApp() {
|
||||||
return {
|
return {
|
||||||
//loading
|
//loading
|
||||||
|
@ -275,6 +288,8 @@
|
||||||
locations: [],
|
locations: [],
|
||||||
products: [],
|
products: [],
|
||||||
|
|
||||||
|
submitClicked: false,
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description set available eggs based on the selected nest
|
* @description set available eggs based on the selected nest
|
||||||
|
@ -358,7 +373,8 @@
|
||||||
|
|
||||||
this.fetchedProducts = true;
|
this.fetchedProducts = true;
|
||||||
// TODO: Sortable by user chosen property (cpu, ram, disk...)
|
// TODO: Sortable by user chosen property (cpu, ram, disk...)
|
||||||
this.products = response.data.sort((p1, p2) => parseInt(p1.price,10) > parseInt(p2.price,10) && 1 || -1)
|
this.products = response.data.sort((p1, p2) => parseInt(p1.price, 10) > parseInt(p2.price, 10) &&
|
||||||
|
1 || -1)
|
||||||
|
|
||||||
//divide cpu by 100 for each product
|
//divide cpu by 100 for each product
|
||||||
this.products.forEach(product => {
|
this.products.forEach(product => {
|
||||||
|
|
Loading…
Reference in a new issue