Merge branch 'develop' into feature/vuejs
This commit is contained in:
commit
21ffa08d66
54 changed files with 407 additions and 243 deletions
|
@ -11,7 +11,7 @@ server {
|
|||
listen 443 ssl http2;
|
||||
server_name <domain>;
|
||||
|
||||
root /var/www/pterodactyl/public;
|
||||
root /app/public;
|
||||
index index.php;
|
||||
|
||||
access_log /var/log/nginx/pterodactyl.app-access.log;
|
||||
|
@ -49,7 +49,7 @@ server {
|
|||
|
||||
location ~ \.php$ {
|
||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||
fastcgi_pass unix:/run/php/pterodactyl.sock;
|
||||
fastcgi_pass unix:/var/run/php/php-fpm7.2.sock;
|
||||
fastcgi_index index.php;
|
||||
include fastcgi_params;
|
||||
fastcgi_param PHP_VALUE "upload_max_filesize = 100M \n post_max_size=100M";
|
||||
|
|
|
@ -3,19 +3,24 @@
|
|||
|
||||
cd /app
|
||||
|
||||
mkdir -p /var/log/panel/logs/ /var/log/supervisord/ /var/log/nginx/ /var/log/php7/ \
|
||||
&& rmdir /app/storage/logs/ \
|
||||
&& chmod 777 /var/log/panel/logs/ \
|
||||
&& ln -s /var/log/panel/logs/ /app/storage/
|
||||
|
||||
## check for .env file and generate app keys if missing
|
||||
if [ -f /app/var/.env ]; then
|
||||
echo "external vars exist"
|
||||
echo "external vars exist."
|
||||
rm /app/.env
|
||||
|
||||
ln -s /app/var/.env /app/
|
||||
else
|
||||
echo "external vars don't exist"
|
||||
echo "external vars don't exist."
|
||||
rm /app/.env
|
||||
touch /app/var/.env
|
||||
|
||||
## manually generate a key because key generate --force fails
|
||||
echo -e "Generating key"
|
||||
echo -e "Generating key."
|
||||
APP_KEY=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)
|
||||
echo -e "Generated app key: $APP_KEY"
|
||||
echo -e "APP_KEY=$APP_KEY" > /app/var/.env
|
||||
|
@ -23,6 +28,25 @@ else
|
|||
ln -s /app/var/.env /app/
|
||||
fi
|
||||
|
||||
echo "Checking if https is required."
|
||||
if [ -f /etc/nginx/conf.d/default.conf ]; then
|
||||
echo "Using nginx config already in place."
|
||||
else
|
||||
echo "Checking if letsencrypt email is set."
|
||||
if [ -z $LE_EMAIL ]; then
|
||||
echo "No letsencrypt email is set Failing to http."
|
||||
cp .dev/docker/default.conf /etc/nginx/conf.d/default.conf
|
||||
|
||||
else
|
||||
echo "writing ssl config"
|
||||
cp .dev/docker/default_ssl.conf /etc/nginx/conf.d/default.conf
|
||||
echo "updating ssl config for domain"
|
||||
sed -i "s|<domain>|$(echo $APP_URL | sed 's~http[s]*://~~g')|g" /etc/nginx/conf.d/default.conf
|
||||
echo "generating certs"
|
||||
certbot certonly -d $(echo $APP_URL | sed 's~http[s]*://~~g') --standalone -m $LE_EMAIL --agree-tos -n
|
||||
fi
|
||||
fi
|
||||
|
||||
## check for DB up before starting the panel
|
||||
echo "Checking database status."
|
||||
until nc -z -v -w30 $DB_HOST 3306
|
||||
|
@ -34,13 +58,13 @@ do
|
|||
done
|
||||
|
||||
## make sure the db is set up
|
||||
echo -e "Migrating and Seeding DB"
|
||||
echo -e "Migrating and Seeding D.B"
|
||||
php artisan migrate --force
|
||||
php artisan db:seed --force
|
||||
|
||||
## start cronjobs for the queue
|
||||
echo -e "Starting cron jobs"
|
||||
crond
|
||||
echo -e "Starting cron jobs."
|
||||
crond -L /var/log/crond -l 5
|
||||
|
||||
echo -e "Starting supervisord"
|
||||
echo -e "Starting supervisord."
|
||||
exec "$@"
|
|
@ -1,29 +0,0 @@
|
|||
phraseapp:
|
||||
project_id: 94f8b39450cd749ae9c3cc0ab8cdb61d
|
||||
file_format: laravel
|
||||
push:
|
||||
sources:
|
||||
- file: ./resources/lang/<locale_code>/<tag>.php
|
||||
pull:
|
||||
targets:
|
||||
- file: ./resources/lang/<locale_code>/auth.php
|
||||
params:
|
||||
tag: "auth"
|
||||
- file: ./resources/lang/<locale_code>/base.php
|
||||
params:
|
||||
tag: "base"
|
||||
- file: ./resources/lang/<locale_code>/pagination.php
|
||||
params:
|
||||
tag: "pagination"
|
||||
- file: ./resources/lang/<locale_code>/passwords.php
|
||||
params:
|
||||
tag: "passwords"
|
||||
- file: ./resources/lang/<locale_code>/server.php
|
||||
params:
|
||||
tag: "server"
|
||||
- file: ./resources/lang/<locale_code>/strings.php
|
||||
params:
|
||||
tag: "strings"
|
||||
- file: ./resources/lang/<locale_code>/validation.php
|
||||
params:
|
||||
tag: "validation"
|
28
CHANGELOG.md
28
CHANGELOG.md
|
@ -3,6 +3,34 @@ 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.
|
||||
|
||||
## v0.7.12 (Derelict Dermodactylus)
|
||||
### Fixed
|
||||
* Fixes an issue with the locations API endpoint referencing an invalid namespace.
|
||||
* Fixes the `store()` function on the locations API not working due to an incorrect return typehint.
|
||||
* Fixes daemon secrets not being able to be reset on a Node.
|
||||
|
||||
### Updated
|
||||
* Upgraded core to use Laravel `5.7.14`.
|
||||
|
||||
### Added
|
||||
* Added support for opening and editing Python files through the web editor.
|
||||
|
||||
## v0.7.11 (Derelict Dermodactylus)
|
||||
### Fixed
|
||||
* Fixes an issue with certain systems not handling an API folder that was named `API` but referenced as `Api` in the namespace.
|
||||
* TS3 egg updated to use CLI arguments correctly and have a more minimalistic installation script.
|
||||
* Terminal was not properly displaying longer lines leading to some visual inconsistency.
|
||||
* Assorted translation updates.
|
||||
* Pagination for server listing now properly respects configuration setting.
|
||||
* Client API now properly respects permissions that are set and allows subusers to access their assigned servers.
|
||||
|
||||
### Changed
|
||||
* Removed PhraseApp integration from Panel code as it is no longer used.
|
||||
* SFTP login endpoint now returns the permissions for that user rather than requiring additional queries to get that data.
|
||||
|
||||
### Added
|
||||
* You can now test your mail settings from the Admin CP without waiting to see if things are working correctly.
|
||||
|
||||
## v0.7.10 (Derelict Dermodactylus)
|
||||
### Fixed
|
||||
* Scheduled tasks triggered manually no longer improperly change the `next_run_at` time and do not run twice in a row anymore.
|
||||
|
|
|
@ -2,7 +2,7 @@ FROM alpine:3.8
|
|||
|
||||
WORKDIR /app
|
||||
|
||||
RUN apk add --no-cache --update ca-certificates certbot nginx dcron curl tini php7 php7-bcmath php7-common php7-dom php7-fpm php7-gd php7-mbstring php7-openssl php7-zip php7-pdo php7-phar php7-json php7-pdo_mysql php7-session php7-ctype php7-tokenizer php7-zlib php7-simplexml supervisor \
|
||||
RUN apk add --no-cache --update ca-certificates certbot nginx dcron curl tini php7 php7-bcmath php7-common php7-dom php7-fpm php7-gd php7-mbstring php7-openssl php7-zip php7-pdo php7-phar php7-json php7-pdo_mysql php7-session php7-ctype php7-tokenizer php7-zlib php7-simplexml php7-fileinfo supervisor \
|
||||
&& curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
|
||||
|
||||
COPY . ./
|
||||
|
@ -15,9 +15,9 @@ RUN cp .env.example .env \
|
|||
RUN cp .dev/docker/default.conf /etc/nginx/conf.d/default.conf \
|
||||
&& cp .dev/docker/www.conf /etc/php7/php-fpm.d/www.conf \
|
||||
&& cat .dev/docker/supervisord.conf > /etc/supervisord.conf \
|
||||
&& echo "* * * * * /usr/bin/php /app/pterodactyl/artisan schedule:run >> /dev/null 2>&1" >> /var/spool/cron/crontabs/root \
|
||||
&& mkdir -p /var/run/php /var/run/nginx \
|
||||
&& mkdir -p /var/log/supervisord/
|
||||
&& echo "* * * * * /usr/bin/php /app/artisan schedule:run >> /dev/null 2>&1" >> /var/spool/cron/crontabs/root \
|
||||
&& sed -i s/ssl_session_cache/#ssl_session_cache/g /etc/nginx/nginx.conf \
|
||||
&& mkdir -p /var/run/php /var/run/nginx
|
||||
|
||||
EXPOSE 80 443
|
||||
|
||||
|
|
|
@ -41,8 +41,7 @@ In addition to our standard nest of supported games, our community is constantly
|
|||
* Discord ATLBot
|
||||
|
||||
## Credits
|
||||
A huge thank you to [PhraseApp](https://phraseapp.com) who provide us the software to help translate this project. This software would not be possible
|
||||
without the work of other open-source authors who provide tools such as:
|
||||
This software would not be possible without the work of other open-source authors who provide tools such as:
|
||||
|
||||
[Ace Editor](https://ace.c9.io), [AdminLTE](https://almsaeedstudio.com), [Animate.css](http://daneden.github.io/animate.css/), [AnsiUp](https://github.com/drudru/ansi_up), [Async.js](https://github.com/caolan/async),
|
||||
[Bootstrap](http://getbootstrap.com), [Bootstrap Notify](http://bootstrap-notify.remabledesigns.com), [Chart.js](http://www.chartjs.org), [FontAwesome](http://fontawesome.io),
|
||||
|
|
|
@ -132,7 +132,7 @@ class AppSettingsCommand extends Command
|
|||
);
|
||||
|
||||
$selected = $this->config->get('queue.default', 'redis');
|
||||
$this->variables['QUEUE_DRIVER'] = $this->option('queue') ?? $this->choice(
|
||||
$this->variables['QUEUE_CONNECTION'] = $this->option('queue') ?? $this->choice(
|
||||
trans('command/messages.environment.app.queue_driver'),
|
||||
self::ALLOWED_QUEUE_DRIVERS,
|
||||
array_key_exists($selected, self::ALLOWED_QUEUE_DRIVERS) ? $selected : null
|
||||
|
|
|
@ -103,10 +103,10 @@ interface ServerRepositoryInterface extends RepositoryInterface, SearchableInter
|
|||
*
|
||||
* @param \Pterodactyl\Models\User $user
|
||||
* @param int $level
|
||||
* @param bool $paginate
|
||||
* @param bool|int $paginate
|
||||
* @return \Illuminate\Pagination\LengthAwarePaginator|\Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function filterUserAccessServers(User $user, int $level, bool $paginate = true);
|
||||
public function filterUserAccessServers(User $user, int $level, $paginate = 25);
|
||||
|
||||
/**
|
||||
* Return a server by UUID.
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Pterodactyl - Panel
|
||||
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
|
||||
*
|
||||
* This software is licensed under the terms of the MIT license.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
namespace Pterodactyl\Extensions;
|
||||
|
||||
use Illuminate\Translation\Translator as LaravelTranslator;
|
||||
|
||||
class PhraseAppTranslator extends LaravelTranslator
|
||||
{
|
||||
/**
|
||||
* Get the translation for the given key.
|
||||
*
|
||||
* @param string $key
|
||||
* @param array $replace
|
||||
* @param string|null $locale
|
||||
* @param bool $fallback
|
||||
* @return string
|
||||
*/
|
||||
public function get($key, array $replace = [], $locale = null, $fallback = true)
|
||||
{
|
||||
$key = substr($key, strpos($key, '.') + 1);
|
||||
|
||||
return "{{__phrase_${key}__}}";
|
||||
}
|
||||
}
|
|
@ -263,7 +263,7 @@ class NodesController extends Controller
|
|||
*/
|
||||
public function updateSettings(NodeFormRequest $request, Node $node)
|
||||
{
|
||||
$this->updateService->handle($node, $request->normalize());
|
||||
$this->updateService->handle($node, $request->normalize(), $request->input('reset_secret') === 'on');
|
||||
$this->alert->success(trans('admin/node.notices.node_updated'))->flash();
|
||||
|
||||
return redirect()->route('admin.nodes.view.settings', $node->id)->withInput();
|
||||
|
@ -289,7 +289,7 @@ class NodesController extends Controller
|
|||
* Removes multiple individual allocations from a node.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param int $node
|
||||
* @param int $node
|
||||
* @return \Illuminate\Http\Response
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Service\Allocation\ServerUsingAllocationException
|
||||
|
|
|
@ -2,10 +2,14 @@
|
|||
|
||||
namespace Pterodactyl\Http\Controllers\Admin\Settings;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\View\View;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Prologue\Alerts\AlertsMessageBag;
|
||||
use Illuminate\Contracts\Console\Kernel;
|
||||
use Pterodactyl\Notifications\MailTested;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Pterodactyl\Exceptions\DisplayException;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Illuminate\Contracts\Encryption\Encrypter;
|
||||
|
@ -81,13 +85,13 @@ class MailController extends Controller
|
|||
* Handle request to update SMTP mail settings.
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Admin\Settings\MailSettingsFormRequest $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @return \Illuminate\Http\Response
|
||||
*
|
||||
* @throws DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function update(MailSettingsFormRequest $request): RedirectResponse
|
||||
public function update(MailSettingsFormRequest $request): Response
|
||||
{
|
||||
if ($this->config->get('mail.driver') !== 'smtp') {
|
||||
throw new DisplayException('This feature is only available if SMTP is the selected email driver for the Panel.');
|
||||
|
@ -107,8 +111,25 @@ class MailController extends Controller
|
|||
}
|
||||
|
||||
$this->kernel->call('queue:restart');
|
||||
$this->alert->success('Mail settings have been updated successfully and the queue worker was restarted to apply these changes.')->flash();
|
||||
|
||||
return redirect()->route('admin.settings.mail');
|
||||
return response('', 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit a request to send a test mail message.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function test(Request $request): Response
|
||||
{
|
||||
try {
|
||||
Notification::route('mail', $request->user()->email)
|
||||
->notify(new MailTested($request->user()));
|
||||
} catch (Exception $exception) {
|
||||
return response($exception->getMessage(), 500);
|
||||
}
|
||||
|
||||
return response('', 204);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ use Pterodactyl\Http\Controllers\Api\Application\ApplicationApiController;
|
|||
use Pterodactyl\Http\Requests\Api\Application\Locations\GetLocationRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Locations\GetLocationsRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Locations\DeleteLocationRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Locations\StoreLocationRequest;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Locations\UpdateLocationRequest;
|
||||
|
||||
class LocationController extends ApplicationApiController
|
||||
|
@ -92,7 +93,7 @@ class LocationController extends ApplicationApiController
|
|||
* Store a new location on the Panel and return a HTTP/201 response code with the
|
||||
* new location attached.
|
||||
*
|
||||
* @param \Pterodactyl\Http\Controllers\Api\Application\Locations\StoreLocationRequest $request
|
||||
* @param \Pterodactyl\Http\Requests\Api\Application\Locations\StoreLocationRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
|
|
|
@ -71,14 +71,14 @@ class AllocationController extends ApplicationApiController
|
|||
* Store new allocations for a given node.
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Api\Application\Allocations\StoreAllocationRequest $request
|
||||
* @return array
|
||||
* @return \Illuminate\Http\Response
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Service\Allocation\CidrOutOfRangeException
|
||||
* @throws \Pterodactyl\Exceptions\Service\Allocation\InvalidPortMappingException
|
||||
* @throws \Pterodactyl\Exceptions\Service\Allocation\PortOutOfRangeException
|
||||
* @throws \Pterodactyl\Exceptions\Service\Allocation\TooManyPortsInRangeException
|
||||
*/
|
||||
public function store(StoreAllocationRequest $request): array
|
||||
public function store(StoreAllocationRequest $request): Response
|
||||
{
|
||||
$this->assignmentService->handle($request->getModel(Node::class), $request->validated());
|
||||
|
||||
|
|
|
@ -125,7 +125,7 @@ class NodeController extends ApplicationApiController
|
|||
public function update(UpdateNodeRequest $request): array
|
||||
{
|
||||
$node = $this->updateService->handle(
|
||||
$request->getModel(Node::class), $request->validated()
|
||||
$request->getModel(Node::class), $request->validated(), $request->input('reset_secret') === true
|
||||
);
|
||||
|
||||
return $this->fractal->item($node)
|
||||
|
|
|
@ -7,7 +7,6 @@ use Pterodactyl\Models\Server;
|
|||
use Psr\Http\Message\ResponseInterface;
|
||||
use GuzzleHttp\Exception\ClientException;
|
||||
use GuzzleHttp\Exception\RequestException;
|
||||
use Pterodactyl\Services\DaemonKeys\DaemonKeyProviderService;
|
||||
use Pterodactyl\Http\Controllers\Api\Client\ClientApiController;
|
||||
use Pterodactyl\Http\Requests\Api\Client\Servers\SendCommandRequest;
|
||||
use Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException;
|
||||
|
@ -16,11 +15,6 @@ use Symfony\Component\HttpKernel\Exception\PreconditionFailedHttpException;
|
|||
|
||||
class CommandController extends ClientApiController
|
||||
{
|
||||
/**
|
||||
* @var \Pterodactyl\Services\DaemonKeys\DaemonKeyProviderService
|
||||
*/
|
||||
private $keyProviderService;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Contracts\Repository\Daemon\CommandRepositoryInterface
|
||||
*/
|
||||
|
@ -30,13 +24,11 @@ class CommandController extends ClientApiController
|
|||
* CommandController constructor.
|
||||
*
|
||||
* @param \Pterodactyl\Contracts\Repository\Daemon\CommandRepositoryInterface $repository
|
||||
* @param \Pterodactyl\Services\DaemonKeys\DaemonKeyProviderService $keyProviderService
|
||||
*/
|
||||
public function __construct(CommandRepositoryInterface $repository, DaemonKeyProviderService $keyProviderService)
|
||||
public function __construct(CommandRepositoryInterface $repository)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->keyProviderService = $keyProviderService;
|
||||
$this->repository = $repository;
|
||||
}
|
||||
|
||||
|
@ -46,14 +38,12 @@ class CommandController extends ClientApiController
|
|||
* @param \Pterodactyl\Http\Requests\Api\Client\Servers\SendCommandRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
* @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException
|
||||
*/
|
||||
public function index(SendCommandRequest $request): Response
|
||||
{
|
||||
$server = $request->getModel(Server::class);
|
||||
$token = $this->keyProviderService->handle($server, $request->user());
|
||||
$token = $request->attributes->get('server_token');
|
||||
|
||||
try {
|
||||
$this->repository->setServer($server)
|
||||
|
|
|
@ -4,18 +4,12 @@ namespace Pterodactyl\Http\Controllers\Api\Client\Servers;
|
|||
|
||||
use Illuminate\Http\Response;
|
||||
use Pterodactyl\Models\Server;
|
||||
use Pterodactyl\Services\DaemonKeys\DaemonKeyProviderService;
|
||||
use Pterodactyl\Http\Controllers\Api\Client\ClientApiController;
|
||||
use Pterodactyl\Http\Requests\Api\Client\Servers\SendPowerRequest;
|
||||
use Pterodactyl\Contracts\Repository\Daemon\PowerRepositoryInterface;
|
||||
|
||||
class PowerController extends ClientApiController
|
||||
{
|
||||
/**
|
||||
* @var \Pterodactyl\Services\DaemonKeys\DaemonKeyProviderService
|
||||
*/
|
||||
private $keyProviderService;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Contracts\Repository\Daemon\PowerRepositoryInterface
|
||||
*/
|
||||
|
@ -24,14 +18,12 @@ class PowerController extends ClientApiController
|
|||
/**
|
||||
* PowerController constructor.
|
||||
*
|
||||
* @param \Pterodactyl\Services\DaemonKeys\DaemonKeyProviderService $keyProviderService
|
||||
* @param \Pterodactyl\Contracts\Repository\Daemon\PowerRepositoryInterface $repository
|
||||
*/
|
||||
public function __construct(DaemonKeyProviderService $keyProviderService, PowerRepositoryInterface $repository)
|
||||
public function __construct(PowerRepositoryInterface $repository)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->keyProviderService = $keyProviderService;
|
||||
$this->repository = $repository;
|
||||
}
|
||||
|
||||
|
@ -41,14 +33,12 @@ class PowerController extends ClientApiController
|
|||
* @param \Pterodactyl\Http\Requests\Api\Client\Servers\SendPowerRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\Daemon\InvalidPowerSignalException
|
||||
*/
|
||||
public function index(SendPowerRequest $request): Response
|
||||
{
|
||||
$server = $request->getModel(Server::class);
|
||||
$token = $this->keyProviderService->handle($server, $request->user());
|
||||
$token = $request->attributes->get('server_token');
|
||||
|
||||
$this->repository->setServer($server)->setToken($token)->sendSignal($request->input('signal'));
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ class ForgotPasswordController extends Controller
|
|||
// exist on the system.
|
||||
event(new FailedPasswordReset($request->ip(), $request->input('email')));
|
||||
|
||||
return $this->sendResetLinkResponse(Password::RESET_LINK_SENT);
|
||||
return $this->sendResetLinkResponse($request, Password::RESET_LINK_SENT);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -56,7 +56,7 @@ class IndexController extends Controller
|
|||
public function index(Request $request)
|
||||
{
|
||||
$servers = $this->repository->setSearchTerm($request->input('query'))->filterUserAccessServers(
|
||||
$request->user(), User::FILTER_LEVEL_ALL
|
||||
$request->user(), User::FILTER_LEVEL_ALL, config('pterodactyl.paginate.frontend.servers')
|
||||
);
|
||||
|
||||
return view('templates/base.core', ['servers' => $servers]);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Api\Application\Locations;
|
||||
namespace Pterodactyl\Http\Requests\Api\Application\Locations;
|
||||
|
||||
use Pterodactyl\Models\Location;
|
||||
use Pterodactyl\Services\Acl\Api\AdminAcl;
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
namespace Pterodactyl\Http\Requests\Api\Application\Locations;
|
||||
|
||||
use Pterodactyl\Models\Location;
|
||||
use Pterodactyl\Http\Controllers\Api\Application\Locations\StoreLocationRequest;
|
||||
|
||||
class UpdateLocationRequest extends StoreLocationRequest
|
||||
{
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
namespace Pterodactyl\Http\Requests\Api\Client\Servers;
|
||||
|
||||
use Pterodactyl\Models\Server;
|
||||
use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest;
|
||||
|
||||
class GetServerRequest extends ClientApiRequest
|
||||
|
@ -18,14 +17,4 @@ class GetServerRequest extends ClientApiRequest
|
|||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the user should even know that this server exists.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function resourceExists(): bool
|
||||
{
|
||||
return $this->user()->can('view-server', $this->getModel(Server::class));
|
||||
}
|
||||
}
|
||||
|
|
33
app/Notifications/MailTested.php
Normal file
33
app/Notifications/MailTested.php
Normal file
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
namespace Pterodactyl\Notifications;
|
||||
|
||||
use Pterodactyl\Models\User;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
|
||||
class MailTested extends Notification
|
||||
{
|
||||
/**
|
||||
* @var \Pterodactyl\Models\User
|
||||
*/
|
||||
private $user;
|
||||
|
||||
public function __construct(User $user)
|
||||
{
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
public function via()
|
||||
{
|
||||
return ['mail'];
|
||||
}
|
||||
|
||||
public function toMail()
|
||||
{
|
||||
return (new MailMessage)
|
||||
->subject('Pterodactyl Test Message')
|
||||
->greeting('Hello ' . $this->user->name . '!')
|
||||
->line('This is a test of the Pterodactyl mail system. You\'re good to go!');
|
||||
}
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Pterodactyl - Panel
|
||||
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
|
||||
*
|
||||
* This software is licensed under the terms of the MIT license.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
namespace Pterodactyl\Providers;
|
||||
|
||||
use Pterodactyl\Extensions\PhraseAppTranslator;
|
||||
use Illuminate\Translation\TranslationServiceProvider;
|
||||
use Illuminate\Translation\Translator as IlluminateTranslator;
|
||||
|
||||
class PhraseAppTranslationProvider extends TranslationServiceProvider
|
||||
{
|
||||
/**
|
||||
* Register the service provider.
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
$this->registerLoader();
|
||||
|
||||
$this->app->singleton('translator', function ($app) {
|
||||
$loader = $app['translation.loader'];
|
||||
|
||||
// When registering the translator component, we'll need to set the default
|
||||
// locale as well as the fallback locale. So, we'll grab the application
|
||||
// configuration so we can easily get both of these values from there.
|
||||
$locale = $app['config']['app.locale'];
|
||||
|
||||
if ($app['config']['pterodactyl.lang.in_context']) {
|
||||
$trans = new PhraseAppTranslator($loader, $locale);
|
||||
} else {
|
||||
$trans = new IlluminateTranslator($loader, $locale);
|
||||
}
|
||||
|
||||
$trans->setFallback($app['config']['app.fallback_locale']);
|
||||
|
||||
return $trans;
|
||||
});
|
||||
}
|
||||
}
|
|
@ -211,10 +211,10 @@ class ServerRepository extends EloquentRepository implements ServerRepositoryInt
|
|||
*
|
||||
* @param \Pterodactyl\Models\User $user
|
||||
* @param int $level
|
||||
* @param bool $paginate
|
||||
* @param bool|int $paginate
|
||||
* @return \Illuminate\Contracts\Pagination\LengthAwarePaginator|\Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function filterUserAccessServers(User $user, int $level, bool $paginate = true)
|
||||
public function filterUserAccessServers(User $user, int $level, $paginate = 25)
|
||||
{
|
||||
$instance = $this->getBuilder()->select($this->getColumns())->with(['user', 'node', 'allocation']);
|
||||
|
||||
|
@ -240,7 +240,7 @@ class ServerRepository extends EloquentRepository implements ServerRepositoryInt
|
|||
|
||||
$instance->search($this->getSearchTerm());
|
||||
|
||||
return $paginate ? $instance->paginate(25) : $instance->get();
|
||||
return $paginate ? $instance->paginate($paginate) : $instance->get();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -50,24 +50,41 @@ class NodeUpdateService
|
|||
*
|
||||
* @param \Pterodactyl\Models\Node $node
|
||||
* @param array $data
|
||||
* @param bool $resetToken
|
||||
*
|
||||
* @return \Pterodactyl\Models\Node
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
* @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException
|
||||
* @throws \Pterodactyl\Exceptions\Service\Node\ConfigurationNotPersistedException
|
||||
*/
|
||||
public function handle(Node $node, array $data)
|
||||
public function handle(Node $node, array $data, bool $resetToken = false)
|
||||
{
|
||||
if (! is_null(array_get($data, 'reset_secret'))) {
|
||||
if ($resetToken) {
|
||||
$data['daemonSecret'] = str_random(Node::DAEMON_SECRET_LENGTH);
|
||||
unset($data['reset_secret']);
|
||||
}
|
||||
|
||||
$this->connection->beginTransaction();
|
||||
|
||||
/** @var \Pterodactyl\Models\Node $updatedModel */
|
||||
$updatedModel = $this->repository->update($node->id, $data);
|
||||
|
||||
try {
|
||||
$this->configRepository->setNode($updatedModel)->update();
|
||||
if ($resetToken) {
|
||||
// We need to clone the new model and set it's authentication token to be the
|
||||
// old one so we can connect. Then we will pass the new token through as an
|
||||
// override on the call.
|
||||
$cloned = $updatedModel->replicate(['daemonSecret']);
|
||||
$cloned->setAttribute('daemonSecret', $node->getAttribute('daemonSecret'));
|
||||
|
||||
$this->configRepository->setNode($cloned)->update([
|
||||
'keys' => [$data['daemonSecret']],
|
||||
]);
|
||||
} else {
|
||||
$this->configRepository->setNode($updatedModel)->update();
|
||||
}
|
||||
|
||||
$this->connection->commit();
|
||||
} catch (RequestException $exception) {
|
||||
// Failed to connect to the Daemon. Let's go ahead and save the configuration
|
||||
|
|
|
@ -102,6 +102,7 @@ class AuthenticateUsingPasswordService
|
|||
return [
|
||||
'server' => $server->uuid,
|
||||
'token' => $this->keyProviderService->handle($server, $user),
|
||||
'permissions' => $permissions ?? ['*'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
"hashids/hashids": "^2.0",
|
||||
"igaster/laravel-theme": "^2.0.6",
|
||||
"laracasts/utilities": "^3.0",
|
||||
"laravel/framework": "5.6.*",
|
||||
"laravel/framework": "~5.7.14",
|
||||
"laravel/tinker": "^1.0",
|
||||
"lord/laroute": "^2.4",
|
||||
"matriphe/iso-639": "^1.2",
|
||||
|
@ -34,15 +34,15 @@
|
|||
"prologue/alerts": "^0.4",
|
||||
"ramsey/uuid": "^3.7",
|
||||
"s1lentium/iptools": "^1.1",
|
||||
"sofa/eloquence-base": "v5.6",
|
||||
"sofa/eloquence-base": "v5.6.2",
|
||||
"sofa/eloquence-validable": "v5.6",
|
||||
"spatie/laravel-fractal": "^5.3",
|
||||
"spatie/laravel-fractal": "^5.4",
|
||||
"webmozart/assert": "^1.2",
|
||||
"znck/belongs-to-through": "^2.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"barryvdh/laravel-debugbar": "^3.1",
|
||||
"barryvdh/laravel-ide-helper": "^2.4",
|
||||
"barryvdh/laravel-debugbar": "^3.2",
|
||||
"barryvdh/laravel-ide-helper": "^2.5",
|
||||
"codedungeon/phpunit-result-printer": "^0.17.1",
|
||||
"filp/whoops": "^2.1",
|
||||
"friendsofphp/php-cs-fixer": "^2.11.1",
|
||||
|
|
|
@ -9,7 +9,7 @@ return [
|
|||
| change this value if you are not maintaining your own internal versions.
|
||||
*/
|
||||
|
||||
'version' => '0.7.10',
|
||||
'version' => 'canary',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
@ -166,6 +166,7 @@ return [
|
|||
Illuminate\Redis\RedisServiceProvider::class,
|
||||
Illuminate\Auth\Passwords\PasswordResetServiceProvider::class,
|
||||
Illuminate\Session\SessionServiceProvider::class,
|
||||
Illuminate\Translation\TranslationServiceProvider::class,
|
||||
Illuminate\Validation\ValidationServiceProvider::class,
|
||||
Illuminate\View\ViewServiceProvider::class,
|
||||
|
||||
|
@ -179,7 +180,6 @@ return [
|
|||
Pterodactyl\Providers\HashidsServiceProvider::class,
|
||||
Pterodactyl\Providers\RouteServiceProvider::class,
|
||||
Pterodactyl\Providers\MacroServiceProvider::class,
|
||||
Pterodactyl\Providers\PhraseAppTranslationProvider::class,
|
||||
Pterodactyl\Providers\RepositoryServiceProvider::class,
|
||||
Pterodactyl\Providers\ViewComposerServiceProvider::class,
|
||||
|
||||
|
|
|
@ -153,23 +153,10 @@ return [
|
|||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Language Editor
|
||||
| Client Features
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Set `PHRASE_IN_CONTEXT` to true to enable the PhaseApp in-context editor
|
||||
| on this site which allows you to translate the panel, from the panel.
|
||||
*/
|
||||
'lang' => [
|
||||
'in_context' => env('PHRASE_IN_CONTEXT', false),
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Language Editor
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Set `PHRASE_IN_CONTEXT` to true to enable the PhaseApp in-context editor
|
||||
| on this site which allows you to translate the panel, from the panel.
|
||||
| Allow clients to create their own databases.
|
||||
*/
|
||||
'client_features' => [
|
||||
'databases' => [
|
||||
|
@ -199,6 +186,7 @@ return [
|
|||
'text/plain',
|
||||
'text/x-perl',
|
||||
'text/x-shellscript',
|
||||
'text/x-python',
|
||||
],
|
||||
],
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ return [
|
|||
|
|
||||
*/
|
||||
|
||||
'default' => env('QUEUE_DRIVER', 'database'),
|
||||
'default' => env('QUEUE_CONNECTION', env('QUEUE_DRIVER', 'database')),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"meta": {
|
||||
"version": "PTDL_v1"
|
||||
},
|
||||
"exported_at": "2018-02-25T12:20:22-05:00",
|
||||
"exported_at": "2018-11-16T02:14:51-05:00",
|
||||
"name": "Spigot",
|
||||
"author": "support@pterodactyl.io",
|
||||
"description": "Spigot is the most widely-used modded Minecraft server software in the world. It powers many of the top Minecraft server networks around to ensure they can cope with their huge player base and ensure the satisfaction of their players. Spigot works by reducing and eliminating many causes of lag, as well as adding in handy features and settings that help make your job of server administration easier.",
|
||||
|
@ -17,7 +17,7 @@
|
|||
},
|
||||
"scripts": {
|
||||
"installation": {
|
||||
"script": "#!\/bin\/ash\r\n# Spigot Installation Script\r\n#\r\n# Server Files: \/mnt\/server\r\n\r\n## Only download if a path is provided, otherwise continue.\r\nif [ ! -z \"${DL_PATH}\" ]; then\r\n apk update\r\n apk add curl\r\n\r\n cd \/mnt\/server\r\n\r\n MODIFIED_DOWNLOAD=`eval echo $(echo ${DL_PATH} | sed -e 's\/{{\/${\/g' -e 's\/}}\/}\/g')`\r\n curl -sSL -o ${SERVER_JARFILE} ${MODIFIED_DOWNLOAD}\r\nelse\r\n apk add --no-cache curl git openjdk8 openssl\r\n \r\n cd \/srv\/\r\n \r\n wget https:\/\/hub.spigotmc.org\/jenkins\/job\/BuildTools\/lastSuccessfulBuild\/artifact\/target\/BuildTools.jar\r\n \r\n mv BuildTools.jar \/srv\/\r\n\r\n java -jar BuildTools.jar --rev ${DL_VERSION}\r\n\r\n mv spigot-*.jar \/mnt\/server\/${SERVER_JARFILE}\r\nfi",
|
||||
"script": "#!\/bin\/ash\r\n# Spigot Installation Script\r\n#\r\n# Server Files: \/mnt\/server\r\n\r\n## Only download if a path is provided, otherwise continue.\r\nif [ ! -z \"${DL_PATH}\" ]; then\r\n apk update\r\n apk add curl\r\n\r\n cd \/mnt\/server\r\n\r\n MODIFIED_DOWNLOAD=`eval echo $(echo ${DL_PATH} | sed -e 's\/{{\/${\/g' -e 's\/}}\/}\/g')`\r\n curl -sSL -o ${SERVER_JARFILE} ${MODIFIED_DOWNLOAD}\r\nelse\r\n apk add --no-cache curl git openjdk8 openssl bash\r\n \r\n cd \/srv\/\r\n \r\n wget https:\/\/hub.spigotmc.org\/jenkins\/job\/BuildTools\/lastSuccessfulBuild\/artifact\/target\/BuildTools.jar\r\n \r\n mv BuildTools.jar \/srv\/\r\n\r\n java -jar BuildTools.jar --rev ${DL_VERSION}\r\n\r\n mv spigot-*.jar \/mnt\/server\/${SERVER_JARFILE}\r\nfi",
|
||||
"container": "alpine:3.7",
|
||||
"entrypoint": "ash"
|
||||
}
|
||||
|
|
|
@ -3,21 +3,21 @@
|
|||
"meta": {
|
||||
"version": "PTDL_v1"
|
||||
},
|
||||
"exported_at": "2018-01-21T17:01:45-06:00",
|
||||
"exported_at": "2018-10-28T20:50:23+01:00",
|
||||
"name": "Teamspeak3 Server",
|
||||
"author": "support@pterodactyl.io",
|
||||
"description": "VoIP software designed with security in mind, featuring crystal clear voice quality, endless customization options, and scalabilty up to thousands of simultaneous users.",
|
||||
"image": "quay.io\/pterodactyl\/core:glibc",
|
||||
"startup": ".\/ts3server_minimal_runscript.sh default_voice_port={{SERVER_PORT}} query_port={{SERVER_PORT}}",
|
||||
"startup": ".\/ts3server_minimal_runscript.sh default_voice_port={{SERVER_PORT}} query_port={{SERVER_PORT}} license_accepted=1",
|
||||
"config": {
|
||||
"files": "{\"ts3server.ini\":{\"parser\": \"ini\", \"find\":{\"default_voice_port\": \"{{server.build.default.port}}\", \"voice_ip\": \"0.0.0.0\", \"query_port\": \"{{server.build.default.port}}\", \"query_ip\": \"0.0.0.0\"}}}",
|
||||
"files": "{}",
|
||||
"startup": "{\"done\": \"listening on 0.0.0.0:\", \"userInteraction\": []}",
|
||||
"logs": "{\"custom\": true, \"location\": \"logs\/ts3.log\"}",
|
||||
"stop": "^C"
|
||||
},
|
||||
"scripts": {
|
||||
"installation": {
|
||||
"script": "#!\/bin\/ash\n# TS3 Installation Script\n#\n# Server Files: \/mnt\/server\napk update\napk add tar curl\n\ncd \/tmp\n\ncurl -sSLO http:\/\/dl.4players.de\/ts\/releases\/${TS_VERSION}\/teamspeak3-server_linux_amd64-${TS_VERSION}.tar.bz2\n\ntar -xjvf teamspeak3-server_linux_amd64-${TS_VERSION}.tar.bz2\ncp -r teamspeak3-server_linux_amd64\/* \/mnt\/server\n\necho \"machine_id=\ndefault_voice_port=${SERVER_PORT}\nvoice_ip=0.0.0.0\nlicensepath=\nfiletransfer_port=30033\nfiletransfer_ip=\nquery_port=${SERVER_PORT}\nquery_ip=0.0.0.0\nquery_ip_whitelist=query_ip_whitelist.txt\nquery_ip_blacklist=query_ip_blacklist.txt\ndbplugin=ts3db_sqlite3\ndbpluginparameter=\ndbsqlpath=sql\/\ndbsqlcreatepath=create_sqlite\/\ndbconnections=10\nlogpath=logs\nlogquerycommands=0\ndbclientkeepdays=30\nlogappend=0\nquery_skipbruteforcecheck=0\" > \/mnt\/server\/ts3server.ini\n\ntouch \/mnt\/server\/.ts3server_license_accepted",
|
||||
"script": "#!\/bin\/ash\n# TS3 Installation Script\n#\n# Server Files: \/mnt\/server\napk update\napk add tar curl\n\ncd \/mnt\/server\n\ncurl http:\/\/dl.4players.de\/ts\/releases\/${TS_VERSION}\/teamspeak3-server_linux_amd64-${TS_VERSION}.tar.bz2 | tar xj --strip-components=1",
|
||||
"container": "alpine:3.4",
|
||||
"entrypoint": "ash"
|
||||
}
|
||||
|
@ -27,7 +27,7 @@
|
|||
"name": "Server Version",
|
||||
"description": "The version of Teamspeak 3 to use when running the server.",
|
||||
"env_variable": "TS_VERSION",
|
||||
"default_value": "3.1.1",
|
||||
"default_value": "3.5.0",
|
||||
"user_viewable": 1,
|
||||
"user_editable": 1,
|
||||
"rules": "required|regex:\/^([0-9_\\.-]{5,10})$\/"
|
||||
|
|
|
@ -25,6 +25,9 @@ services:
|
|||
- cache
|
||||
volumes:
|
||||
- "/srv/pterodactyl/var/:/app/var/"
|
||||
- "/srv/pterodactyl/nginx/:/etc/nginx/conf.d/"
|
||||
- "/srv/pterodactyl/certs/:/etc/letsencrypt/"
|
||||
- "/srv/pterodactyl/logs/:/var/log/"
|
||||
environment:
|
||||
## These are defaults and should be left alone
|
||||
- "APP_ENV=production"
|
||||
|
@ -44,13 +47,13 @@ services:
|
|||
- "REDIS_PASSWORD=null"
|
||||
- "REDIS_PORT=6379"
|
||||
## Domain settings
|
||||
- "APP_URL=https://your.domain.here"
|
||||
- "APP_URL=https://your.domain.here" ## if you are running this behind a reverse proxy with ssl app_url needs to be https still.
|
||||
## Timezone settings
|
||||
- "APP_TIMEZONE=America/New_York"
|
||||
- "APP_TIMEZONE=UTC" ## http://php.net/manual/en/timezones.php
|
||||
## Service egg settings
|
||||
- "APP_SERVICE_AUTHOR=noreply@your.domain.here"
|
||||
- "APP_SERVICE_AUTHOR=noreply@your.domain.here" ## this is the email that gets put on eggs you create
|
||||
## Database settings
|
||||
## change if you want it to be more secure.
|
||||
## These can be left alone. Only change if you know what you are doing.
|
||||
- "DB_HOST=database"
|
||||
- "DB_PORT=3306"
|
||||
- "DB_DATABASE=pterodb"
|
||||
|
@ -64,6 +67,8 @@ services:
|
|||
- "MAIL_USERNAME=''"
|
||||
- "MAIL_PASSWORD=''"
|
||||
- "MAIL_ENCRYPTION=true"
|
||||
## certbot settings - Used to automatically generate ssl certs and
|
||||
- "LE_EMAIL=''" ## leave blank unless you aree generating certs.
|
||||
|
||||
networks:
|
||||
default:
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
<env name="DB_CONNECTION" value="testing"/>
|
||||
<env name="CACHE_DRIVER" value="array"/>
|
||||
<env name="SESSION_DRIVER" value="array"/>
|
||||
<env name="QUEUE_DRIVER" value="sync"/>
|
||||
<env name="QUEUE_CONNECTION" value="sync"/>
|
||||
<env name="MAIL_DRIVER" value="array"/>
|
||||
</php>
|
||||
</phpunit>
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -26,6 +26,7 @@
|
|||
|
||||
#terminal > .cmd {
|
||||
padding: 1px 0;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
#terminal_input {
|
||||
|
|
|
@ -30,7 +30,7 @@ var Server = (function () {
|
|||
}
|
||||
|
||||
if (typeof io !== 'function') {
|
||||
console.error('Socket.io is reqired to use this panel.');
|
||||
console.error('Socket.io is required to use this panel.');
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ $(document).ready(function () {
|
|||
console.error(jqXHR);
|
||||
swal({
|
||||
title: 'Whoops!',
|
||||
text: 'An error occured while attempting to set the EULA as accepted: ' . jqXHR.responseJSON.error,
|
||||
text: 'An error occurred while attempting to set the EULA as accepted: ' + jqXHR.responseJSON.error,
|
||||
type: 'error'
|
||||
})
|
||||
});
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
window.PHRASEAPP_CONFIG = {
|
||||
projectId: '94f8b39450cd749ae9c3cc0ab8cdb61d'
|
||||
};
|
||||
(function() {
|
||||
var phraseapp = document.createElement('script'); phraseapp.type = 'text/javascript'; phraseapp.async = true;
|
||||
phraseapp.src = ['https://', 'phraseapp.com/assets/in-context-editor/2.0/app.js?', new Date().getTime()].join('');
|
||||
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(phraseapp, s);
|
||||
})();
|
|
@ -340,7 +340,7 @@ return [
|
|||
'2fa_disable_error' => 'Der bereitgestellte 2FA-Token war nicht gültig. Der Schutz wurde für dieses Konto nicht deaktiviert.',
|
||||
'2fa_header' => '2-Faktor-Authentifizierung',
|
||||
'2fa_qr' => '2FA konfigurieren',
|
||||
'2fa_token_help' => 'Bitte gebe den 2FA Code von deiner 2FA APP ein (Google Authenticatior, Authy, etc.).',
|
||||
'2fa_token_help' => 'Bitte gebe den 2FA Code von deiner 2FA APP ein (Google Authenticator, Authy, etc.).',
|
||||
'disable_2fa' => '2-Factor-Authentifizierung deaktivieren',
|
||||
'enable_2fa' => '2-Faktor-Authentifizierung aktivieren',
|
||||
'header' => 'Kontosicherheit',
|
||||
|
|
|
@ -362,7 +362,7 @@ return [
|
|||
'2fa_enabled' => '2-Factor de Autenticación está habilitada en esta cuenta y será necesario iniciar la sesión en el panel de. Si usted desea deshabilitar el 2FA, simplemente ingrese un token válido a continuación y envíe el formulario.',
|
||||
'2fa_header' => '2-Factor De Autenticación',
|
||||
'2fa_qr' => 'Confgure 2FA en Su Dispositivo',
|
||||
'2fa_token_help' => 'Introduzca el 2FA Token generado por la aplicación (Google Authenticatior, Authy, etc.).',
|
||||
'2fa_token_help' => 'Introduzca el 2FA Token generado por la aplicación (Google Authenticator, Authy, etc.).',
|
||||
'disable_2fa' => 'Deshabilitar 2-Factor De Autenticación',
|
||||
'enable_2fa' => 'Habilitar 2-Factor De Autenticación',
|
||||
'header' => 'Seguridad De La Cuenta',
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
</div>
|
||||
</div>
|
||||
@else
|
||||
<form action="{{ route('admin.settings.mail') }}" method="POST">
|
||||
<form>
|
||||
<div class="box-body">
|
||||
<div class="row">
|
||||
<div class="form-group col-md-6">
|
||||
|
@ -98,7 +98,10 @@
|
|||
</div>
|
||||
<div class="box-footer">
|
||||
{{ csrf_field() }}
|
||||
<button type="submit" name="_method" value="PATCH" class="btn btn-sm btn-primary pull-right">Save</button>
|
||||
<div class="pull-right">
|
||||
<button type="button" id="testButton" class="btn btn-sm btn-success">Test</button>
|
||||
<button type="button" id="saveButton" class="btn btn-sm btn-primary">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@endif
|
||||
|
@ -106,3 +109,96 @@
|
|||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@section('footer-scripts')
|
||||
{!! Theme::js('js/laroute.js?t={cache-version}') !!}
|
||||
{!! Theme::js('vendor/jquery/jquery.min.js?t={cache-version}') !!}
|
||||
{!! Theme::js('vendor/sweetalert/sweetalert.min.js?t={cache-version}') !!}
|
||||
|
||||
<script>
|
||||
function saveSettings() {
|
||||
return $.ajax({
|
||||
method: 'PATCH',
|
||||
url: Router.route('admin.settings.mail'),
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({
|
||||
'mail:host': $('input[name="mail:host"]').val(),
|
||||
'mail:port': $('input[name="mail:port"]').val(),
|
||||
'mail:encryption': $('select[name="mail:encryption"]').val(),
|
||||
'mail:username': $('input[name="mail:username"]').val(),
|
||||
'mail:password': $('input[name="mail:password"]').val(),
|
||||
'mail:from:address': $('input[name="mail:from:address"]').val(),
|
||||
'mail:from:name': $('input[name="mail:from:name"]').val()
|
||||
}),
|
||||
headers: { 'X-CSRF-Token': $('input[name="_token"]').val() }
|
||||
}).fail(function (jqXHR) {
|
||||
showErrorDialog(jqXHR, 'save');
|
||||
});
|
||||
}
|
||||
|
||||
function testSettings() {
|
||||
swal({
|
||||
type: 'info',
|
||||
title: 'Test Mail Settings',
|
||||
text: 'Click "Test" to begin the test.',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: 'Test',
|
||||
closeOnConfirm: false,
|
||||
showLoaderOnConfirm: true
|
||||
}, function () {
|
||||
$.ajax({
|
||||
method: 'GET',
|
||||
url: Router.route('admin.settings.mail.test'),
|
||||
headers: { 'X-CSRF-Token': $('input[name="_token"]').val() }
|
||||
}).fail(function (jqXHR) {
|
||||
showErrorDialog(jqXHR, 'test');
|
||||
}).done(function () {
|
||||
swal({
|
||||
title: 'Success',
|
||||
text: 'The test message was sent successfully.',
|
||||
type: 'success'
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function saveAndTestSettings() {
|
||||
saveSettings().done(testSettings);
|
||||
}
|
||||
|
||||
function showErrorDialog(jqXHR, verb) {
|
||||
console.error(jqXHR);
|
||||
var errorText = '';
|
||||
if (!jqXHR.responseJSON) {
|
||||
errorText = jqXHR.responseText;
|
||||
} else if (jqXHR.responseJSON.error) {
|
||||
errorText = jqXHR.responseJSON.error;
|
||||
} else if (jqXHR.responseJSON.errors) {
|
||||
$.each(jqXHR.responseJSON.errors, function (i, v) {
|
||||
if (v.detail) {
|
||||
errorText += v.detail + ' ';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
swal({
|
||||
title: 'Whoops!',
|
||||
text: 'An error occurred while attempting to ' + verb + ' mail settings: ' + errorText,
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
$('#testButton').on('click', saveAndTestSettings);
|
||||
$('#saveButton').on('click', function () {
|
||||
saveSettings().done(function () {
|
||||
swal({
|
||||
title: 'Success',
|
||||
text: 'Mail settings have been updated successfully and the queue worker was restarted to apply these changes.',
|
||||
type: 'success'
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endsection
|
||||
|
|
|
@ -60,7 +60,5 @@
|
|||
particlesJS.load('particles-js', '{!! Theme::url('vendor/particlesjs/particles.json?t={cache-version}') !!}', function() {});
|
||||
})
|
||||
</script>
|
||||
|
||||
@if(config('pterodactyl.lang.in_context')) {!! Theme::js('vendor/phraseapp/phraseapp.js?t={cache-version}') !!} @endif
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -286,9 +286,6 @@
|
|||
{!! Theme::js('vendor/socketio/socket.io.v203.min.js?t={cache-version}') !!}
|
||||
{!! Theme::js('vendor/bootstrap-notify/bootstrap-notify.min.js?t={cache-version}') !!}
|
||||
{!! Theme::js('js/autocomplete.js?t={cache-version}') !!}
|
||||
@if(config('pterodactyl.lang.in_context'))
|
||||
{!! Theme::js('vendor/phraseapp/phraseapp.js?t={cache-version}') !!}
|
||||
@endif
|
||||
|
||||
@if(Auth::user()->root_admin)
|
||||
<script>
|
||||
|
|
|
@ -64,6 +64,7 @@ Route::group(['prefix' => 'databases'], function () {
|
|||
Route::group(['prefix' => 'settings'], function () {
|
||||
Route::get('/', 'Settings\IndexController@index')->name('admin.settings');
|
||||
Route::get('/mail', 'Settings\MailController@index')->name('admin.settings.mail');
|
||||
Route::get('/mail/test', 'Settings\MailController@test')->name('admin.settings.mail.test');
|
||||
Route::get('/advanced', 'Settings\AdvancedController@index')->name('admin.settings.advanced');
|
||||
|
||||
Route::patch('/', 'Settings\IndexController@update');
|
||||
|
|
1
storage/framework/cache/.gitignore
vendored
1
storage/framework/cache/.gitignore
vendored
|
@ -1,2 +1,3 @@
|
|||
*
|
||||
!data/
|
||||
!.gitignore
|
2
storage/framework/cache/data/.gitignore
vendored
Normal file
2
storage/framework/cache/data/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
*
|
||||
!.gitignore
|
82
tests/Unit/Http/Controllers/Admin/MailControllerTest.php
Normal file
82
tests/Unit/Http/Controllers/Admin/MailControllerTest.php
Normal file
|
@ -0,0 +1,82 @@
|
|||
<?php
|
||||
|
||||
namespace Tests\Unit\Http\Controllers;
|
||||
|
||||
use Mockery as m;
|
||||
use Prologue\Alerts\AlertsMessageBag;
|
||||
use Illuminate\Contracts\Console\Kernel;
|
||||
use Illuminate\Contracts\Encryption\Encrypter;
|
||||
use Illuminate\Contracts\Config\Repository as ConfigRepository;
|
||||
use Pterodactyl\Http\Controllers\Admin\Settings\MailController;
|
||||
use Pterodactyl\Contracts\Repository\SettingsRepositoryInterface;
|
||||
|
||||
class MailControllerTest extends ControllerTestCase
|
||||
{
|
||||
/**
|
||||
* @var \Prologue\Alerts\AlertsMessageBag
|
||||
*/
|
||||
private $alert;
|
||||
|
||||
/**
|
||||
* @var \Illuminate\Contracts\Config\Repository
|
||||
*/
|
||||
private $configRepository;
|
||||
|
||||
/**
|
||||
* @var \Illuminate\Contracts\Encryption\Encrypter
|
||||
*/
|
||||
private $encrypter;
|
||||
|
||||
/**
|
||||
* @var \Illuminate\Contracts\Console\Kernel
|
||||
*/
|
||||
private $kernel;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Contracts\Repository\SettingsRepositoryInterface
|
||||
*/
|
||||
private $settingsRepositoryInterface;
|
||||
|
||||
/**
|
||||
* Setup tests.
|
||||
*/
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->alert = m::mock(AlertsMessageBag::class);
|
||||
$this->configRepository = m::mock(ConfigRepository::class);
|
||||
$this->encrypter = m::mock(Encrypter::class);
|
||||
$this->kernel = m::mock(Kernel::class);
|
||||
$this->settingsRepositoryInterface = m::mock(SettingsRepositoryInterface::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the mail controller for viewing mail settings page.
|
||||
*/
|
||||
public function testIndex()
|
||||
{
|
||||
$this->configRepository->shouldReceive('get');
|
||||
|
||||
$response = $this->getController()->index();
|
||||
|
||||
$this->assertIsViewResponse($response);
|
||||
$this->assertViewNameEquals('admin.settings.mail', $response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a MailController using our mocks.
|
||||
*
|
||||
* @return MailController
|
||||
*/
|
||||
public function getController()
|
||||
{
|
||||
return new MailController(
|
||||
$this->alert,
|
||||
$this->configRepository,
|
||||
$this->encrypter,
|
||||
$this->kernel,
|
||||
$this->settingsRepositoryInterface
|
||||
);
|
||||
}
|
||||
}
|
|
@ -73,7 +73,7 @@ class IndexControllerTest extends ControllerTestCase
|
|||
|
||||
$this->request->shouldReceive('input')->with('query')->once()->andReturn('searchTerm');
|
||||
$this->repository->shouldReceive('setSearchTerm')->with('searchTerm')->once()->andReturnSelf()
|
||||
->shouldReceive('filterUserAccessServers')->with($model, User::FILTER_LEVEL_ALL)
|
||||
->shouldReceive('filterUserAccessServers')->with($model, User::FILTER_LEVEL_ALL, config('pterodactyl.paginate.frontend.servers'))
|
||||
->once()->andReturn($paginator);
|
||||
|
||||
$response = $this->controller->index($this->request);
|
||||
|
|
|
@ -51,21 +51,34 @@ class NodeUpdateServiceTest extends TestCase
|
|||
public function testNodeIsUpdatedAndDaemonSecretIsReset()
|
||||
{
|
||||
$model = factory(Node::class)->make();
|
||||
$updatedModel = factory(Node::class)->make([
|
||||
'name' => 'New Name',
|
||||
'daemonSecret' => 'abcd1234',
|
||||
]);
|
||||
|
||||
$this->getFunctionMock('\\Pterodactyl\\Services\\Nodes', 'str_random')
|
||||
->expects($this->once())->willReturn('random_string');
|
||||
->expects($this->once())->willReturn($updatedModel->daemonSecret);
|
||||
|
||||
$this->connection->shouldReceive('beginTransaction')->withNoArgs()->once()->andReturnNull();
|
||||
$this->repository->shouldReceive('update')->with($model->id, [
|
||||
'name' => 'NewName',
|
||||
'daemonSecret' => 'random_string',
|
||||
'name' => $updatedModel->name,
|
||||
'daemonSecret' => $updatedModel->daemonSecret,
|
||||
])->andReturn($model);
|
||||
|
||||
$this->configRepository->shouldReceive('setNode')->with($model)->once()->andReturnSelf()
|
||||
->shouldReceive('update')->withNoArgs()->once()->andReturn(new Response);
|
||||
$cloned = $updatedModel->replicate(['daemonSecret']);
|
||||
$cloned->daemonSecret = $model->daemonSecret;
|
||||
|
||||
$this->configRepository->shouldReceive('setNode')->with(m::on(function ($model) use ($updatedModel) {
|
||||
return $model->daemonSecret !== $updatedModel->daemonSecret;
|
||||
}))->once()->andReturnSelf();
|
||||
|
||||
$this->configRepository->shouldReceive('update')->with([
|
||||
'keys' => ['abcd1234'],
|
||||
])->once()->andReturn(new Response);
|
||||
|
||||
$this->connection->shouldReceive('commit')->withNoArgs()->once()->andReturnNull();
|
||||
|
||||
$response = $this->getService()->handle($model, ['name' => 'NewName', 'reset_secret' => true]);
|
||||
$response = $this->getService()->handle($model, ['name' => $updatedModel->name], true);
|
||||
$this->assertInstanceOf(Node::class, $response);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue