Begin moving packs to new service mechanisms, refactor exceptions for services

This commit is contained in:
Dane Everitt 2017-08-18 22:19:06 -05:00
parent 46cb71e69d
commit 9d3dca87f2
No known key found for this signature in database
GPG key ID: EEA66103B3D71F53
62 changed files with 492 additions and 303 deletions

View file

@ -13,5 +13,5 @@ Default panel users:
MySQL is accessible using root/pterodactyl or pterodactyl/pterodactyl
Services for pteroq and mailhog are running
Service for pteroq and mailhog are running
#####################################################

View file

@ -3,6 +3,7 @@ dist: trusty
php:
- '7.0'
- '7.1'
- '7.2'
sudo: false
cache:
directories:

View file

@ -245,7 +245,7 @@ spatie/laravel-fractal (4.0.0 => 4.0.1)
* New theme applied to Admin CP. Many graphical changes were made, some data was moved around and some display data changed. Too much was changed to feasibly log it all in here. Major breaking changes or notable new features will be logged.
* New server creation page now makes significantly less AJAX calls and is much quicker to respond.
* Server and Node view pages wee modified to split tabs into individual pages to make re-themeing and modifications significantly easier, and reduce MySQL query loads on page.
* `[pre.4]` — Services and Pack magement overhauled to be faster, cleaner, and more extensible in the future.
* `[pre.4]` — Service and Pack magement overhauled to be faster, cleaner, and more extensible in the future.
* Most of the backend `UnhandledException` display errors now include a clearer error that directs admins to the program's logs.
* Table seeders for services now can be run during upgrades and will attempt to locate and update, or create new if not found in the database.
* Many structural changes to the database and `Pterodactyl\Models` classes that would flood this changelog if they were all included. All required migrations included to handle database changes.

View file

@ -0,0 +1,39 @@
<?php
/*
* Pterodactyl - Panel
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Contracts\Repository;
use Pterodactyl\Contracts\Repository\Attributes\SearchableInterface;
interface PackRepositoryInterface extends RepositoryInterface, SearchableInterface
{
/**
* Return all of the file archives for a given pack.
*
* @param int $id
* @param bool $collection
* @return object|\Illuminate\Support\Collection
*/
public function getFileArchives($id, $collection = false);
}

View file

@ -22,7 +22,7 @@
* SOFTWARE.
*/
namespace Pterodactyl\Exceptions\Services;
namespace Pterodactyl\Exceptions\Service;
class HasActiveServersException extends \Exception
{

View file

@ -0,0 +1,30 @@
<?php
/*
* Pterodactyl - Panel
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Exceptions\Service\Pack;
class InvalidFileMimeTypeException extends \Exception
{
//
}

View file

@ -0,0 +1,30 @@
<?php
/*
* Pterodactyl - Panel
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Exceptions\Service\Pack;
class InvalidFileUploadException extends \Exception
{
//
}

View file

@ -22,7 +22,7 @@
* SOFTWARE.
*/
namespace Pterodactyl\Exceptions\Services\Server;
namespace Pterodactyl\Exceptions\Service\Server;
use Exception;

View file

@ -22,7 +22,7 @@
* SOFTWARE.
*/
namespace Pterodactyl\Exceptions\Services\ServiceOption;
namespace Pterodactyl\Exceptions\Service\ServiceOption;
class InvalidCopyFromException extends \Exception
{

View file

@ -22,7 +22,7 @@
* SOFTWARE.
*/
namespace Pterodactyl\Exceptions\Services\ServiceOption;
namespace Pterodactyl\Exceptions\Service\ServiceOption;
class NoParentConfigurationFoundException extends \Exception
{

View file

@ -22,7 +22,7 @@
* SOFTWARE.
*/
namespace Pterodactyl\Exceptions\Services\ServiceVariable;
namespace Pterodactyl\Exceptions\Service\ServiceVariable;
use Exception;

View file

@ -30,7 +30,7 @@ use Prologue\Alerts\AlertsMessageBag;
use Pterodactyl\Models\ServiceOption;
use Pterodactyl\Http\Controllers\Controller;
use Pterodactyl\Http\Requests\Admin\Service\EditOptionScript;
use Pterodactyl\Exceptions\Services\HasActiveServersException;
use Pterodactyl\Exceptions\Service\HasActiveServersException;
use Pterodactyl\Services\Services\Options\OptionUpdateService;
use Pterodactyl\Contracts\Repository\ServiceRepositoryInterface;
use Pterodactyl\Services\Services\Options\OptionCreationService;
@ -38,8 +38,8 @@ use Pterodactyl\Services\Services\Options\OptionDeletionService;
use Pterodactyl\Http\Requests\Admin\Service\ServiceOptionFormRequest;
use Pterodactyl\Services\Services\Options\InstallScriptUpdateService;
use Pterodactyl\Contracts\Repository\ServiceOptionRepositoryInterface;
use Pterodactyl\Exceptions\Services\ServiceOption\InvalidCopyFromException;
use Pterodactyl\Exceptions\Services\ServiceOption\NoParentConfigurationFoundException;
use Pterodactyl\Exceptions\Service\ServiceOption\InvalidCopyFromException;
use Pterodactyl\Exceptions\Service\ServiceOption\NoParentConfigurationFoundException;
class OptionController extends Controller
{

View file

@ -30,7 +30,7 @@ use Pterodactyl\Http\Controllers\Controller;
use Pterodactyl\Services\Services\ServiceUpdateService;
use Pterodactyl\Services\Services\ServiceCreationService;
use Pterodactyl\Services\Services\ServiceDeletionService;
use Pterodactyl\Exceptions\Services\HasActiveServersException;
use Pterodactyl\Exceptions\Service\HasActiveServersException;
use Pterodactyl\Http\Requests\Admin\Service\ServiceFormRequest;
use Pterodactyl\Contracts\Repository\ServiceRepositoryInterface;
use Pterodactyl\Http\Requests\Admin\Service\ServiceFunctionsFormRequest;

View file

@ -83,7 +83,7 @@ class VariableController extends Controller
* @return \Illuminate\Http\RedirectResponse
*
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
* @throws \Pterodactyl\Exceptions\Services\ServiceVariable\ReservedVariableNameException
* @throws \Pterodactyl\Exceptions\Service\ServiceVariable\ReservedVariableNameException
*/
public function store(OptionVariableFormRequest $request, ServiceOption $option)
{
@ -117,7 +117,7 @@ class VariableController extends Controller
* @throws \Pterodactyl\Exceptions\DisplayException
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
* @throws \Pterodactyl\Exceptions\Services\ServiceVariable\ReservedVariableNameException
* @throws \Pterodactyl\Exceptions\Service\ServiceVariable\ReservedVariableNameException
*/
public function update(OptionVariableFormRequest $request, ServiceOption $option, ServiceVariable $variable)
{

View file

@ -26,12 +26,15 @@ namespace Pterodactyl\Models;
use File;
use Storage;
use Sofa\Eloquence\Eloquence;
use Sofa\Eloquence\Validable;
use Illuminate\Database\Eloquent\Model;
use Nicolaslopezj\Searchable\SearchableTrait;
use Sofa\Eloquence\Contracts\CleansAttributes;
use Sofa\Eloquence\Contracts\Validable as ValidableContract;
class Pack extends Model
class Pack extends Model implements CleansAttributes, ValidableContract
{
use SearchableTrait;
use Eloquence, Validable;
/**
* The table associated with the model.
@ -46,7 +49,33 @@ class Pack extends Model
* @var array
*/
protected $fillable = [
'option_id', 'name', 'version', 'description', 'selectable', 'visible', 'locked',
'option_id', 'uuid', 'name', 'version', 'description', 'selectable', 'visible', 'locked',
];
/**
* @var array
*/
protected static $applicationRules = [
'name' => 'required',
'version' => 'required',
'description' => 'sometimes',
'selectable' => 'sometimes|required',
'visible' => 'sometimes|required',
'locked' => 'sometimes|required',
'option_id' => 'required',
];
/**
* @var array
*/
protected static $dataIntegrityRules = [
'name' => 'string',
'version' => 'string',
'description' => 'nullable|string',
'selectable' => 'boolean',
'visible' => 'boolean',
'locked' => 'boolean',
'option_id' => 'exists:service_options,id',
];
/**
@ -66,18 +95,13 @@ class Pack extends Model
*
* @var array
*/
protected $searchable = [
'columns' => [
'packs.name' => 10,
'packs.uuid' => 8,
'service_options.name' => 6,
'service_options.tag' => 5,
'service_options.docker_image' => 5,
'packs.version' => 2,
],
'joins' => [
'service_options' => ['packs.option_id', 'service_options.id'],
],
protected $searchableColumns = [
'name' => 10,
'uuid' => 8,
'option.name' => 6,
'option.tag' => 5,
'option.docker_image' => 5,
'version' => 2,
];
/**
@ -85,6 +109,7 @@ class Pack extends Model
*
* @param bool $collection
* @return \Illuminate\Support\Collection|object
* @deprecated
*/
public function files($collection = false)
{

View file

@ -22,20 +22,22 @@
* SOFTWARE.
*/
namespace Pterodactyl\Repositories\Eloquent\Attributes;
namespace Pterodactyl\Repositories\Concerns;
use Pterodactyl\Repositories\Eloquent\EloquentRepository;
use Pterodactyl\Contracts\Repository\Attributes\SearchableInterface;
abstract class SearchableRepository extends EloquentRepository implements SearchableInterface
trait Searchable
{
/**
* The term to search.
*
* @var bool|string
*/
protected $searchTerm = false;
/**
* {@inheritdoc}
* Perform a search of the model using the given term.
*
* @param string $term
* @return $this
*/
public function search($term)
{

View file

@ -28,10 +28,12 @@ use Pterodactyl\Models\Location;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Exceptions\Repository\RecordNotFoundException;
use Pterodactyl\Contracts\Repository\LocationRepositoryInterface;
use Pterodactyl\Repositories\Eloquent\Attributes\SearchableRepository;
use Pterodactyl\Repositories\Concerns\Searchable;
class LocationRepository extends SearchableRepository implements LocationRepositoryInterface
class LocationRepository extends EloquentRepository implements LocationRepositoryInterface
{
use Searchable;
/**
* @var string
*/

View file

@ -27,10 +27,12 @@ namespace Pterodactyl\Repositories\Eloquent;
use Pterodactyl\Models\Node;
use Pterodactyl\Contracts\Repository\NodeRepositoryInterface;
use Pterodactyl\Exceptions\Repository\RecordNotFoundException;
use Pterodactyl\Repositories\Eloquent\Attributes\SearchableRepository;
use Pterodactyl\Repositories\Concerns\Searchable;
class NodeRepository extends SearchableRepository implements NodeRepositoryInterface
class NodeRepository extends EloquentRepository implements NodeRepositoryInterface
{
use Searchable;
/**
* {@inheritdoc}
*/

View file

@ -0,0 +1,65 @@
<?php
/*
* Pterodactyl - Panel
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Repositories\Eloquent;
use Pterodactyl\Models\Pack;
use Illuminate\Contracts\Filesystem\Factory as FilesystemFactory;
use Pterodactyl\Repositories\Concerns\Searchable;
use Pterodactyl\Contracts\Repository\PackRepositoryInterface;
class PackRepository extends EloquentRepository implements PackRepositoryInterface
{
use Searchable;
/**
* {@inheritdoc}
*/
public function model()
{
return Pack::class;
}
/**
* {@inheritdoc}
*/
public function getFileArchives($id, $collection = false)
{
$pack = $this->getBuilder()->find($id, ['id', 'uuid']);
$storage = $this->app->make(FilesystemFactory::class);
$files = collect($storage->disk('default')->files('packs/' . $pack->uuid));
$files = $files->map(function ($file) {
$path = storage_path('app/' . $file);
return (object) [
'name' => basename($file),
'hash' => sha1_file($path),
'size' => human_readable($path),
];
});
return ($collection) ? $files : (object) $files->all();
}
}

View file

@ -25,12 +25,14 @@
namespace Pterodactyl\Repositories\Eloquent;
use Pterodactyl\Models\Server;
use Pterodactyl\Repositories\Concerns\Searchable;
use Pterodactyl\Exceptions\Repository\RecordNotFoundException;
use Pterodactyl\Contracts\Repository\ServerRepositoryInterface;
use Pterodactyl\Repositories\Eloquent\Attributes\SearchableRepository;
class ServerRepository extends SearchableRepository implements ServerRepositoryInterface
class ServerRepository extends EloquentRepository implements ServerRepositoryInterface
{
use Searchable;
/**
* {@inheritdoc}
*/

View file

@ -26,12 +26,14 @@ namespace Pterodactyl\Repositories\Eloquent;
use Pterodactyl\Models\User;
use Illuminate\Foundation\Application;
use Pterodactyl\Repositories\Concerns\Searchable;
use Pterodactyl\Contracts\Repository\UserRepositoryInterface;
use Illuminate\Contracts\Config\Repository as ConfigRepository;
use Pterodactyl\Repositories\Eloquent\Attributes\SearchableRepository;
class UserRepository extends SearchableRepository implements UserRepositoryInterface
class UserRepository extends EloquentRepository implements UserRepositoryInterface
{
use Searchable;
/**
* @var \Illuminate\Contracts\Config\Repository
*/

View file

@ -1,163 +0,0 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Repositories;
use Cron;
use Validator;
use Pterodactyl\Models\Task;
use Pterodactyl\Models\User;
use Pterodactyl\Models\Server;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Exceptions\DisplayValidationException;
class TaskRepository
{
/**
* The default values to use for new tasks.
*
* @var array
*/
protected $defaults = [
'year' => '*',
'day_of_week' => '*',
'month' => '*',
'day_of_month' => '*',
'hour' => '*',
'minute' => '*/30',
];
/**
* Task action types.
*
* @var array
*/
protected $actions = [
'command',
'power',
];
/**
* Deletes a given task.
*
* @param int $id
* @return bool
*/
public function delete($id)
{
$task = Task::findOrFail($id);
$task->delete();
}
/**
* Toggles a task active or inactive.
*
* @param int $id
* @return bool
*/
public function toggle($id)
{
$task = Task::findOrFail($id);
$task->active = ! $task->active;
$task->queued = false;
$task->save();
return $task->active;
}
/**
* Create a new scheduled task for a given server.
*
* @param int $server
* @param int $user
* @param array $data
* @return \Pterodactyl\Models\Task
*
* @throws \Pterodactyl\Exceptions\DisplayException
* @throws \Pterodactyl\Exceptions\DisplayValidationException
*/
public function create($server, $user, $data)
{
$server = Server::findOrFail($server);
$user = User::findOrFail($user);
$validator = Validator::make($data, [
'action' => 'string|required',
'data' => 'string|required',
'year' => 'string|sometimes',
'day_of_week' => 'string|sometimes',
'month' => 'string|sometimes',
'day_of_month' => 'string|sometimes',
'hour' => 'string|sometimes',
'minute' => 'string|sometimes',
]);
if ($validator->fails()) {
throw new DisplayValidationException(json_encode($validator->errors()));
}
if (! in_array($data['action'], $this->actions)) {
throw new DisplayException('The action provided is not valid.');
}
$cron = $this->defaults;
foreach ($this->defaults as $setting => $value) {
if (array_key_exists($setting, $data) && ! is_null($data[$setting]) && $data[$setting] !== '') {
$cron[$setting] = $data[$setting];
}
}
// Check that is this a valid Cron Entry
try {
$buildCron = Cron::factory(sprintf('%s %s %s %s %s %s',
$cron['minute'],
$cron['hour'],
$cron['day_of_month'],
$cron['month'],
$cron['day_of_week'],
$cron['year']
));
} catch (\Exception $ex) {
throw $ex;
}
return Task::create([
'user_id' => $user->id,
'server_id' => $server->id,
'active' => 1,
'action' => $data['action'],
'data' => $data['data'],
'queued' => 0,
'year' => $cron['year'],
'day_of_week' => $cron['day_of_week'],
'month' => $cron['month'],
'day_of_month' => $cron['day_of_month'],
'hour' => $cron['hour'],
'minute' => $cron['minute'],
'last_run' => null,
'next_run' => $buildCron->getNextRunDate(),
]);
}
}

View file

@ -0,0 +1,119 @@
<?php
/*
* Pterodactyl - Panel
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Services\Packs;
use Ramsey\Uuid\Uuid;
use Illuminate\Database\ConnectionInterface;
use Pterodactyl\Contracts\Repository\PackRepositoryInterface;
use Illuminate\Contracts\Config\Repository as ConfigRepository;
use Illuminate\Contracts\Filesystem\Factory as FilesystemFactory;
use Pterodactyl\Exceptions\Service\Pack\InvalidFileUploadException;
use Pterodactyl\Exceptions\Service\Pack\InvalidFileMimeTypeException;
class PackCreationService
{
/**
* @var \Illuminate\Contracts\Config\Repository
*/
protected $config;
/**
* @var \Illuminate\Database\ConnectionInterface
*/
protected $connection;
/**
* @var \Pterodactyl\Contracts\Repository\PackRepositoryInterface
*/
protected $repository;
/**
* @var \Illuminate\Contracts\Filesystem\Factory
*/
protected $storage;
/**
* PackCreationService constructor.
*
* @param \Illuminate\Contracts\Config\Repository $config
* @param \Illuminate\Database\ConnectionInterface $connection
* @param \Illuminate\Contracts\Filesystem\Factory $storage
* @param \Pterodactyl\Contracts\Repository\PackRepositoryInterface $repository
*/
public function __construct(
ConfigRepository $config,
ConnectionInterface $connection,
FilesystemFactory $storage,
PackRepositoryInterface $repository
) {
$this->config = $config;
$this->connection = $connection;
$this->repository = $repository;
$this->storage = $storage;
}
/**
* Add a new service pack to the system.
*
* @param array $data
* @param \Illuminate\Http\UploadedFile|null $file
* @return \Pterodactyl\Models\Pack
*
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
* @throws \Pterodactyl\Exceptions\Service\Pack\InvalidFileMimeTypeException
* @throws \Pterodactyl\Exceptions\Service\Pack\InvalidFileUploadException
*/
public function handle(array $data, $file = null)
{
if (! is_null($file)) {
if (! $file->isValid()) {
throw new InvalidFileUploadException;
}
if (! in_array($file->getMimeType(), $this->config->get('pterodactyl.files.pack_types'))) {
throw new InvalidFileMimeTypeException;
}
}
// Transform values to boolean
$data['selectable'] = isset($data['selectable']);
$data['visible'] = isset($data['visible']);
$data['locked'] = isset($data['locked']);
$this->connection->beginTransaction();
$pack = $this->repository->create(array_merge(
['uuid' => Uuid::uuid4()], $data
));
$this->storage->disk('default')->makeDirectory('packs/' . $pack->uuid);
if (! is_null($file)) {
$file->storeAs('packs/' . $pack->uuid, 'archive.tar.gz');
}
$this->connection->commit();
return $pack;
}
}

View file

@ -26,7 +26,7 @@ namespace Pterodactyl\Services\Services\Options;
use Pterodactyl\Models\ServiceOption;
use Pterodactyl\Contracts\Repository\ServiceOptionRepositoryInterface;
use Pterodactyl\Exceptions\Services\ServiceOption\InvalidCopyFromException;
use Pterodactyl\Exceptions\Service\ServiceOption\InvalidCopyFromException;
class InstallScriptUpdateService
{
@ -53,7 +53,7 @@ class InstallScriptUpdateService
*
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
* @throws \Pterodactyl\Exceptions\Services\ServiceOption\InvalidCopyFromException
* @throws \Pterodactyl\Exceptions\Service\ServiceOption\InvalidCopyFromException
*/
public function handle($option, array $data)
{

View file

@ -25,7 +25,7 @@
namespace Pterodactyl\Services\Services\Options;
use Pterodactyl\Contracts\Repository\ServiceOptionRepositoryInterface;
use Pterodactyl\Exceptions\Services\ServiceOption\NoParentConfigurationFoundException;
use Pterodactyl\Exceptions\Service\ServiceOption\NoParentConfigurationFoundException;
class OptionCreationService
{
@ -51,7 +51,7 @@ class OptionCreationService
* @return \Pterodactyl\Models\ServiceOption
*
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
* @throws \Pterodactyl\Exceptions\Services\ServiceOption\NoParentConfigurationFoundException
* @throws \Pterodactyl\Exceptions\Service\ServiceOption\NoParentConfigurationFoundException
*/
public function handle(array $data)
{

View file

@ -24,7 +24,7 @@
namespace Pterodactyl\Services\Services\Options;
use Pterodactyl\Exceptions\Services\HasActiveServersException;
use Pterodactyl\Exceptions\Service\HasActiveServersException;
use Pterodactyl\Contracts\Repository\ServerRepositoryInterface;
use Pterodactyl\Contracts\Repository\ServiceOptionRepositoryInterface;
@ -60,7 +60,7 @@ class OptionDeletionService
* @param int $option
* @return int
*
* @throws \Pterodactyl\Exceptions\Services\HasActiveServersException
* @throws \Pterodactyl\Exceptions\Service\HasActiveServersException
*/
public function handle($option)
{

View file

@ -26,7 +26,7 @@ namespace Pterodactyl\Services\Services\Options;
use Pterodactyl\Models\ServiceOption;
use Pterodactyl\Contracts\Repository\ServiceOptionRepositoryInterface;
use Pterodactyl\Exceptions\Services\ServiceOption\NoParentConfigurationFoundException;
use Pterodactyl\Exceptions\Service\ServiceOption\NoParentConfigurationFoundException;
class OptionUpdateService
{
@ -53,7 +53,7 @@ class OptionUpdateService
*
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
* @throws \Pterodactyl\Exceptions\Services\ServiceOption\NoParentConfigurationFoundException
* @throws \Pterodactyl\Exceptions\Service\ServiceOption\NoParentConfigurationFoundException
*/
public function handle($option, array $data)
{

View file

@ -24,7 +24,7 @@
namespace Pterodactyl\Services\Services;
use Pterodactyl\Exceptions\Services\HasActiveServersException;
use Pterodactyl\Exceptions\Service\HasActiveServersException;
use Pterodactyl\Contracts\Repository\ServerRepositoryInterface;
use Pterodactyl\Contracts\Repository\ServiceRepositoryInterface;
@ -60,7 +60,7 @@ class ServiceDeletionService
* @param int $service
* @return int
*
* @throws \Pterodactyl\Exceptions\Services\HasActiveServersException
* @throws \Pterodactyl\Exceptions\Service\HasActiveServersException
*/
public function handle($service)
{

View file

@ -28,7 +28,7 @@ use Pterodactyl\Models\ServiceOption;
use Pterodactyl\Models\ServiceVariable;
use Pterodactyl\Contracts\Repository\ServiceOptionRepositoryInterface;
use Pterodactyl\Contracts\Repository\ServiceVariableRepositoryInterface;
use Pterodactyl\Exceptions\Services\ServiceVariable\ReservedVariableNameException;
use Pterodactyl\Exceptions\Service\ServiceVariable\ReservedVariableNameException;
class VariableCreationService
{
@ -58,7 +58,7 @@ class VariableCreationService
* @return \Pterodactyl\Models\ServiceVariable
*
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
* @throws \Pterodactyl\Exceptions\Services\ServiceVariable\ReservedVariableNameException
* @throws \Pterodactyl\Exceptions\Service\ServiceVariable\ReservedVariableNameException
*/
public function handle($option, array $data)
{

View file

@ -27,7 +27,7 @@ namespace Pterodactyl\Services\Services\Variables;
use Pterodactyl\Models\ServiceVariable;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Contracts\Repository\ServiceVariableRepositoryInterface;
use Pterodactyl\Exceptions\Services\ServiceVariable\ReservedVariableNameException;
use Pterodactyl\Exceptions\Service\ServiceVariable\ReservedVariableNameException;
class VariableUpdateService
{
@ -56,7 +56,7 @@ class VariableUpdateService
* @throws \Pterodactyl\Exceptions\DisplayException
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
* @throws \Pterodactyl\Exceptions\Services\ServiceVariable\ReservedVariableNameException
* @throws \Pterodactyl\Exceptions\Service\ServiceVariable\ReservedVariableNameException
*/
public function handle($variable, array $data)
{

View file

@ -1,5 +1,5 @@
<?php
/**
/*
* Pterodactyl - Panel
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
*
@ -22,52 +22,16 @@
* SOFTWARE.
*/
namespace Pterodactyl\Repositories;
class HelperRepository
{
if (! function_exists('human_readable')) {
/**
* Listing of editable files in the control panel.
* Generate a human-readable filesize for a given file path.
*
* @var array
*/
protected static $editable = [
'application/json',
'application/javascript',
'application/xml',
'application/xhtml+xml',
'text/xml',
'text/css',
'text/html',
'text/plain',
'text/x-perl',
'text/x-shellscript',
'inode/x-empty',
];
/**
* Converts from bytes to the largest possible size that is still readable.
*
* @param int $bytes
* @param int $decimals
* @param string $path
* @param int $precision
* @return string
* @deprecated
*/
public static function bytesToHuman($bytes, $decimals = 2)
function human_readable($path, $precision = 2)
{
$sz = explode(',', 'B,KB,MB,GB');
$factor = floor((strlen($bytes) - 1) / 3);
return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) . ' ' . $sz[$factor];
}
/**
* Returns array of editable files.
*
* @return array
*/
public static function editableFiles()
{
return self::$editable;
return app('file')->humanReadableSize($path, $precision);
}
}

View file

@ -54,6 +54,9 @@
"classmap": [
"database"
],
"files": [
"app/helpers.php"
],
"psr-4": {
"Pterodactyl\\": "app/"
}

View file

@ -135,6 +135,33 @@ return [
'in_context' => env('PHRASE_IN_CONTEXT', false),
],
/*
|--------------------------------------------------------------------------
| File Editor
|--------------------------------------------------------------------------
|
| This array includes the MIME filetypes that can be edited via the web.
*/
'files' => [
'editable' => [
'application/json',
'application/javascript',
'application/xml',
'application/xhtml+xml',
'inode/x-empty',
'text/xml',
'text/css',
'text/html',
'text/plain',
'text/x-perl',
'text/x-shellscript',
],
'pack_types' => [
'application/gzip',
'application/x-gzip',
],
],
/*
|--------------------------------------------------------------------------
| JSON Response Routes

View file

@ -4,7 +4,7 @@ return [
/*
|--------------------------------------------------------------------------
| Third Party Services
| Third Party Service
|--------------------------------------------------------------------------
|
| This file is for storing the credentials for third party services such

View file

@ -0,0 +1,36 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class RemovePackWhenParentServiceOptionIsDeleted extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('packs', function (Blueprint $table) {
$table->dropForeign(['option_id']);
$table->foreign('option_id')->references('id')->on('service_options')->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('packs', function (Blueprint $table) {
$table->dropForeign(['option_id']);
$table->foreign('option_id')->references('id')->on('service_options');
});
}
}

File diff suppressed because one or more lines are too long

View file

@ -173,7 +173,7 @@ return [
'service_header' => 'Service Control',
'service' => [
'list' => [
'title' => 'List Services',
'title' => 'List Service',
'desc' => 'Allows listing of all services configured on the system.',
],
'view' => [

View file

@ -20,14 +20,14 @@
@extends('layouts.admin')
@section('title')
Services &rarr; {{ $service->name }} &rarr; Functions
Service &rarr; {{ $service->name }} &rarr; Functions
@endsection
@section('content-header')
<h1>{{ $service->name }}<small>Extend the default daemon functions using this service file.</small></h1>
<ol class="breadcrumb">
<li><a href="{{ route('admin.index') }}">Admin</a></li>
<li><a href="{{ route('admin.services') }}">Services</a></li>
<li><a href="{{ route('admin.services') }}">Service</a></li>
<li><a href="{{ route('admin.services.view', $service->id) }}">{{ $service->name }}</a></li>
<li class="active">Functions</li>
</ol>

View file

@ -20,14 +20,14 @@
@extends('layouts.admin')
@section('title')
Services
Service
@endsection
@section('content-header')
<h1>Services<small>All services currently available on this system.</small></h1>
<h1>Service<small>All services currently available on this system.</small></h1>
<ol class="breadcrumb">
<li><a href="{{ route('admin.index') }}">Admin</a></li>
<li class="active">Services</li>
<li class="active">Service</li>
</ol>
@endsection
@ -36,7 +36,7 @@
<div class="col-xs-12">
<div class="box">
<div class="box-header with-border">
<h3 class="box-title">Configured Services</h3>
<h3 class="box-title">Configured Service</h3>
<div class="box-tools">
<a href="{{ route('admin.services.new') }}"><button class="btn btn-primary btn-sm">Create New</button></a>
</div>

View file

@ -27,7 +27,7 @@
<h1>New Service<small>Configure a new service to deploy to all nodes.</small></h1>
<ol class="breadcrumb">
<li><a href="{{ route('admin.index') }}">Admin</a></li>
<li><a href="{{ route('admin.services') }}">Services</a></li>
<li><a href="{{ route('admin.services') }}">Service</a></li>
<li class="active">New</li>
</ol>
@endsection
@ -64,7 +64,7 @@
<label class="control-label">Folder Name</label>
<div>
<input type="text" name="folder" class="form-control" value="{{ old('folder') }}" />
<p class="text-muted"><small>Services are downloaded by the daemon and stored in a folder using this name. The storage location is <code>/srv/daemon/services/{NAME}</code> by default.</small></p>
<p class="text-muted"><small>Service are downloaded by the daemon and stored in a folder using this name. The storage location is <code>/srv/daemon/services/{NAME}</code> by default.</small></p>
</div>
</div>
<div class="form-group">

View file

@ -20,14 +20,14 @@
@extends('layouts.admin')
@section('title')
Services &rarr; New Option
Service &rarr; New Option
@endsection
@section('content-header')
<h1>New Option<small>Create a new service option to assign to servers.</small></h1>
<ol class="breadcrumb">
<li><a href="{{ route('admin.index') }}">Admin</a></li>
<li><a href="{{ route('admin.services') }}">Services</a></li>
<li><a href="{{ route('admin.services') }}">Service</a></li>
<li class="active">New Service Option</li>
</ol>
@endsection

View file

@ -20,14 +20,14 @@
@extends('layouts.admin')
@section('title')
Services &rarr; Option: {{ $option->name }} &rarr; Scripts
Service &rarr; Option: {{ $option->name }} &rarr; Scripts
@endsection
@section('content-header')
<h1>{{ $option->name }}<small>Manage install and upgrade scripts for this service option.</small></h1>
<ol class="breadcrumb">
<li><a href="{{ route('admin.index') }}">Admin</a></li>
<li><a href="{{ route('admin.services') }}">Services</a></li>
<li><a href="{{ route('admin.services') }}">Service</a></li>
<li><a href="{{ route('admin.services.view', $option->service->id) }}">{{ $option->service->name }}</a></li>
<li class="active">{{ $option->name }}</li>
</ol>

View file

@ -27,7 +27,7 @@
<h1>{{ $option->name }}<small>Managing variables for this service option.</small></h1>
<ol class="breadcrumb">
<li><a href="{{ route('admin.index') }}">Admin</a></li>
<li><a href="{{ route('admin.services') }}">Services</a></li>
<li><a href="{{ route('admin.services') }}">Service</a></li>
<li><a href="{{ route('admin.services.view', $option->service->id) }}">{{ $option->service->name }}</a></li>
<li><a href="{{ route('admin.services.option.view', $option->id) }}">{{ $option->name }}</a></li>
<li class="active">Variables</li>

View file

@ -20,14 +20,14 @@
@extends('layouts.admin')
@section('title')
Services &rarr; Option: {{ $option->name }}
Service &rarr; Option: {{ $option->name }}
@endsection
@section('content-header')
<h1>{{ $option->name }}<small>{{ str_limit($option->description, 50) }}</small></h1>
<ol class="breadcrumb">
<li><a href="{{ route('admin.index') }}">Admin</a></li>
<li><a href="{{ route('admin.services') }}">Services</a></li>
<li><a href="{{ route('admin.services') }}">Service</a></li>
<li><a href="{{ route('admin.services.view', $option->service->id) }}">{{ $option->service->name }}</a></li>
<li class="active">{{ $option->name }}</li>
</ol>

View file

@ -20,14 +20,14 @@
@extends('layouts.admin')
@section('title')
Services &rarr; {{ $service->name }}
Service &rarr; {{ $service->name }}
@endsection
@section('content-header')
<h1>{{ $service->name }}<small>{{ str_limit($service->description, 50) }}</small></h1>
<ol class="breadcrumb">
<li><a href="{{ route('admin.index') }}">Admin</a></li>
<li><a href="{{ route('admin.services') }}">Services</a></li>
<li><a href="{{ route('admin.services') }}">Service</a></li>
<li class="active">{{ $service->name }}</li>
</ol>
@endsection
@ -71,7 +71,7 @@
<label class="control-label">Folder Name</label>
<div>
<input type="text" name="folder" class="form-control" value="{{ $service->folder }}" />
<p class="text-muted"><small>Services are downloaded by the daemon and stored in a folder using this name. The storage location is <code>/srv/daemon/services/{NAME}</code> by default.</small></p>
<p class="text-muted"><small>Service are downloaded by the daemon and stored in a folder using this name. The storage location is <code>/srv/daemon/services/{NAME}</code> by default.</small></p>
</div>
</div>
<div class="form-group">

View file

@ -128,7 +128,7 @@
<li class="header">SERVICE MANAGEMENT</li>
<li class="{{ ! starts_with(Route::currentRouteName(), 'admin.services') ?: 'active' }}">
<a href="{{ route('admin.services') }}">
<i class="fa fa-th-large"></i> <span>Services</span>
<i class="fa fa-th-large"></i> <span>Service</span>
</a>
</li>
<li class="{{ ! starts_with(Route::currentRouteName(), 'admin.packs') ?: 'active' }}">

View file

@ -99,6 +99,9 @@ class DatabaseControllerTest extends TestCase
$this->assertViewKeyEquals('hosts', 'getWithViewDetails', $view);
}
/**
* Test the view controller for displaying a specific database host.
*/
public function testViewController()
{
$this->locationRepository->shouldReceive('getAllWithNodes')->withNoArgs()->once()->andReturn('getAllWithNodes');

View file

@ -71,7 +71,7 @@ class AssignmentServiceTest extends TestCase
//
// This can also be avoided if tests were run in isolated processes, or if that test
// came first, but neither of those are good solutions, so this is the next best option.
PHPMock::defineFunctionMock('\\Pterodactyl\\Services\\Allocations', 'gethostbyname');
PHPMock::defineFunctionMock('\\Pterodactyl\\Service\\Allocations', 'gethostbyname');
$this->node = factory(Node::class)->make();
$this->connection = m::mock(ConnectionInterface::class);
@ -180,7 +180,7 @@ class AssignmentServiceTest extends TestCase
'allocation_ports' => ['1024'],
];
$this->getFunctionMock('\\Pterodactyl\\Services\\Allocations', 'gethostbyname')
$this->getFunctionMock('\\Pterodactyl\\Service\\Allocations', 'gethostbyname')
->expects($this->once())->willReturn('192.168.1.1');
$this->connection->shouldReceive('beginTransaction')->withNoArgs()->once()->andReturnNull();

View file

@ -81,7 +81,7 @@ class KeyServiceTest extends TestCase
*/
public function test_create_function()
{
$this->getFunctionMock('\\Pterodactyl\\Services\\Api', 'random_bytes')
$this->getFunctionMock('\\Pterodactyl\\Service\\Api', 'random_bytes')
->expects($this->exactly(2))
->willReturnCallback(function ($bytes) {
return hex2bin(str_pad('', $bytes * 2, '0'));

View file

@ -84,7 +84,7 @@ class DatabaseManagementServiceTest extends TestCase
$this->encrypter = m::mock(Encrypter::class);
$this->repository = m::mock(DatabaseRepositoryInterface::class);
$this->getFunctionMock('\\Pterodactyl\\Services\\Database', 'str_random')
$this->getFunctionMock('\\Pterodactyl\\Service\\Database', 'str_random')
->expects($this->any())->willReturn('str_random');
$this->service = new DatabaseManagementService(

View file

@ -61,7 +61,7 @@ class CreationServiceTest extends TestCase
*/
public function testNodeIsCreatedAndDaemonSecretIsGenerated()
{
$this->getFunctionMock('\\Pterodactyl\\Services\\Nodes', 'bin2hex')
$this->getFunctionMock('\\Pterodactyl\\Service\\Nodes', 'bin2hex')
->expects($this->once())->willReturn('hexResult');
$this->repository->shouldReceive('create')->with([

View file

@ -97,14 +97,14 @@ class UpdateServiceTest extends TestCase
*/
public function testNodeIsUpdatedAndDaemonSecretIsReset()
{
$this->getFunctionMock('\\Pterodactyl\\Services\\Nodes', 'random_bytes')
$this->getFunctionMock('\\Pterodactyl\\Service\\Nodes', 'random_bytes')
->expects($this->once())->willReturnCallback(function ($bytes) {
$this->assertEquals(CreationService::DAEMON_SECRET_LENGTH, $bytes);
return '\00';
});
$this->getFunctionMock('\\Pterodactyl\\Services\\Nodes', 'bin2hex')
$this->getFunctionMock('\\Pterodactyl\\Service\\Nodes', 'bin2hex')
->expects($this->once())->willReturn('hexResponse');
$this->repository->shouldReceive('withoutFresh')->withNoArgs()->once()->andReturnSelf()

View file

@ -155,7 +155,7 @@ class CreationServiceTest extends TestCase
$this->uuid = m::mock('overload:Ramsey\Uuid\Uuid');
$this->writer = m::mock(Writer::class);
$this->getFunctionMock('\\Pterodactyl\\Services\\Servers', 'bin2hex')
$this->getFunctionMock('\\Pterodactyl\\Service\\Servers', 'bin2hex')
->expects($this->any())->willReturn('randomstring');
$this->getFunctionMock('\\Ramsey\\Uuid\\Uuid', 'uuid4')

View file

@ -84,7 +84,7 @@ class DetailsModificationServiceTest extends TestCase
$this->repository = m::mock(ServerRepository::class);
$this->writer = m::mock(Writer::class);
$this->getFunctionMock('\\Pterodactyl\\Services\\Servers', 'bin2hex')
$this->getFunctionMock('\\Pterodactyl\\Service\\Servers', 'bin2hex')
->expects($this->any())->willReturn('randomString');
$this->service = new DetailsModificationService(

View file

@ -46,10 +46,10 @@ class UsernameGenerationServiceTest extends TestCase
$this->service = new UsernameGenerationService();
$this->getFunctionMock('\\Pterodactyl\\Services\\Servers', 'bin2hex')
$this->getFunctionMock('\\Pterodactyl\\Service\\Servers', 'bin2hex')
->expects($this->any())->willReturn('dddddddd');
$this->getFunctionMock('\\Pterodactyl\\Services\\Servers', 'str_random')
$this->getFunctionMock('\\Pterodactyl\\Service\\Servers', 'str_random')
->expects($this->any())->willReturnCallback(function ($count) {
return str_pad('', $count, 'a');
});

View file

@ -30,7 +30,7 @@ use Tests\TestCase;
use Pterodactyl\Models\ServiceOption;
use Pterodactyl\Services\Services\Options\InstallScriptUpdateService;
use Pterodactyl\Contracts\Repository\ServiceOptionRepositoryInterface;
use Pterodactyl\Exceptions\Services\ServiceOption\InvalidCopyFromException;
use Pterodactyl\Exceptions\Service\ServiceOption\InvalidCopyFromException;
class InstallScriptUpdateServiceTest extends TestCase
{

View file

@ -30,7 +30,7 @@ use Tests\TestCase;
use Pterodactyl\Models\ServiceOption;
use Pterodactyl\Services\Services\Options\OptionCreationService;
use Pterodactyl\Contracts\Repository\ServiceOptionRepositoryInterface;
use Pterodactyl\Exceptions\Services\ServiceOption\NoParentConfigurationFoundException;
use Pterodactyl\Exceptions\Service\ServiceOption\NoParentConfigurationFoundException;
class OptionCreationServiceTest extends TestCase
{

View file

@ -26,7 +26,7 @@ namespace Tests\Unit\Services\Services\Options;
use Mockery as m;
use Tests\TestCase;
use Pterodactyl\Exceptions\Services\HasActiveServersException;
use Pterodactyl\Exceptions\Service\HasActiveServersException;
use Pterodactyl\Contracts\Repository\ServerRepositoryInterface;
use Pterodactyl\Services\Services\Options\OptionDeletionService;
use Pterodactyl\Contracts\Repository\ServiceOptionRepositoryInterface;

View file

@ -30,7 +30,7 @@ use Tests\TestCase;
use Pterodactyl\Models\ServiceOption;
use Pterodactyl\Services\Services\Options\OptionUpdateService;
use Pterodactyl\Contracts\Repository\ServiceOptionRepositoryInterface;
use Pterodactyl\Exceptions\Services\ServiceOption\NoParentConfigurationFoundException;
use Pterodactyl\Exceptions\Service\ServiceOption\NoParentConfigurationFoundException;
class OptionUpdateServiceTest extends TestCase
{

View file

@ -28,7 +28,7 @@ use Exception;
use Mockery as m;
use Tests\TestCase;
use Pterodactyl\Services\Services\ServiceDeletionService;
use Pterodactyl\Exceptions\Services\HasActiveServersException;
use Pterodactyl\Exceptions\Service\HasActiveServersException;
use Pterodactyl\Contracts\Repository\ServerRepositoryInterface;
use Pterodactyl\Contracts\Repository\ServiceRepositoryInterface;

View file

@ -99,7 +99,7 @@ class VariableCreationServiceTest extends TestCase
* Test that all of the reserved variables defined in the model trigger an exception.
*
* @dataProvider reservedNamesProvider
* @expectedException \Pterodactyl\Exceptions\Services\ServiceVariable\ReservedVariableNameException
* @expectedException \Pterodactyl\Exceptions\Service\ServiceVariable\ReservedVariableNameException
*/
public function testExceptionIsThrownIfEnvironmentVariableIsInListOfReservedNames($variable)
{

View file

@ -126,7 +126,7 @@ class VariableUpdateServiceTest extends TestCase
* Test that all of the reserved variables defined in the model trigger an exception.
*
* @dataProvider reservedNamesProvider
* @expectedException \Pterodactyl\Exceptions\Services\ServiceVariable\ReservedVariableNameException
* @expectedException \Pterodactyl\Exceptions\Service\ServiceVariable\ReservedVariableNameException
*/
public function testExceptionIsThrownIfEnvironmentVariableIsInListOfReservedNames($variable)
{