Merge branch 'develop' into feature/option-scripts
# Conflicts: # app/Http/Routes/AdminRoutes.php # app/Http/Routes/DaemonRoutes.php # app/Models/ServiceOption.php
This commit is contained in:
commit
8d24e5f168
683 changed files with 8854 additions and 12362 deletions
|
@ -29,99 +29,58 @@ use Auth;
|
|||
use Crypt;
|
||||
use Validator;
|
||||
use IPTools\Network;
|
||||
use Pterodactyl\Models;
|
||||
use Pterodactyl\Models\User;
|
||||
use Pterodactyl\Models\APIKey as Key;
|
||||
use Pterodactyl\Exceptions\DisplayException;
|
||||
use Pterodactyl\Models\APIPermission as Permission;
|
||||
use Pterodactyl\Exceptions\DisplayValidationException;
|
||||
|
||||
class APIRepository
|
||||
{
|
||||
/**
|
||||
* Valid API permissions.
|
||||
* @var array
|
||||
*/
|
||||
protected $permissions = [
|
||||
'admin' => [
|
||||
'*',
|
||||
|
||||
// User Management Routes
|
||||
'users.list',
|
||||
'users.create',
|
||||
'users.view',
|
||||
'users.update',
|
||||
'users.delete',
|
||||
|
||||
// Server Manaement Routes
|
||||
'servers.list',
|
||||
'servers.create',
|
||||
'servers.view',
|
||||
'servers.config',
|
||||
'servers.build',
|
||||
'servers.suspend',
|
||||
'servers.unsuspend',
|
||||
'servers.delete',
|
||||
|
||||
// Node Management Routes
|
||||
'nodes.list',
|
||||
'nodes.view',
|
||||
'nodes.create',
|
||||
'nodes.allocations',
|
||||
'nodes.delete',
|
||||
|
||||
// Service Routes
|
||||
'services.list',
|
||||
'services.view',
|
||||
|
||||
// Location Routes
|
||||
'locations.list',
|
||||
|
||||
],
|
||||
'user' => [
|
||||
'*',
|
||||
|
||||
// Informational
|
||||
'me',
|
||||
|
||||
// Server Control
|
||||
'server',
|
||||
'server.power',
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* Holder for listing of allowed IPs when creating a new key.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $allowed = [];
|
||||
|
||||
/**
|
||||
* The eloquent model for a user.
|
||||
*
|
||||
* @var \Pterodactyl\Models\User
|
||||
*/
|
||||
protected $user;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* Constructor for API Repository.
|
||||
*
|
||||
* @param null|\Pterodactyl\Models\User $user
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Models\User $user = null)
|
||||
public function __construct(User $user = null)
|
||||
{
|
||||
$this->user = is_null($user) ? Auth::user() : $user;
|
||||
if (is_null($this->user)) {
|
||||
throw new \Exception('Cannot access API Repository without passing a user to constructor.');
|
||||
throw new \Exception('Unable to initialize user for API repository instance.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a New API Keypair on the system.
|
||||
*
|
||||
* @param array $data An array with a permissions and allowed_ips key.
|
||||
* @param array $data
|
||||
* @return string
|
||||
*
|
||||
* @throws Pterodactyl\Exceptions\DisplayException if there was an error that can be safely displayed to end-users.
|
||||
* @throws Pterodactyl\Exceptions\DisplayValidationException if there was a validation error.
|
||||
*
|
||||
* @return string Returns the generated secret token.
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\DisplayValidationException
|
||||
*/
|
||||
public function create(array $data)
|
||||
{
|
||||
$validator = Validator::make($data, [
|
||||
'memo' => 'string|max:500',
|
||||
'allowed_ips' => 'sometimes|string',
|
||||
'permissions' => 'sometimes|required|array',
|
||||
'adminPermissions' => 'sometimes|required|array',
|
||||
'admin_permissions' => 'sometimes|required|array',
|
||||
]);
|
||||
|
||||
$validator->after(function ($validator) use ($data) {
|
||||
|
@ -147,8 +106,7 @@ class APIRepository
|
|||
DB::beginTransaction();
|
||||
try {
|
||||
$secretKey = str_random(16) . '.' . str_random(7) . '.' . str_random(7);
|
||||
$key = new Models\APIKey;
|
||||
$key->fill([
|
||||
$key = Key::create([
|
||||
'user_id' => $this->user->id,
|
||||
'public' => str_random(16),
|
||||
'secret' => Crypt::encrypt($secretKey),
|
||||
|
@ -156,44 +114,61 @@ class APIRepository
|
|||
'memo' => $data['memo'],
|
||||
'expires_at' => null,
|
||||
]);
|
||||
$key->save();
|
||||
|
||||
$totalPermissions = 0;
|
||||
$pNodes = Permission::permissions();
|
||||
|
||||
if (isset($data['permissions'])) {
|
||||
foreach ($data['permissions'] as $permNode) {
|
||||
if (! strpos($permNode, ':')) {
|
||||
foreach ($data['permissions'] as $permission) {
|
||||
$parts = explode('-', $permission);
|
||||
|
||||
if (count($parts) !== 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
list($toss, $permission) = explode(':', $permNode);
|
||||
if (in_array($permission, $this->permissions['user'])) {
|
||||
$totalPermissions++;
|
||||
$model = new Models\APIPermission;
|
||||
$model->fill([
|
||||
'key_id' => $key->id,
|
||||
'permission' => 'api.user.' . $permission,
|
||||
]);
|
||||
$model->save();
|
||||
list($block, $search) = $parts;
|
||||
|
||||
if (! array_key_exists($block, $pNodes['_user'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! in_array($search, $pNodes['_user'][$block])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$totalPermissions++;
|
||||
Permission::create([
|
||||
'key_id' => $key->id,
|
||||
'permission' => 'user.' . $permission,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->user->isRootAdmin() && isset($data['adminPermissions'])) {
|
||||
foreach ($data['adminPermissions'] as $permNode) {
|
||||
if (! strpos($permNode, ':')) {
|
||||
if ($this->user->isRootAdmin() && isset($data['admin_permissions'])) {
|
||||
unset($pNodes['_user']);
|
||||
|
||||
foreach ($data['admin_permissions'] as $permission) {
|
||||
$parts = explode('-', $permission);
|
||||
|
||||
if (count($parts) !== 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
list($toss, $permission) = explode(':', $permNode);
|
||||
if (in_array($permission, $this->permissions['admin'])) {
|
||||
$totalPermissions++;
|
||||
$model = new Models\APIPermission;
|
||||
$model->fill([
|
||||
'key_id' => $key->id,
|
||||
'permission' => 'api.admin.' . $permission,
|
||||
]);
|
||||
$model->save();
|
||||
list($block, $search) = $parts;
|
||||
|
||||
if (! array_key_exists($block, $pNodes)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! in_array($search, $pNodes[$block])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$totalPermissions++;
|
||||
Permission::create([
|
||||
'key_id' => $key->id,
|
||||
'permission' => $permission,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -213,28 +188,20 @@ class APIRepository
|
|||
/**
|
||||
* Revokes an API key and associated permissions.
|
||||
*
|
||||
* @param string $key The public key.
|
||||
*
|
||||
* @throws Illuminate\Database\Eloquent\ModelNotFoundException
|
||||
*
|
||||
* @param string $key
|
||||
* @return void
|
||||
*
|
||||
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException
|
||||
*/
|
||||
public function revoke($key)
|
||||
{
|
||||
DB::beginTransaction();
|
||||
|
||||
try {
|
||||
$model = Models\APIKey::with('permissions')->where('public', $key)->where('user_id', $this->user->id)->firstOrFail();
|
||||
DB::transaction(function () use ($key) {
|
||||
$model = Key::with('permissions')->where('public', $key)->where('user_id', $this->user->id)->firstOrFail();
|
||||
foreach ($model->permissions as &$permission) {
|
||||
$permission->delete();
|
||||
}
|
||||
|
||||
$model->delete();
|
||||
|
||||
DB::commit();
|
||||
} catch (\Exception $ex) {
|
||||
DB::rollBack();
|
||||
throw $ex;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,44 +24,67 @@
|
|||
|
||||
namespace Pterodactyl\Repositories\Daemon;
|
||||
|
||||
use Pterodactyl\Models;
|
||||
use GuzzleHttp\Exception\RequestException;
|
||||
use Pterodactyl\Models\User;
|
||||
use Pterodactyl\Models\Server;
|
||||
use GuzzleHttp\Exception\ConnectException;
|
||||
use Pterodactyl\Exceptions\DisplayException;
|
||||
|
||||
class CommandRepository
|
||||
{
|
||||
/**
|
||||
* The Eloquent Model associated with the requested server.
|
||||
*
|
||||
* @var \Pterodactyl\Models\Server
|
||||
*/
|
||||
protected $server;
|
||||
|
||||
public function __construct($server)
|
||||
/**
|
||||
* The Eloquent Model associated with the user to run the request as.
|
||||
*
|
||||
* @var \Pterodactyl\Models\User|null
|
||||
*/
|
||||
protected $user;
|
||||
|
||||
/**
|
||||
* Constuctor for repository.
|
||||
*
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @param \Pterodactyl\Models\User|null $user
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Server $server, User $user = null)
|
||||
{
|
||||
$this->server = ($server instanceof Models\Server) ? $server : Models\Server::findOrFail($server);
|
||||
$this->server = $server;
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* [send description].
|
||||
* @param string $command
|
||||
* @return bool
|
||||
* @throws DisplayException
|
||||
* @throws RequestException
|
||||
* Sends a command to the daemon.
|
||||
*
|
||||
* @param string $command
|
||||
* @return string
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \GuzzleHttp\Exception\RequestException
|
||||
*/
|
||||
public function send($command)
|
||||
{
|
||||
// We don't use the user's specific daemon secret here since we
|
||||
// are assuming that a call to this function has been validated.
|
||||
// Additionally not all calls to this will be from a logged in user.
|
||||
// (e.g. task queue or API)
|
||||
try {
|
||||
$response = $this->server->node->guzzleClient([
|
||||
'X-Access-Token' => $this->server->daemonSecret,
|
||||
'X-Access-Server' => $this->server->uuid,
|
||||
])->request('POST', '/server/command', ['json' => ['command' => $command]]);
|
||||
$response = $this->server->guzzleClient($this->user)->request('POST', '/server/command', [
|
||||
'http_errors' => false,
|
||||
'json' => [
|
||||
'command' => $command,
|
||||
],
|
||||
]);
|
||||
|
||||
if ($response->getStatusCode() < 200 || $response->getStatusCode() >= 300) {
|
||||
throw new DisplayException('Command sending responded with a non-200 error code.');
|
||||
throw new DisplayException('Command sending responded with a non-200 error code (HTTP/' . $response->getStatusCode() . ').');
|
||||
}
|
||||
|
||||
return $response->getBody();
|
||||
} catch (\Exception $ex) {
|
||||
} catch (ConnectException $ex) {
|
||||
throw $ex;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,14 +35,15 @@ class FileRepository
|
|||
/**
|
||||
* The Eloquent Model associated with the requested server.
|
||||
*
|
||||
* @var \Illuminate\Database\Eloquent\Model
|
||||
* @var \Pterodactyl\Models\Server
|
||||
*/
|
||||
protected $server;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $server The server Short UUID
|
||||
* @param string $uuid
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($uuid)
|
||||
{
|
||||
|
@ -52,8 +53,11 @@ class FileRepository
|
|||
/**
|
||||
* Get the contents of a requested file for the server.
|
||||
*
|
||||
* @param string $file
|
||||
* @param string $file
|
||||
* @return array
|
||||
*
|
||||
* @throws \GuzzleHttp\Exception\RequestException
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
*/
|
||||
public function returnFileContents($file)
|
||||
{
|
||||
|
@ -95,9 +99,12 @@ class FileRepository
|
|||
/**
|
||||
* Save the contents of a requested file on the daemon.
|
||||
*
|
||||
* @param string $file
|
||||
* @param string $content
|
||||
* @param string $file
|
||||
* @param string $content
|
||||
* @return bool
|
||||
*
|
||||
* @throws \GuzzleHttp\Exception\RequestException
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
*/
|
||||
public function saveFileContents($file, $content)
|
||||
{
|
||||
|
@ -125,8 +132,11 @@ class FileRepository
|
|||
/**
|
||||
* Returns a listing of all files and folders within a specified directory on the daemon.
|
||||
*
|
||||
* @param string $directory
|
||||
* @param string $directory
|
||||
* @return object
|
||||
*
|
||||
* @throws \GuzzleHttp\Exception\RequestException
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
*/
|
||||
public function returnDirectoryListing($directory)
|
||||
{
|
||||
|
|
|
@ -24,55 +24,104 @@
|
|||
|
||||
namespace Pterodactyl\Repositories\Daemon;
|
||||
|
||||
use Pterodactyl\Models;
|
||||
use Pterodactyl\Models\User;
|
||||
use Pterodactyl\Models\Server;
|
||||
use GuzzleHttp\Exception\ConnectException;
|
||||
use Pterodactyl\Exceptions\DisplayException;
|
||||
|
||||
class PowerRepository
|
||||
{
|
||||
/**
|
||||
* The Eloquent Model associated with the requested server.
|
||||
*
|
||||
* @var \Pterodactyl\Models\Server
|
||||
*/
|
||||
protected $server;
|
||||
|
||||
public function __construct($server)
|
||||
/**
|
||||
* The Eloquent Model associated with the user to run the request as.
|
||||
*
|
||||
* @var \Pterodactyl\Models\User|null
|
||||
*/
|
||||
protected $user;
|
||||
|
||||
/**
|
||||
* Constuctor for repository.
|
||||
*
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @param \Pterodactyl\Models\User|null $user
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Server $server, User $user = null)
|
||||
{
|
||||
$this->server = ($server instanceof Models\Server) ? $server : Models\Server::findOrFail($server);
|
||||
$this->server = $server;
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a power option to the daemon.
|
||||
*
|
||||
* @param string $action
|
||||
* @return string
|
||||
*
|
||||
* @throws \GuzzleHttp\Exception\RequestException
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
*/
|
||||
public function do($action)
|
||||
{
|
||||
// We don't use the user's specific daemon secret here since we
|
||||
// are assuming that a call to this function has been validated.
|
||||
// Additionally not all calls to this will be from a logged in user.
|
||||
// (e.g. task queue or API)
|
||||
try {
|
||||
$response = $this->server->node->guzzleClient([
|
||||
'X-Access-Token' => $this->server->daemonSecret,
|
||||
'X-Access-Server' => $this->server->uuid,
|
||||
])->request('PUT', '/server/power', ['json' => ['action' => $action]]);
|
||||
$response = $this->server->guzzleClient($this->user)->request('PUT', '/server/power', [
|
||||
'http_errors' => false,
|
||||
'json' => [
|
||||
'action' => $action,
|
||||
],
|
||||
]);
|
||||
|
||||
if ($response->getStatusCode() < 200 || $response->getStatusCode() >= 300) {
|
||||
throw new DisplayException('Power status responded with a non-200 error code.');
|
||||
throw new DisplayException('Power toggle endpoint responded with a non-200 error code (HTTP/' . $response->getStatusCode() . ').');
|
||||
}
|
||||
|
||||
return $response->getBody();
|
||||
} catch (\Exception $ex) {
|
||||
} catch (ConnectException $ex) {
|
||||
throw $ex;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a server.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function start()
|
||||
{
|
||||
$this->do('start');
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops a server.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function stop()
|
||||
{
|
||||
$this->do('stop');
|
||||
}
|
||||
|
||||
/**
|
||||
* Restarts a server.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function restart()
|
||||
{
|
||||
$this->do('restart');
|
||||
}
|
||||
|
||||
/**
|
||||
* Kills a server.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function kill()
|
||||
{
|
||||
$this->do('kill');
|
||||
|
|
|
@ -39,8 +39,8 @@ class DatabaseRepository
|
|||
/**
|
||||
* Adds a new database to a specified database host server.
|
||||
*
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @return \Pterodactyl\Models\Database
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
|
@ -84,18 +84,9 @@ class DatabaseRepository
|
|||
throw $ex;
|
||||
}
|
||||
|
||||
Config::set('database.connections.dynamic', [
|
||||
'driver' => 'mysql',
|
||||
'host' => $host->host,
|
||||
'port' => $host->port,
|
||||
'database' => 'mysql',
|
||||
'username' => $host->username,
|
||||
'password' => Crypt::decrypt($host->password),
|
||||
'charset' => 'utf8',
|
||||
'collation' => 'utf8_unicode_ci',
|
||||
]);
|
||||
|
||||
try {
|
||||
$host->setDynamicConnection();
|
||||
|
||||
DB::connection('dynamic')->statement(sprintf('CREATE DATABASE IF NOT EXISTS `%s`', $database->database));
|
||||
DB::connection('dynamic')->statement(sprintf(
|
||||
'CREATE USER `%s`@`%s` IDENTIFIED BY \'%s\'',
|
||||
|
@ -128,8 +119,8 @@ class DatabaseRepository
|
|||
/**
|
||||
* Updates the password for a given database.
|
||||
*
|
||||
* @param int $id
|
||||
* @param string $password
|
||||
* @param int $id
|
||||
* @param string $password
|
||||
* @return void
|
||||
*
|
||||
* @todo Fix logic behind resetting passwords.
|
||||
|
@ -137,21 +128,11 @@ class DatabaseRepository
|
|||
public function password($id, $password)
|
||||
{
|
||||
$database = Database::with('host')->findOrFail($id);
|
||||
$database->host->setDynamicConnection();
|
||||
|
||||
DB::transaction(function () use ($database, $password) {
|
||||
$database->password = Crypt::encrypt($password);
|
||||
|
||||
Config::set('database.connections.dynamic', [
|
||||
'driver' => 'mysql',
|
||||
'host' => $database->host->host,
|
||||
'port' => $database->host->port,
|
||||
'database' => 'mysql',
|
||||
'username' => $database->host->username,
|
||||
'password' => Crypt::decrypt($database->host->password),
|
||||
'charset' => 'utf8',
|
||||
'collation' => 'utf8_unicode_ci',
|
||||
]);
|
||||
|
||||
// We have to do the whole delete user, create user thing rather than
|
||||
// SET PASSWORD ... because MariaDB and PHP statements ends up inserting
|
||||
// a corrupted password. A way around this is strtoupper(sha1(sha1($password, true)))
|
||||
|
@ -174,25 +155,15 @@ class DatabaseRepository
|
|||
/**
|
||||
* Drops a database from the associated database host.
|
||||
*
|
||||
* @param int $id
|
||||
* @param int $id
|
||||
* @return void
|
||||
*/
|
||||
public function drop($id)
|
||||
{
|
||||
$database = Database::with('host')->findOrFail($id);
|
||||
$database->host->setDynamicConnection();
|
||||
|
||||
DB::transaction(function () use ($database) {
|
||||
Config::set('database.connections.dynamic', [
|
||||
'driver' => 'mysql',
|
||||
'host' => $database->host->host,
|
||||
'port' => $database->host->port,
|
||||
'database' => 'mysql',
|
||||
'username' => $database->host->username,
|
||||
'password' => Crypt::decrypt($database->host->password),
|
||||
'charset' => 'utf8',
|
||||
'collation' => 'utf8_unicode_ci',
|
||||
]);
|
||||
|
||||
DB::connection('dynamic')->statement(sprintf('DROP DATABASE IF EXISTS `%s`', $database->database));
|
||||
DB::connection('dynamic')->statement(sprintf('DROP USER IF EXISTS `%s`@`%s`', $database->username, $database->remote));
|
||||
DB::connection('dynamic')->statement('FLUSH PRIVILEGES');
|
||||
|
@ -204,7 +175,7 @@ class DatabaseRepository
|
|||
/**
|
||||
* Deletes a database host from the system if it has no associated databases.
|
||||
*
|
||||
* @param int $server
|
||||
* @param int $id
|
||||
* @return void
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
|
@ -223,7 +194,7 @@ class DatabaseRepository
|
|||
/**
|
||||
* Adds a new Database Host to the system.
|
||||
*
|
||||
* @param array $data
|
||||
* @param array $data
|
||||
* @return \Pterodactyl\Models\DatabaseHost
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayValidationException
|
||||
|
@ -248,20 +219,6 @@ class DatabaseRepository
|
|||
}
|
||||
|
||||
return DB::transaction(function () use ($data) {
|
||||
Config::set('database.connections.dynamic', [
|
||||
'driver' => 'mysql',
|
||||
'host' => $data['host'],
|
||||
'port' => $data['port'],
|
||||
'database' => 'mysql',
|
||||
'username' => $data['username'],
|
||||
'password' => $data['password'],
|
||||
'charset' => 'utf8',
|
||||
'collation' => 'utf8_unicode_ci',
|
||||
]);
|
||||
|
||||
// Allows us to check that we can connect to things.
|
||||
DB::connection('dynamic')->select('SELECT 1 FROM dual');
|
||||
|
||||
$host = new DatabaseHost;
|
||||
$host->password = Crypt::encrypt($data['password']);
|
||||
|
||||
|
@ -274,6 +231,10 @@ class DatabaseRepository
|
|||
'node_id' => (isset($data['node_id'])) ? $data['node_id'] : null,
|
||||
])->save();
|
||||
|
||||
// Allows us to check that we can connect to things.
|
||||
$host->setDynamicConnection();
|
||||
DB::connection('dynamic')->select('SELECT 1 FROM dual');
|
||||
|
||||
return $host;
|
||||
});
|
||||
}
|
||||
|
@ -281,8 +242,8 @@ class DatabaseRepository
|
|||
/**
|
||||
* Updates a Database Host on the system.
|
||||
*
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @return \Pterodactyl\Models\DatabaseHost
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayValidationException
|
||||
|
@ -315,18 +276,7 @@ class DatabaseRepository
|
|||
$host->fill($data)->save();
|
||||
|
||||
// Check that we can still connect with these details.
|
||||
Config::set('database.connections.dynamic', [
|
||||
'driver' => 'mysql',
|
||||
'host' => $host->host,
|
||||
'port' => $host->port,
|
||||
'database' => 'mysql',
|
||||
'username' => $host->username,
|
||||
'password' => Crypt::decrypt($host->password),
|
||||
'charset' => 'utf8',
|
||||
'collation' => 'utf8_unicode_ci',
|
||||
]);
|
||||
|
||||
// Allows us to check that we can connect to things.
|
||||
$host->setDynamicConnection();
|
||||
DB::connection('dynamic')->select('SELECT 1 FROM dual');
|
||||
|
||||
return $host;
|
||||
|
|
|
@ -28,6 +28,7 @@ class HelperRepository
|
|||
{
|
||||
/**
|
||||
* Listing of editable files in the control panel.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $editable = [
|
||||
|
@ -44,17 +45,13 @@ class HelperRepository
|
|||
'inode/x-empty',
|
||||
];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts from bytes to the largest possible size that is still readable.
|
||||
*
|
||||
* @param int $bytes
|
||||
* @param int $decimals
|
||||
* @param int $bytes
|
||||
* @param int $decimals
|
||||
* @return string
|
||||
* @deprecated
|
||||
*/
|
||||
public static function bytesToHuman($bytes, $decimals = 2)
|
||||
{
|
||||
|
@ -64,6 +61,11 @@ class HelperRepository
|
|||
return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) . ' ' . $sz[$factor];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns array of editable files.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function editableFiles()
|
||||
{
|
||||
return self::$editable;
|
||||
|
|
|
@ -35,8 +35,9 @@ class LocationRepository
|
|||
* Creates a new location on the system.
|
||||
*
|
||||
* @param array $data
|
||||
* @throws \Pterodactyl\Exceptions\DisplayValidationException
|
||||
* @return \Pterodactyl\Models\Location
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayValidationException
|
||||
*/
|
||||
public function create(array $data)
|
||||
{
|
||||
|
@ -58,11 +59,11 @@ class LocationRepository
|
|||
/**
|
||||
* Modifies a location.
|
||||
*
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @return \Pterodactyl\Models\Location
|
||||
*
|
||||
* @throws Pterodactyl\Exceptions\DisplayValidationException
|
||||
* @throws \Pterodactyl\Exceptions\DisplayValidationException
|
||||
*/
|
||||
public function update($id, array $data)
|
||||
{
|
||||
|
@ -85,10 +86,10 @@ class LocationRepository
|
|||
/**
|
||||
* Deletes a location from the system.
|
||||
*
|
||||
* @param int $id
|
||||
* @param int $id
|
||||
* @return void
|
||||
*
|
||||
* @throws Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
*/
|
||||
public function delete($id)
|
||||
{
|
||||
|
|
|
@ -34,11 +34,15 @@ use Pterodactyl\Exceptions\DisplayValidationException;
|
|||
|
||||
class NodeRepository
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new node on the system.
|
||||
*
|
||||
* @param array $data
|
||||
* @return \Pterodactyl\Models\Node
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\DisplayValidationException
|
||||
*/
|
||||
public function create(array $data)
|
||||
{
|
||||
// Validate Fields
|
||||
|
@ -84,6 +88,16 @@ class NodeRepository
|
|||
return Models\Node::create($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a node on the system.
|
||||
*
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @return \Pterodactyl\Models\Node
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\DisplayValidationException
|
||||
*/
|
||||
public function update($id, array $data)
|
||||
{
|
||||
$node = Models\Node::findOrFail($id);
|
||||
|
@ -179,8 +193,13 @@ class NodeRepository
|
|||
|
||||
/**
|
||||
* Adds allocations to a provided node.
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
*
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @return void
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\DisplayValidationException
|
||||
*/
|
||||
public function addAllocations($id, array $data)
|
||||
{
|
||||
|
@ -203,7 +222,7 @@ class NodeRepository
|
|||
}
|
||||
}
|
||||
|
||||
DB::transaction(function () use ($parsed, $node, $data) {
|
||||
DB::transaction(function () use ($data, $node) {
|
||||
foreach (Network::parse(gethostbyname($data['allocation_ip'])) as $ip) {
|
||||
foreach ($data['allocation_ports'] as $port) {
|
||||
// Determine if this is a valid single port, or a valid port range.
|
||||
|
@ -243,6 +262,14 @@ class NodeRepository
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a node on the system.
|
||||
*
|
||||
* @param int $id
|
||||
* @return void
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
*/
|
||||
public function delete($id)
|
||||
{
|
||||
$node = Models\Node::withCount('servers')->findOrFail($id);
|
||||
|
@ -250,13 +277,9 @@ class NodeRepository
|
|||
throw new DisplayException('You cannot delete a node with servers currently attached to it.');
|
||||
}
|
||||
|
||||
DB::beginTransaction();
|
||||
|
||||
try {
|
||||
DB::transaction(function () use ($node) {
|
||||
// Unlink Database Servers
|
||||
Models\DatabaseServer::where('linked_node', $node->id)->update([
|
||||
'linked_node' => null,
|
||||
]);
|
||||
Models\DatabaseHost::where('node_id', $node->id)->update(['node_id' => null]);
|
||||
|
||||
// Delete Allocations
|
||||
Models\Allocation::where('node_id', $node->id)->delete();
|
||||
|
@ -266,11 +289,6 @@ class NodeRepository
|
|||
|
||||
// Delete Node
|
||||
$node->delete();
|
||||
|
||||
DB::commit();
|
||||
} catch (\Exception $ex) {
|
||||
DB::rollback();
|
||||
throw $ex;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ class OptionRepository
|
|||
/**
|
||||
* Deletes a service option from the system.
|
||||
*
|
||||
* @param int $id
|
||||
* @param int $id
|
||||
* @return void
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
|
|
|
@ -38,7 +38,7 @@ class PackRepository
|
|||
/**
|
||||
* Creates a new pack on the system.
|
||||
*
|
||||
* @param array $data
|
||||
* @param array $data
|
||||
* @return \Pterodactyl\Models\Pack
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
|
@ -101,7 +101,7 @@ class PackRepository
|
|||
/**
|
||||
* Creates a new pack on the system given a template file.
|
||||
*
|
||||
* @param array $data
|
||||
* @param array $data
|
||||
* @return \Pterodactyl\Models\Pack
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
|
@ -173,8 +173,8 @@ class PackRepository
|
|||
/**
|
||||
* Updates a pack on the system.
|
||||
*
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @return \Pterodactyl\Models\Pack
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
|
@ -225,7 +225,7 @@ class PackRepository
|
|||
*/
|
||||
public function delete($id)
|
||||
{
|
||||
$pack = Models\Pack::withCount('servers')->findOrFail($id);
|
||||
$pack = Pack::withCount('servers')->findOrFail($id);
|
||||
|
||||
if ($pack->servers_count > 0) {
|
||||
throw new DisplayException('Cannot delete a pack from the system if servers are assocaited with it.');
|
||||
|
|
|
@ -25,11 +25,11 @@
|
|||
namespace Pterodactyl\Repositories;
|
||||
|
||||
use DB;
|
||||
use Log;
|
||||
use Crypt;
|
||||
use Validator;
|
||||
use Pterodactyl\Models;
|
||||
use Pterodactyl\Services\UuidService;
|
||||
use GuzzleHttp\Exception\ClientException;
|
||||
use GuzzleHttp\Exception\TransferException;
|
||||
use Pterodactyl\Services\DeploymentService;
|
||||
use Pterodactyl\Exceptions\DisplayException;
|
||||
|
@ -37,21 +37,21 @@ use Pterodactyl\Exceptions\DisplayValidationException;
|
|||
|
||||
class ServerRepository
|
||||
{
|
||||
/**
|
||||
* An array of daemon permission to assign to this server.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $daemonPermissions = [
|
||||
's:*',
|
||||
];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a SFTP username for a server given a server name.
|
||||
* format: mumble_67c7a4b0.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $identifier
|
||||
* @param string $name
|
||||
* @param null|string $identifier
|
||||
* @return string
|
||||
*/
|
||||
protected function generateSFTPUsername($name, $identifier = null)
|
||||
|
@ -75,8 +75,12 @@ class ServerRepository
|
|||
|
||||
/**
|
||||
* Adds a new server to the system.
|
||||
* @param array $data An array of data descriptors for creating the server. These should align to the columns in the database.
|
||||
* @return int
|
||||
*
|
||||
* @param array $data
|
||||
* @return \Pterodactyl\Models\Server
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\DisplayValidationException
|
||||
*/
|
||||
public function create(array $data)
|
||||
{
|
||||
|
@ -85,6 +89,7 @@ class ServerRepository
|
|||
$validator = Validator::make($data, [
|
||||
'user_id' => 'required|exists:users,id',
|
||||
'name' => 'required|regex:/^([\w .-]{1,200})$/',
|
||||
'description' => 'sometimes|nullable|string',
|
||||
'memory' => 'required|numeric|min:0',
|
||||
'swap' => 'required|numeric|min:-1',
|
||||
'io' => 'required|numeric|min:10|max:1000',
|
||||
|
@ -96,7 +101,7 @@ class ServerRepository
|
|||
'pack_id' => 'sometimes|nullable|numeric|min:0',
|
||||
'custom_container' => 'string',
|
||||
'startup' => 'string',
|
||||
'auto_deploy' => 'sometimes|boolean',
|
||||
'auto_deploy' => 'sometimes|required|accepted',
|
||||
'custom_id' => 'sometimes|required|numeric|unique:servers,id',
|
||||
]);
|
||||
|
||||
|
@ -243,6 +248,7 @@ class ServerRepository
|
|||
'uuidShort' => $genShortUuid,
|
||||
'node_id' => $node->id,
|
||||
'name' => $data['name'],
|
||||
'description' => $data['description'],
|
||||
'suspended' => 0,
|
||||
'owner_id' => $user->id,
|
||||
'memory' => $data['memory'],
|
||||
|
@ -325,15 +331,13 @@ class ServerRepository
|
|||
(string) $server->daemonSecret => $this->daemonPermissions,
|
||||
],
|
||||
'rebuild' => false,
|
||||
'start_on_completion' => isset($data['start_on_completion']),
|
||||
],
|
||||
]);
|
||||
|
||||
DB::commit();
|
||||
|
||||
return $server;
|
||||
} catch (TransferException $ex) {
|
||||
DB::rollBack();
|
||||
throw new DisplayException('There was an error while attempting to connect to the daemon to add this server.', $ex);
|
||||
} catch (\Exception $ex) {
|
||||
DB::rollBack();
|
||||
throw $ex;
|
||||
|
@ -341,10 +345,14 @@ class ServerRepository
|
|||
}
|
||||
|
||||
/**
|
||||
* [updateDetails description].
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @return bool
|
||||
* Update the details for a server.
|
||||
*
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @return \Pterodactyl\Models\Server
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\DisplayValidationException
|
||||
*/
|
||||
public function updateDetails($id, array $data)
|
||||
{
|
||||
|
@ -355,6 +363,7 @@ class ServerRepository
|
|||
$validator = Validator::make($data, [
|
||||
'owner_id' => 'sometimes|required|integer|exists:users,id',
|
||||
'name' => 'sometimes|required|regex:([\w .-]{1,200})',
|
||||
'description' => 'sometimes|required|string',
|
||||
'reset_token' => 'sometimes|required|accepted',
|
||||
]);
|
||||
|
||||
|
@ -376,24 +385,12 @@ class ServerRepository
|
|||
$resetDaemonKey = true;
|
||||
}
|
||||
|
||||
// Update Server Owner if it was passed.
|
||||
if (isset($data['owner_id']) && (int) $data['owner_id'] !== $server->user->id) {
|
||||
$server->owner_id = $data['owner_id'];
|
||||
}
|
||||
|
||||
// Update Server Name if it was passed.
|
||||
if (isset($data['name'])) {
|
||||
$server->name = $data['name'];
|
||||
}
|
||||
|
||||
// Save our changes
|
||||
$server->save();
|
||||
$server->fill($data)->save();
|
||||
|
||||
// Do we need to update? If not, return successful.
|
||||
if (! $resetDaemonKey) {
|
||||
DB::commit();
|
||||
|
||||
return true;
|
||||
return DB::commit();
|
||||
}
|
||||
|
||||
$res = $server->node->guzzleClient([
|
||||
|
@ -412,22 +409,24 @@ class ServerRepository
|
|||
if ($res->getStatusCode() === 204) {
|
||||
DB::commit();
|
||||
|
||||
return true;
|
||||
return $server;
|
||||
} else {
|
||||
throw new DisplayException('Daemon returned a a non HTTP/204 error code. HTTP/' + $res->getStatusCode());
|
||||
}
|
||||
} catch (\Exception $ex) {
|
||||
DB::rollBack();
|
||||
Log::error($ex);
|
||||
throw new DisplayException('An error occured while attempting to update this server\'s information.');
|
||||
throw $ex;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* [updateContainer description].
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @return bool
|
||||
* Update the container for a server.
|
||||
*
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @return \Pterodactyl\Models\Server
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayValidationException
|
||||
*/
|
||||
public function updateContainer($id, array $data)
|
||||
{
|
||||
|
@ -461,10 +460,7 @@ class ServerRepository
|
|||
|
||||
DB::commit();
|
||||
|
||||
return true;
|
||||
} catch (TransferException $ex) {
|
||||
DB::rollBack();
|
||||
throw new DisplayException('A TransferException occured while attempting to update the container image. Is the daemon online? This error has been logged.', $ex);
|
||||
return $server;
|
||||
} catch (\Exception $ex) {
|
||||
DB::rollBack();
|
||||
throw $ex;
|
||||
|
@ -472,10 +468,14 @@ class ServerRepository
|
|||
}
|
||||
|
||||
/**
|
||||
* [changeBuild description].
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @return bool
|
||||
* Update the build details for a server.
|
||||
*
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @return \Pterodactyl\Models\Server
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\DisplayValidationException
|
||||
*/
|
||||
public function changeBuild($id, array $data)
|
||||
{
|
||||
|
@ -518,23 +518,7 @@ class ServerRepository
|
|||
}
|
||||
|
||||
$newPorts = false;
|
||||
// Remove Assignments
|
||||
if (isset($data['remove_allocations'])) {
|
||||
foreach ($data['remove_allocations'] as $allocation) {
|
||||
// Can't remove the assigned IP/Port combo
|
||||
if ((int) $allocation === $server->allocation_id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$newPorts = true;
|
||||
Models\Allocation::where('id', $allocation)->where('server_id', $server->id)->update([
|
||||
'server_id' => null,
|
||||
]);
|
||||
}
|
||||
|
||||
$server->load('allocations');
|
||||
}
|
||||
|
||||
$firstNewAllocation = null;
|
||||
// Add Assignments
|
||||
if (isset($data['add_allocations'])) {
|
||||
foreach ($data['add_allocations'] as $allocation) {
|
||||
|
@ -544,6 +528,7 @@ class ServerRepository
|
|||
}
|
||||
|
||||
$newPorts = true;
|
||||
$firstNewAllocation = (is_null($firstNewAllocation)) ? $model->id : $firstNewAllocation;
|
||||
$model->update([
|
||||
'server_id' => $server->id,
|
||||
]);
|
||||
|
@ -552,6 +537,29 @@ class ServerRepository
|
|||
$server->load('allocations');
|
||||
}
|
||||
|
||||
// Remove Assignments
|
||||
if (isset($data['remove_allocations'])) {
|
||||
foreach ($data['remove_allocations'] as $allocation) {
|
||||
// Can't remove the assigned IP/Port combo
|
||||
if ((int) $allocation === $server->allocation_id) {
|
||||
// No New Allocation
|
||||
if (is_null($firstNewAllocation)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// New Allocation, set as the default.
|
||||
$server->allocation_id = $firstNewAllocation;
|
||||
}
|
||||
|
||||
$newPorts = true;
|
||||
Models\Allocation::where('id', $allocation)->where('server_id', $server->id)->update([
|
||||
'server_id' => null,
|
||||
]);
|
||||
}
|
||||
|
||||
$server->load('allocations');
|
||||
}
|
||||
|
||||
if ($newPorts) {
|
||||
$newBuild['ports|overwrite'] = $server->allocations->groupBy('ip')->map(function ($item) {
|
||||
return $item->pluck('port');
|
||||
|
@ -605,15 +613,24 @@ class ServerRepository
|
|||
DB::commit();
|
||||
|
||||
return $server;
|
||||
} catch (TransferException $ex) {
|
||||
DB::rollBack();
|
||||
throw new DisplayException('A TransferException occured while attempting to update the server configuration, check that the daemon is online. This error has been logged.', $ex);
|
||||
} catch (\Exception $ex) {
|
||||
DB::rollBack();
|
||||
throw $ex;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the startup details for a server.
|
||||
*
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @param bool $admin
|
||||
* @return void
|
||||
*
|
||||
* @throws \GuzzleHttp\Exception\RequestException
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\DisplayValidationException
|
||||
*/
|
||||
public function updateStartup($id, array $data, $admin = false)
|
||||
{
|
||||
$server = Models\Server::with('variables', 'option.variables')->findOrFail($id);
|
||||
|
@ -691,34 +708,18 @@ class ServerRepository
|
|||
});
|
||||
}
|
||||
|
||||
public function queueDeletion($id, $force = false)
|
||||
{
|
||||
$server = Models\Server::findOrFail($id);
|
||||
DB::beginTransaction();
|
||||
|
||||
try {
|
||||
if ($force) {
|
||||
$server->installed = 3;
|
||||
$server->save();
|
||||
}
|
||||
$server->delete();
|
||||
|
||||
return DB::commit();
|
||||
} catch (\Exception $ex) {
|
||||
DB::rollBack();
|
||||
throw $ex;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a server from the system permanetly.
|
||||
*
|
||||
* @param int $id
|
||||
* @param bool $force
|
||||
* @return void
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
*/
|
||||
public function delete($id, $force = false)
|
||||
{
|
||||
$server = Models\Server::withTrashed()->with('node', 'allocations', 'variables')->findOrFail($id);
|
||||
|
||||
// Handle server being restored previously or
|
||||
// an accidental queue.
|
||||
if (! $server->trashed()) {
|
||||
return;
|
||||
}
|
||||
$server = Models\Server::with('node', 'allocations', 'variables')->findOrFail($id);
|
||||
|
||||
// Due to MySQL lockouts if the daemon response fails, we need to
|
||||
// delete the server from the daemon first. If it succeedes and then
|
||||
|
@ -730,8 +731,18 @@ class ServerRepository
|
|||
'X-Access-Token' => $server->node->daemonSecret,
|
||||
'X-Access-Server' => $server->uuid,
|
||||
])->request('DELETE', '/servers');
|
||||
} catch (ClientException $ex) {
|
||||
// Exception is thrown on 4XX HTTP errors, so catch and determine
|
||||
// if we should continue, or if there is a permissions error.
|
||||
//
|
||||
// Daemon throws a 404 if the server doesn't exist, if that is returned
|
||||
// continue with deletion, even if not a force deletion.
|
||||
$response = $ex->getResponse();
|
||||
if ($ex->getResponse()->getStatusCode() !== 404 && ! $force) {
|
||||
throw new DisplayException($ex->getMessage());
|
||||
}
|
||||
} catch (TransferException $ex) {
|
||||
if ($server->installed !== 3 && ! $force) {
|
||||
if (! $force) {
|
||||
throw new DisplayException($ex->getMessage());
|
||||
}
|
||||
} catch (\Exception $ex) {
|
||||
|
@ -744,45 +755,40 @@ class ServerRepository
|
|||
$item->save();
|
||||
});
|
||||
|
||||
$server->variables->each(function ($item) {
|
||||
$item->delete();
|
||||
$server->variables->each->delete();
|
||||
|
||||
$server->load('subusers.permissions');
|
||||
$server->subusers->each(function ($subuser) {
|
||||
$subuser->permissions->each(function ($permission) {
|
||||
$perm->delete();
|
||||
});
|
||||
$subuser->delete();
|
||||
});
|
||||
|
||||
foreach (Models\Subuser::with('permissions')->where('server_id', $server->id)->get() as &$subuser) {
|
||||
foreach ($subuser->permissions as &$permission) {
|
||||
$permission->delete();
|
||||
}
|
||||
$subuser->delete();
|
||||
}
|
||||
|
||||
// Remove Downloads
|
||||
Models\Download::where('server', $server->uuid)->delete();
|
||||
|
||||
// Clear Tasks
|
||||
Models\Task::where('server', $server->id)->delete();
|
||||
$server->downloads->each->delete();
|
||||
$server->tasks->each->delete();
|
||||
|
||||
// Delete Databases
|
||||
// This is the one un-recoverable point where
|
||||
// transactions will not save us.
|
||||
$repository = new DatabaseRepository;
|
||||
foreach (Models\Database::select('id')->where('server_id', $server->id)->get() as $database) {
|
||||
$repository->drop($database->id);
|
||||
}
|
||||
$server->databases->each(function ($item) {
|
||||
$repository->drop($item->id);
|
||||
});
|
||||
|
||||
// Fully delete the server.
|
||||
$server->forceDelete();
|
||||
$server->delete();
|
||||
});
|
||||
}
|
||||
|
||||
public function cancelDeletion($id)
|
||||
{
|
||||
$server = Models\Server::withTrashed()->findOrFail($id);
|
||||
$server->restore();
|
||||
|
||||
$server->installed = 1;
|
||||
$server->save();
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle the install status of a serve.
|
||||
*
|
||||
* @param int $id
|
||||
* @return bool
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
*/
|
||||
public function toggleInstall($id)
|
||||
{
|
||||
$server = Models\Server::findOrFail($id);
|
||||
|
@ -795,77 +801,43 @@ class ServerRepository
|
|||
}
|
||||
|
||||
/**
|
||||
* Suspends a server instance making it unable to be booted or used by a user.
|
||||
* @param int $id
|
||||
* @return bool
|
||||
* Suspends or unsuspends a server.
|
||||
*
|
||||
* @param int $id
|
||||
* @param bool $unsuspend
|
||||
* @return void
|
||||
*/
|
||||
public function suspend($id, $deleted = false)
|
||||
{
|
||||
$server = Models\Server::withTrashed()->with('node')->findOrFail($id);
|
||||
|
||||
DB::beginTransaction();
|
||||
|
||||
try {
|
||||
|
||||
// Already suspended, no need to make more requests.
|
||||
if ($server->suspended) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$server->suspended = 1;
|
||||
$server->save();
|
||||
|
||||
$server->node->guzzleClient([
|
||||
'X-Access-Token' => $server->node->daemonSecret,
|
||||
'X-Access-Server' => $server->uuid,
|
||||
])->request('POST', '/server/suspend');
|
||||
|
||||
return DB::commit();
|
||||
} catch (TransferException $ex) {
|
||||
DB::rollBack();
|
||||
throw new DisplayException('An error occured while attempting to contact the remote daemon to suspend this server.', $ex);
|
||||
} catch (\Exception $ex) {
|
||||
DB::rollBack();
|
||||
throw $ex;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsuspends a server instance.
|
||||
* @param int $id
|
||||
* @return bool
|
||||
*/
|
||||
public function unsuspend($id)
|
||||
public function toggleAccess($id, $unsuspend = true)
|
||||
{
|
||||
$server = Models\Server::with('node')->findOrFail($id);
|
||||
|
||||
DB::beginTransaction();
|
||||
|
||||
try {
|
||||
|
||||
// Already unsuspended, no need to make more requests.
|
||||
if ($server->suspended === 0) {
|
||||
DB::transaction(function () use ($server, $unsuspend) {
|
||||
if (
|
||||
(! $unsuspend && $server->suspended) ||
|
||||
($unsuspend && ! $server->suspended)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$server->suspended = 0;
|
||||
$server->suspended = ! $unsuspend;
|
||||
$server->save();
|
||||
|
||||
$server->node->guzzleClient([
|
||||
'X-Access-Token' => $server->node->daemonSecret,
|
||||
'X-Access-Server' => $server->uuid,
|
||||
])->request('POST', '/server/unsuspend');
|
||||
|
||||
return DB::commit();
|
||||
} catch (TransferException $ex) {
|
||||
DB::rollBack();
|
||||
throw new DisplayException('An error occured while attempting to contact the remote daemon to un-suspend this server.', $ex);
|
||||
} catch (\Exception $ex) {
|
||||
DB::rollBack();
|
||||
throw $ex;
|
||||
}
|
||||
])->request('POST', ($unsuspend) ? '/server/unsuspend' : '/server/suspend');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the SFTP password for a server.
|
||||
*
|
||||
* @param int $id
|
||||
* @param string $password
|
||||
* @return void
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayValidationException
|
||||
*/
|
||||
public function updateSFTPPassword($id, $password)
|
||||
{
|
||||
$server = Models\Server::with('node')->findOrFail($id);
|
||||
|
@ -878,10 +850,8 @@ class ServerRepository
|
|||
throw new DisplayValidationException(json_encode($validator->errors()));
|
||||
}
|
||||
|
||||
DB::beginTransaction();
|
||||
$server->sftp_password = Crypt::encrypt($password);
|
||||
|
||||
try {
|
||||
DB::transaction(function () use ($password, $server) {
|
||||
$server->sftp_password = Crypt::encrypt($password);
|
||||
$server->save();
|
||||
|
||||
$server->node->guzzleClient([
|
||||
|
@ -890,16 +860,6 @@ class ServerRepository
|
|||
])->request('POST', '/server/password', [
|
||||
'json' => ['password' => $password],
|
||||
]);
|
||||
|
||||
DB::commit();
|
||||
|
||||
return true;
|
||||
} catch (TransferException $ex) {
|
||||
DB::rollBack();
|
||||
throw new DisplayException('There was an error while attmping to contact the remote service to change the password.', $ex);
|
||||
} catch (\Exception $ex) {
|
||||
DB::rollBack();
|
||||
throw $ex;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,8 @@ class ServiceRepository
|
|||
*
|
||||
* @param array $data
|
||||
* @return \Pterodactyl\Models\Service
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayValidationException
|
||||
*/
|
||||
public function create(array $data)
|
||||
{
|
||||
|
@ -80,6 +82,8 @@ class ServiceRepository
|
|||
* @param int $id
|
||||
* @param array $data
|
||||
* @return \Pterodactyl\Models\Service
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayValidationException
|
||||
*/
|
||||
public function update($id, array $data)
|
||||
{
|
||||
|
@ -109,6 +113,8 @@ class ServiceRepository
|
|||
*
|
||||
* @param int $id
|
||||
* @return void
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
*/
|
||||
public function delete($id)
|
||||
{
|
||||
|
|
|
@ -26,8 +26,12 @@ namespace Pterodactyl\Repositories;
|
|||
|
||||
use DB;
|
||||
use Validator;
|
||||
use Pterodactyl\Models;
|
||||
use Pterodactyl\Models\User;
|
||||
use Pterodactyl\Models\Server;
|
||||
use Pterodactyl\Models\Subuser;
|
||||
use Pterodactyl\Models\Permission;
|
||||
use Pterodactyl\Services\UuidService;
|
||||
use GuzzleHttp\Exception\TransferException;
|
||||
use Pterodactyl\Exceptions\DisplayException;
|
||||
use Pterodactyl\Exceptions\DisplayValidationException;
|
||||
|
||||
|
@ -37,6 +41,7 @@ class SubuserRepository
|
|||
* Core permissions required for every subuser on the daemon.
|
||||
* Without this we cannot connect the websocket or get basic
|
||||
* information about the server.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $coreDaemonPermissions = [
|
||||
|
@ -44,77 +49,19 @@ class SubuserRepository
|
|||
's:console',
|
||||
];
|
||||
|
||||
/**
|
||||
* Allowed permissions and their related daemon permission.
|
||||
* @var array
|
||||
*/
|
||||
protected $permissions = [
|
||||
// Power Permissions
|
||||
'power-start' => 's:power:start',
|
||||
'power-stop' => 's:power:stop',
|
||||
'power-restart' => 's:power:restart',
|
||||
'power-kill' => 's:power:kill',
|
||||
|
||||
// Commands
|
||||
'send-command' => 's:command',
|
||||
|
||||
// File Manager
|
||||
'list-files' => 's:files:get',
|
||||
'edit-files' => 's:files:read',
|
||||
'save-files' => 's:files:post',
|
||||
'create-files' => 's:files:create',
|
||||
'download-files' => null,
|
||||
'upload-files' => 's:files:upload',
|
||||
'delete-files' => 's:files:delete',
|
||||
'move-files' => 's:files:move',
|
||||
'copy-files' => 's:files:copy',
|
||||
'compress-files' => 's:files:compress',
|
||||
'decompress-files' => 's:files:decompress',
|
||||
|
||||
// Subusers
|
||||
'list-subusers' => null,
|
||||
'view-subuser' => null,
|
||||
'edit-subuser' => null,
|
||||
'create-subuser' => null,
|
||||
'delete-subuser' => null,
|
||||
|
||||
// Tasks
|
||||
'list-tasks' => null,
|
||||
'view-task' => null,
|
||||
'toggle-task' => null,
|
||||
'delete-task' => null,
|
||||
'create-task' => null,
|
||||
'queue-task' => null,
|
||||
|
||||
// Management
|
||||
'set-connection' => null,
|
||||
'view-startup' => null,
|
||||
'edit-startup' => null,
|
||||
'view-sftp' => null,
|
||||
'reset-sftp' => 's:set-password',
|
||||
'view-sftp-password' => null,
|
||||
|
||||
// Databases
|
||||
'view-databases' => null,
|
||||
'reset-db-password' => null,
|
||||
];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new subuser on the server.
|
||||
* @param int $id The ID of the server to add this subuser to.
|
||||
*
|
||||
* @param int $sid
|
||||
* @param array $data
|
||||
* @throws DisplayValidationException
|
||||
* @throws DisplayException
|
||||
* @return \Pterodactyl\Models\Subuser
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\DisplayValidationException
|
||||
*/
|
||||
public function create($sid, array $data)
|
||||
{
|
||||
$server = Models\Server::with('node')->findOrFail($sid);
|
||||
$server = Server::with('node')->findOrFail($sid);
|
||||
|
||||
$validator = Validator::make($data, [
|
||||
'permissions' => 'required|array',
|
||||
|
@ -129,7 +76,7 @@ class SubuserRepository
|
|||
|
||||
try {
|
||||
// Determine if this user exists or if we need to make them an account.
|
||||
$user = Models\User::where('email', $data['email'])->first();
|
||||
$user = User::where('email', $data['email'])->first();
|
||||
if (! $user) {
|
||||
try {
|
||||
$repo = new UserRepository;
|
||||
|
@ -145,26 +92,28 @@ class SubuserRepository
|
|||
}
|
||||
} elseif ($server->owner_id === $user->id) {
|
||||
throw new DisplayException('You cannot add the owner of a server as a subuser.');
|
||||
} elseif (Models\Subuser::select('id')->where('user_id', $user->id)->where('server_id', $server->id)->first()) {
|
||||
} elseif (Subuser::select('id')->where('user_id', $user->id)->where('server_id', $server->id)->first()) {
|
||||
throw new DisplayException('A subuser with that email already exists for this server.');
|
||||
}
|
||||
|
||||
$uuid = new UuidService;
|
||||
$subuser = Models\Subuser::create([
|
||||
$subuser = Subuser::create([
|
||||
'user_id' => $user->id,
|
||||
'server_id' => $server->id,
|
||||
'daemonSecret' => (string) $uuid->generate('servers', 'uuid'),
|
||||
]);
|
||||
|
||||
$perms = Permission::list(true);
|
||||
$daemonPermissions = $this->coreDaemonPermissions;
|
||||
|
||||
foreach ($data['permissions'] as $permission) {
|
||||
if (array_key_exists($permission, $this->permissions)) {
|
||||
if (array_key_exists($permission, $perms)) {
|
||||
// Build the daemon permissions array for sending.
|
||||
if (! is_null($this->permissions[$permission])) {
|
||||
array_push($daemonPermissions, $this->permissions[$permission]);
|
||||
if (! is_null($perms[$permission])) {
|
||||
array_push($daemonPermissions, $perms[$permission]);
|
||||
}
|
||||
|
||||
Models\Permission::create([
|
||||
Permission::create([
|
||||
'subuser_id' => $subuser->id,
|
||||
'permission' => $permission,
|
||||
]);
|
||||
|
@ -189,7 +138,7 @@ class SubuserRepository
|
|||
DB::commit();
|
||||
|
||||
return $subuser;
|
||||
} catch (\GuzzleHttp\Exception\TransferException $ex) {
|
||||
} catch (TransferException $ex) {
|
||||
DB::rollBack();
|
||||
throw new DisplayException('There was an error attempting to connect to the daemon to add this user.', $ex);
|
||||
} catch (\Exception $ex) {
|
||||
|
@ -202,15 +151,15 @@ class SubuserRepository
|
|||
|
||||
/**
|
||||
* Revokes a users permissions on a server.
|
||||
* @param int $id The ID of the subuser row in MySQL.
|
||||
* @param array $data
|
||||
* @throws DisplayValidationException
|
||||
* @throws DisplayException
|
||||
*
|
||||
* @param int $id
|
||||
* @return void
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
*/
|
||||
public function delete($id)
|
||||
{
|
||||
$subuser = Models\Subuser::with('server.node')->findOrFail($id);
|
||||
$subuser = Subuser::with('server.node')->findOrFail($id);
|
||||
$server = $subuser->server;
|
||||
|
||||
DB::beginTransaction();
|
||||
|
@ -232,26 +181,24 @@ class SubuserRepository
|
|||
}
|
||||
$subuser->delete();
|
||||
DB::commit();
|
||||
|
||||
return true;
|
||||
} catch (\GuzzleHttp\Exception\TransferException $ex) {
|
||||
} catch (TransferException $ex) {
|
||||
DB::rollBack();
|
||||
throw new DisplayException('There was an error attempting to connect to the daemon to delete this subuser.', $ex);
|
||||
} catch (\Exception $ex) {
|
||||
DB::rollBack();
|
||||
throw $ex;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates permissions for a given subuser.
|
||||
* @param int $id The ID of the subuser row in MySQL. (Not the user ID)
|
||||
*
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @throws DisplayValidationException
|
||||
* @throws DisplayException
|
||||
* @return void
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\DisplayValidationException
|
||||
*/
|
||||
public function update($id, array $data)
|
||||
{
|
||||
|
@ -265,7 +212,7 @@ class SubuserRepository
|
|||
throw new DisplayValidationException(json_encode($validator->all()));
|
||||
}
|
||||
|
||||
$subuser = Models\Subuser::with('server.node')->findOrFail($id);
|
||||
$subuser = Subuser::with('server.node')->findOrFail($id);
|
||||
$server = $subuser->server;
|
||||
|
||||
DB::beginTransaction();
|
||||
|
@ -275,14 +222,16 @@ class SubuserRepository
|
|||
$permission->delete();
|
||||
}
|
||||
|
||||
$perms = Permission::list(true);
|
||||
$daemonPermissions = $this->coreDaemonPermissions;
|
||||
|
||||
foreach ($data['permissions'] as $permission) {
|
||||
if (array_key_exists($permission, $this->permissions)) {
|
||||
if (array_key_exists($permission, $perms)) {
|
||||
// Build the daemon permissions array for sending.
|
||||
if (! is_null($this->permissions[$permission])) {
|
||||
array_push($daemonPermissions, $this->permissions[$permission]);
|
||||
if (! is_null($perms[$permission])) {
|
||||
array_push($daemonPermissions, $perms[$permission]);
|
||||
}
|
||||
Models\Permission::create([
|
||||
Permission::create([
|
||||
'subuser_id' => $subuser->id,
|
||||
'permission' => $permission,
|
||||
]);
|
||||
|
@ -304,16 +253,12 @@ class SubuserRepository
|
|||
]);
|
||||
|
||||
DB::commit();
|
||||
|
||||
return true;
|
||||
} catch (\GuzzleHttp\Exception\TransferException $ex) {
|
||||
} catch (TransferException $ex) {
|
||||
DB::rollBack();
|
||||
throw new DisplayException('There was an error attempting to connect to the daemon to update permissions.', $ex);
|
||||
} catch (\Exception $ex) {
|
||||
DB::rollBack();
|
||||
throw $ex;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,14 +24,22 @@
|
|||
|
||||
namespace Pterodactyl\Repositories;
|
||||
|
||||
use DB;
|
||||
use Cron;
|
||||
use Validator;
|
||||
use Pterodactyl\Models;
|
||||
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' => '*',
|
||||
|
@ -41,66 +49,60 @@ class TaskRepository
|
|||
'minute' => '*/30',
|
||||
];
|
||||
|
||||
/**
|
||||
* Task action types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $actions = [
|
||||
'command',
|
||||
'power',
|
||||
];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a given task.
|
||||
* @param int $id
|
||||
*
|
||||
* @param int $id
|
||||
* @return bool
|
||||
*/
|
||||
public function delete($id)
|
||||
{
|
||||
$task = Models\Task::findOrFail($id);
|
||||
try {
|
||||
$task->delete();
|
||||
|
||||
return true;
|
||||
} catch (\Exception $ex) {
|
||||
throw $ex;
|
||||
}
|
||||
$task = Task::findOrFail($id);
|
||||
$task->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles a task active or inactive.
|
||||
* @param int $id
|
||||
*
|
||||
* @return int
|
||||
* @param int $id
|
||||
* @return bool
|
||||
*/
|
||||
public function toggle($id)
|
||||
{
|
||||
$task = Models\Task::findOrFail($id);
|
||||
try {
|
||||
$task->active = ($task->active === 1) ? 0 : 1;
|
||||
$task->queued = 0;
|
||||
$task->save();
|
||||
$task = Task::findOrFail($id);
|
||||
|
||||
return $task->active;
|
||||
} catch (\Exception $ex) {
|
||||
throw $ex;
|
||||
}
|
||||
$task->active = ! $task->active;
|
||||
$task->queued = false;
|
||||
$task->save();
|
||||
|
||||
return $task->active;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new scheduled task for a given server.
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
*
|
||||
* @throws DisplayException
|
||||
* @throws DisplayValidationException
|
||||
* @return void
|
||||
* @param int $server
|
||||
* @param int $user
|
||||
* @param array $data
|
||||
* @return \Pterodactyl\Models\Task
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\DisplayValidationException
|
||||
*/
|
||||
public function create($id, $data)
|
||||
public function create($server, $user, $data)
|
||||
{
|
||||
$server = Models\Server::findOrFail($id);
|
||||
$server = Server::findOrFail($server);
|
||||
$user = User::findOrFail($user);
|
||||
|
||||
$validator = Validator::make($data, [
|
||||
'action' => 'string|required',
|
||||
|
@ -142,9 +144,9 @@ class TaskRepository
|
|||
throw $ex;
|
||||
}
|
||||
|
||||
$task = new Models\Task;
|
||||
$task->fill([
|
||||
'server' => $server->id,
|
||||
return Task::create([
|
||||
'user_id' => $user->id,
|
||||
'server_id' => $server->id,
|
||||
'active' => 1,
|
||||
'action' => $data['action'],
|
||||
'data' => $data['data'],
|
||||
|
@ -158,7 +160,5 @@ class TaskRepository
|
|||
'last_run' => null,
|
||||
'next_run' => $buildCron->getNextRunDate(),
|
||||
]);
|
||||
|
||||
return $task->save();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,19 +38,13 @@ use Pterodactyl\Exceptions\DisplayValidationException;
|
|||
|
||||
class UserRepository
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a user on the panel. Returns the created user's ID.
|
||||
*
|
||||
* @param string $email
|
||||
* @param string|null $password An unhashed version of the user's password.
|
||||
* @param bool $admin Boolean value if user should be an admin or not.
|
||||
* @param int $token A custom user ID.
|
||||
* @return bool|int
|
||||
* @param array $data
|
||||
* @return \Pterodactyl\Models\User
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayValidationException
|
||||
*/
|
||||
public function create(array $data)
|
||||
{
|
||||
|
@ -118,9 +112,11 @@ class UserRepository
|
|||
/**
|
||||
* Updates a user on the panel.
|
||||
*
|
||||
* @param int $id
|
||||
* @param array $data An array of columns and their associated values to update for the user.
|
||||
* @return bool
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @return \Pterodactyl\Models\User
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayValidationException
|
||||
*/
|
||||
public function update($id, array $data)
|
||||
{
|
||||
|
@ -151,16 +147,19 @@ class UserRepository
|
|||
unset($data['password']);
|
||||
}
|
||||
|
||||
$user->fill($data);
|
||||
$user->fill($data)->save();
|
||||
|
||||
return $user->save();
|
||||
return $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a user on the panel, returns the number of records deleted.
|
||||
* Deletes a user on the panel.
|
||||
*
|
||||
* @param int $id
|
||||
* @return int
|
||||
* @return void
|
||||
* @todo Move user self-deletion checking to the controller, rather than the repository.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
*/
|
||||
public function delete($id)
|
||||
{
|
||||
|
@ -168,8 +167,7 @@ class UserRepository
|
|||
throw new DisplayException('Cannot delete a user with active servers attached to thier account.');
|
||||
}
|
||||
|
||||
// @TODO: this should probably be checked outside of this method because we won't always have Auth::user()
|
||||
if (! is_null(Auth::user()) && Auth::user()->id === $id) {
|
||||
if (! is_null(Auth::user()) && (int) Auth::user()->id === (int) $id) {
|
||||
throw new DisplayException('Cannot delete your own account.');
|
||||
}
|
||||
|
||||
|
@ -186,8 +184,6 @@ class UserRepository
|
|||
|
||||
Models\User::destroy($id);
|
||||
DB::commit();
|
||||
|
||||
return true;
|
||||
} catch (\Exception $ex) {
|
||||
DB::rollBack();
|
||||
throw $ex;
|
||||
|
|
|
@ -91,7 +91,7 @@ class VariableRepository
|
|||
* Deletes a specified option variable as well as all server
|
||||
* variables currently assigned.
|
||||
*
|
||||
* @param int $id
|
||||
* @param int $id
|
||||
* @return void
|
||||
*/
|
||||
public function delete($id)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue