commit
324a1db621
17 changed files with 91 additions and 32 deletions
14
CHANGELOG.md
14
CHANGELOG.md
|
@ -3,6 +3,20 @@ This file is a running track of new features and fixes to each version of the pa
|
||||||
|
|
||||||
This project follows [Semantic Versioning](http://semver.org) guidelines.
|
This project follows [Semantic Versioning](http://semver.org) guidelines.
|
||||||
|
|
||||||
|
## v0.6.1 (Courageous Carniadactylus)
|
||||||
|
### Fixed
|
||||||
|
* Fixes a bug preventing the use of services that have no variables attached to them.
|
||||||
|
* Fixes 'Remember Me' checkbox being ignored when using 2FA on an account.
|
||||||
|
* API now returns a useful error displaying what went wrong rather than an obscure 'An Error was Encountered' message when API issues arise.
|
||||||
|
* Fixes bug preventing the creation of new files in the file manager due to a missing JS dependency on page load.
|
||||||
|
* Prevent using a service option tag that contains special characters that are not valid. Now only allows alpha-numeric, no spaces or underscores.
|
||||||
|
* Fix unhandled excpetion due to missing `Log` class when using the API and causing an error.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
* Renamed session cookies from `laravel_session` to `pterodactyl_session`.
|
||||||
|
* Sessions are now encrypted before being stored as an additional layer of security.
|
||||||
|
* It is now possible to clear out a server description and have it be blank, rather than throwing an error about the field being required.
|
||||||
|
|
||||||
## v0.6.0 (Courageous Carniadactylus)
|
## v0.6.0 (Courageous Carniadactylus)
|
||||||
### Fixed
|
### Fixed
|
||||||
* Bug causing error logs to be spammed if someone timed out on an ajax based page.
|
* Bug causing error logs to be spammed if someone timed out on an ajax based page.
|
||||||
|
|
|
@ -48,16 +48,16 @@ class Handler extends ExceptionHandler
|
||||||
if ($request->expectsJson() || $request->isJson() || $request->is(...config('pterodactyl.json_routes'))) {
|
if ($request->expectsJson() || $request->isJson() || $request->is(...config('pterodactyl.json_routes'))) {
|
||||||
$exception = $this->prepareException($exception);
|
$exception = $this->prepareException($exception);
|
||||||
|
|
||||||
if (config('app.debug')) {
|
if (config('app.debug') || $this->isHttpException($exception)) {
|
||||||
$report = [
|
$displayError = $exception->getMessage();
|
||||||
'code' => (! $this->isHttpException($exception)) ?: $exception->getStatusCode(),
|
} else {
|
||||||
'message' => class_basename($exception) . ' in ' . $exception->getFile() . ' on line ' . $exception->getLine(),
|
$displayError = 'An unhandled exception was encountered with this request.';
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$response = response()->json([
|
$response = response()->json([
|
||||||
'error' => (config('app.debug')) ? $exception->getMessage() : 'An unhandled exception was encountered with this request.',
|
'error' => $displayError,
|
||||||
'exception' => ! isset($report) ?: $report,
|
'http_code' => (! $this->isHttpException($exception)) ?: $exception->getStatusCode(),
|
||||||
|
'trace' => (! config('app.debug')) ? null : class_basename($exception) . ' in ' . $exception->getFile() . ' on line ' . $exception->getLine(),
|
||||||
], ($this->isHttpException($exception)) ? $exception->getStatusCode() : 500, [], JSON_UNESCAPED_SLASHES);
|
], ($this->isHttpException($exception)) ? $exception->getStatusCode() : 500, [], JSON_UNESCAPED_SLASHES);
|
||||||
|
|
||||||
parent::report($exception);
|
parent::report($exception);
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
namespace Pterodactyl\Http\Controllers\API\Admin;
|
namespace Pterodactyl\Http\Controllers\API\Admin;
|
||||||
|
|
||||||
|
use Log;
|
||||||
use Fractal;
|
use Fractal;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Pterodactyl\Models\Node;
|
use Pterodactyl\Models\Node;
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
namespace Pterodactyl\Http\Controllers\API\Admin;
|
namespace Pterodactyl\Http\Controllers\API\Admin;
|
||||||
|
|
||||||
|
use Log;
|
||||||
use Fractal;
|
use Fractal;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Pterodactyl\Models\Server;
|
use Pterodactyl\Models\Server;
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
namespace Pterodactyl\Http\Controllers\API\Admin;
|
namespace Pterodactyl\Http\Controllers\API\Admin;
|
||||||
|
|
||||||
|
use Log;
|
||||||
use Fractal;
|
use Fractal;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Pterodactyl\Models\User;
|
use Pterodactyl\Models\User;
|
||||||
|
|
|
@ -273,9 +273,12 @@ class ServersController extends Controller
|
||||||
{
|
{
|
||||||
$repo = new ServerRepository;
|
$repo = new ServerRepository;
|
||||||
try {
|
try {
|
||||||
$repo->updateDetails($id, $request->intersect([
|
$repo->updateDetails($id, array_merge(
|
||||||
'owner_id', 'name', 'description', 'reset_token',
|
$request->only('description'),
|
||||||
]));
|
$request->intersect([
|
||||||
|
'owner_id', 'name', 'reset_token',
|
||||||
|
])
|
||||||
|
));
|
||||||
|
|
||||||
Alert::success('Server details were successfully updated.')->flash();
|
Alert::success('Server details were successfully updated.')->flash();
|
||||||
} catch (DisplayValidationException $ex) {
|
} catch (DisplayValidationException $ex) {
|
||||||
|
|
|
@ -134,7 +134,9 @@ class LoginController extends Controller
|
||||||
])),
|
])),
|
||||||
], 5);
|
], 5);
|
||||||
|
|
||||||
return redirect()->route('auth.totp')->with('authentication_token', $token);
|
return redirect()->route('auth.totp')
|
||||||
|
->with('authentication_token', $token)
|
||||||
|
->with('remember', $request->has('remember'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$attempt = Auth::attempt([
|
$attempt = Auth::attempt([
|
||||||
|
@ -167,7 +169,7 @@ class LoginController extends Controller
|
||||||
|
|
||||||
return view('auth.totp', [
|
return view('auth.totp', [
|
||||||
'verify_key' => $token,
|
'verify_key' => $token,
|
||||||
'remember' => $request->has('remember'),
|
'remember' => $request->session()->get('remember'),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,17 @@ class OptionController extends Controller
|
||||||
return sprintf('%s=%s', $item->variable->env_variable, $item->variable_value);
|
return sprintf('%s=%s', $item->variable->env_variable, $item->variable_value);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$mergeInto = [
|
||||||
|
'STARTUP=' . $server->startup,
|
||||||
|
'SERVER_MEMORY=' . $server->memory,
|
||||||
|
'SERVER_IP=' . $server->allocation->ip,
|
||||||
|
'SERVER_PORT=' . $server->allocation->port,
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($environment->count() === 0) {
|
||||||
|
$environment = collect($mergeInto);
|
||||||
|
}
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'scripts' => [
|
'scripts' => [
|
||||||
'install' => (! $server->option->copy_script_install) ? null : str_replace(["\r\n", "\n", "\r"], "\n", $server->option->copy_script_install),
|
'install' => (! $server->option->copy_script_install) ? null : str_replace(["\r\n", "\n", "\r"], "\n", $server->option->copy_script_install),
|
||||||
|
@ -47,12 +58,7 @@ class OptionController extends Controller
|
||||||
'container' => $server->option->copy_script_container,
|
'container' => $server->option->copy_script_container,
|
||||||
'entry' => $server->option->copy_script_entry,
|
'entry' => $server->option->copy_script_entry,
|
||||||
],
|
],
|
||||||
'env' => $environment->merge([
|
'env' => $environment->toArray(),
|
||||||
'STARTUP=' . $server->startup,
|
|
||||||
'SERVER_MEMORY=' . $server->memory,
|
|
||||||
'SERVER_IP=' . $server->allocation->ip,
|
|
||||||
'SERVER_PORT=' . $server->allocation->port,
|
|
||||||
])->toArray(),
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ class OptionRepository
|
||||||
'service_id' => 'required|numeric|exists:services,id',
|
'service_id' => 'required|numeric|exists:services,id',
|
||||||
'name' => 'required|string|max:255',
|
'name' => 'required|string|max:255',
|
||||||
'description' => 'required|string',
|
'description' => 'required|string',
|
||||||
'tag' => 'required|string|max:255|unique:service_options,tag',
|
'tag' => 'required|alpha_num|max:60|unique:service_options,tag',
|
||||||
'docker_image' => 'sometimes|string|max:255',
|
'docker_image' => 'sometimes|string|max:255',
|
||||||
'startup' => 'sometimes|nullable|string',
|
'startup' => 'sometimes|nullable|string',
|
||||||
'config_from' => 'sometimes|required|numeric|exists:service_options,id',
|
'config_from' => 'sometimes|required|numeric|exists:service_options,id',
|
||||||
|
|
|
@ -370,7 +370,7 @@ class ServerRepository
|
||||||
$validator = Validator::make($data, [
|
$validator = Validator::make($data, [
|
||||||
'owner_id' => 'sometimes|required|integer|exists:users,id',
|
'owner_id' => 'sometimes|required|integer|exists:users,id',
|
||||||
'name' => 'sometimes|required|regex:([\w .-]{1,200})',
|
'name' => 'sometimes|required|regex:([\w .-]{1,200})',
|
||||||
'description' => 'sometimes|required|string',
|
'description' => 'sometimes|nullable|string',
|
||||||
'reset_token' => 'sometimes|required|accepted',
|
'reset_token' => 'sometimes|required|accepted',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -733,6 +733,10 @@ class ServerRepository
|
||||||
$i++;
|
$i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($parsed->count() === 0) {
|
||||||
|
return collect($merge);
|
||||||
|
}
|
||||||
|
|
||||||
return $parsed->merge($merge);
|
return $parsed->merge($merge);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ return [
|
||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'encrypt' => false,
|
'encrypt' => true,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
|
@ -122,7 +122,7 @@ return [
|
||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'cookie' => 'laravel_session',
|
'cookie' => 'pterodactyl_session',
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
|
|
||||||
.login-box, .register-box {
|
.login-box, .register-box {
|
||||||
width: 40%;
|
width: 40%;
|
||||||
|
max-width: 500px;
|
||||||
margin: 7% auto;
|
margin: 7% auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,3 +304,10 @@ input.form-autocomplete-stop[readonly] {
|
||||||
background: inherit;
|
background: inherit;
|
||||||
cursor: text;
|
cursor: text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* fix Google Recaptcha badge */
|
||||||
|
.grecaptcha-badge {
|
||||||
|
bottom: 54px !important;
|
||||||
|
background: white;
|
||||||
|
box-shadow: none !important;
|
||||||
|
}
|
||||||
|
|
|
@ -62,10 +62,14 @@
|
||||||
<p>This will reinstall the server with the assigned pack and service scripts. <strong>Danger!</strong> This could overwrite server data.</p>
|
<p>This will reinstall the server with the assigned pack and service scripts. <strong>Danger!</strong> This could overwrite server data.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="box-footer">
|
<div class="box-footer">
|
||||||
<form action="{{ route('admin.servers.view.manage.reinstall', $server->id) }}" method="POST">
|
@if($server->installed)
|
||||||
{!! csrf_field() !!}
|
<form action="{{ route('admin.servers.view.manage.reinstall', $server->id) }}" method="POST">
|
||||||
<button type="submit" class="btn btn-danger">Reinstall Server</button>
|
{!! csrf_field() !!}
|
||||||
</form>
|
<button type="submit" class="btn btn-danger">Reinstall Server</button>
|
||||||
|
</form>
|
||||||
|
@else
|
||||||
|
<button class="btn btn-danger disabled">Reinstall Server</button>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -66,7 +66,7 @@
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="pTag" class="form-label">Option Tag</label>
|
<label for="pTag" class="form-label">Option Tag</label>
|
||||||
<input type="text" id="pTag" name="tag" value="{{ old('tag') }}" class="form-control" />
|
<input type="text" id="pTag" name="tag" value="{{ old('tag') }}" class="form-control" />
|
||||||
<p class="text-muted small">This should be a unique identifer for this service option that is not used for any other service options.</p>
|
<p class="text-muted small">This should be a unique identifer for this service option that is not used for any other service options. Must be alpha-numeric and no more than 60 characters in length.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="pDockerImage" class="form-label">Docker Image</label>
|
<label for="pDockerImage" class="form-label">Docker Image</label>
|
||||||
|
|
|
@ -47,6 +47,11 @@
|
||||||
</div>
|
</div>
|
||||||
<form action="{{ route('admin.services.option.view', $option->id) }}" method="POST">
|
<form action="{{ route('admin.services.option.view', $option->id) }}" method="POST">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
<div class="col-xs-12">
|
||||||
|
<div class="callout callout-info">
|
||||||
|
<strong>Notice:</strong> Editing the Option Tag or any of the Process Management fields <em>requires</em> that each daemon be rebooted to apply the changes.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="col-xs-12">
|
<div class="col-xs-12">
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<div class="box-header with-border">
|
<div class="box-header with-border">
|
||||||
|
|
|
@ -23,20 +23,29 @@
|
||||||
2FA Checkpoint
|
2FA Checkpoint
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
|
@section('scripts')
|
||||||
|
@parent
|
||||||
|
<style>
|
||||||
|
input::-webkit-outer-spin-button, input::-webkit-inner-spin-button {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
@endsection
|
||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
<div class="login-box-body">
|
<div class="login-box-body">
|
||||||
<p class="login-box-msg">@lang('auth.2fa_required')</p>
|
|
||||||
<form action="{{ route('auth.totp') }}" method="POST">
|
<form action="{{ route('auth.totp') }}" method="POST">
|
||||||
<div class="form-group">
|
<div class="form-group has-feedback">
|
||||||
<input type="text" name="2fa_token" class="form-control" placeholder="@lang('strings.2fa_token')">
|
<input type="number" name="2fa_token" class="form-control input-lg text-center" placeholder="@lang('strings.2fa_token')" autofocus>
|
||||||
<span class="fa fa-lock form-control-feedback"></span>
|
<span class="fa fa-shield form-control-feedback"></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xs-12">
|
<div class="col-xs-12">
|
||||||
{!! csrf_field() !!}
|
{!! csrf_field() !!}
|
||||||
<input type="hidden" name="verify_token" value="{{ $verify_key }}" />
|
<input type="hidden" name="verify_token" value="{{ $verify_key }}" />
|
||||||
@if($remember)
|
@if($remember)
|
||||||
<input type="hidden" name="remember" value="true" />
|
<input type="checkbox" name="remember" checked style="display:none;"/>
|
||||||
@endif
|
@endif
|
||||||
<button type="submit" class="btn btn-primary btn-block btn-flat">@lang('strings.submit')</button>
|
<button type="submit" class="btn btn-primary btn-block btn-flat">@lang('strings.submit')</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -101,6 +101,7 @@
|
||||||
{!! Theme::js('js/frontend/server.socket.js') !!}
|
{!! Theme::js('js/frontend/server.socket.js') !!}
|
||||||
{!! Theme::js('vendor/ace/ace.js') !!}
|
{!! Theme::js('vendor/ace/ace.js') !!}
|
||||||
{!! Theme::js('vendor/ace/ext-modelist.js') !!}
|
{!! Theme::js('vendor/ace/ext-modelist.js') !!}
|
||||||
|
{!! Theme::js('vendor/ace/ext-whitespace.js') !!}
|
||||||
{!! Theme::js('vendor/lodash/lodash.js') !!}
|
{!! Theme::js('vendor/lodash/lodash.js') !!}
|
||||||
{!! Theme::js('js/frontend/files/editor.js') !!}
|
{!! Theme::js('js/frontend/files/editor.js') !!}
|
||||||
<script>
|
<script>
|
||||||
|
|
Loading…
Reference in a new issue