Push initial implementations of new repository structure
This breaks almost the entire panel, do not pull this branch in this state. Mostly just moved old repository files to a new folder without updating anything else in order to start doing new things. Structure is not finalized.
This commit is contained in:
parent
65957e7ea5
commit
5c2b9deb09
39 changed files with 1083 additions and 166 deletions
207
app/Repositories/Old/APIRepository.php
Normal file
207
app/Repositories/Old/APIRepository.php
Normal file
|
@ -0,0 +1,207 @@
|
|||
<?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 DB;
|
||||
use Auth;
|
||||
use Crypt;
|
||||
use Validator;
|
||||
use IPTools\Network;
|
||||
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
|
||||
{
|
||||
/**
|
||||
* 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 for API Repository.
|
||||
*
|
||||
* @param null|\Pterodactyl\Models\User $user
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(User $user = null)
|
||||
{
|
||||
$this->user = is_null($user) ? Auth::user() : $user;
|
||||
if (is_null($this->user)) {
|
||||
throw new \Exception('Unable to initialize user for API repository instance.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a New API Keypair on the system.
|
||||
*
|
||||
* @param array $data
|
||||
* @return string
|
||||
*
|
||||
* @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',
|
||||
'admin_permissions' => 'sometimes|required|array',
|
||||
]);
|
||||
|
||||
$validator->after(function ($validator) use ($data) {
|
||||
if (array_key_exists('allowed_ips', $data) && ! empty($data['allowed_ips'])) {
|
||||
foreach (explode("\n", $data['allowed_ips']) as $ip) {
|
||||
$ip = trim($ip);
|
||||
try {
|
||||
Network::parse($ip);
|
||||
array_push($this->allowed, $ip);
|
||||
} catch (\Exception $ex) {
|
||||
$validator->errors()->add('allowed_ips', 'Could not parse IP <' . $ip . '> because it is in an invalid format.');
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Run validator, throw catchable and displayable exception if it fails.
|
||||
// Exception includes a JSON result of failed validation rules.
|
||||
if ($validator->fails()) {
|
||||
throw new DisplayValidationException(json_encode($validator->errors()));
|
||||
}
|
||||
|
||||
DB::beginTransaction();
|
||||
try {
|
||||
$secretKey = str_random(16) . '.' . str_random(7) . '.' . str_random(7);
|
||||
$key = Key::create([
|
||||
'user_id' => $this->user->id,
|
||||
'public' => str_random(16),
|
||||
'secret' => Crypt::encrypt($secretKey),
|
||||
'allowed_ips' => empty($this->allowed) ? null : json_encode($this->allowed),
|
||||
'memo' => $data['memo'],
|
||||
'expires_at' => null,
|
||||
]);
|
||||
|
||||
$totalPermissions = 0;
|
||||
$pNodes = Permission::permissions();
|
||||
|
||||
if (isset($data['permissions'])) {
|
||||
foreach ($data['permissions'] as $permission) {
|
||||
$parts = explode('-', $permission);
|
||||
|
||||
if (count($parts) !== 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
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['admin_permissions'])) {
|
||||
unset($pNodes['_user']);
|
||||
|
||||
foreach ($data['admin_permissions'] as $permission) {
|
||||
$parts = explode('-', $permission);
|
||||
|
||||
if (count($parts) !== 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
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,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
if ($totalPermissions < 1) {
|
||||
throw new DisplayException('No valid permissions were passed.');
|
||||
}
|
||||
|
||||
DB::commit();
|
||||
|
||||
return $secretKey;
|
||||
} catch (\Exception $ex) {
|
||||
DB::rollBack();
|
||||
throw $ex;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Revokes an API key and associated permissions.
|
||||
*
|
||||
* @param string $key
|
||||
* @return void
|
||||
*
|
||||
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException
|
||||
*/
|
||||
public function revoke($key)
|
||||
{
|
||||
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();
|
||||
});
|
||||
}
|
||||
}
|
284
app/Repositories/Old/DatabaseRepository.php
Normal file
284
app/Repositories/Old/DatabaseRepository.php
Normal file
|
@ -0,0 +1,284 @@
|
|||
<?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 DB;
|
||||
use Crypt;
|
||||
use Validator;
|
||||
use Pterodactyl\Models\Server;
|
||||
use Pterodactyl\Models\Database;
|
||||
use Pterodactyl\Models\DatabaseHost;
|
||||
use Pterodactyl\Exceptions\DisplayException;
|
||||
use Pterodactyl\Exceptions\DisplayValidationException;
|
||||
|
||||
class DatabaseRepository
|
||||
{
|
||||
/**
|
||||
* Adds a new database to a specified database host server.
|
||||
*
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @return \Pterodactyl\Models\Database
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\DisplayValidationException
|
||||
*/
|
||||
public function create($id, array $data)
|
||||
{
|
||||
$server = Server::findOrFail($id);
|
||||
|
||||
$validator = Validator::make($data, [
|
||||
'host' => 'required|exists:database_hosts,id',
|
||||
'database' => 'required|regex:/^\w{1,100}$/',
|
||||
'connection' => 'required|regex:/^[0-9%.]{1,15}$/',
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
throw new DisplayValidationException(json_encode($validator->errors()));
|
||||
}
|
||||
|
||||
$host = DatabaseHost::findOrFail($data['host']);
|
||||
DB::beginTransaction();
|
||||
|
||||
try {
|
||||
$database = Database::firstOrNew([
|
||||
'server_id' => $server->id,
|
||||
'database_host_id' => $data['host'],
|
||||
'database' => sprintf('s%d_%s', $server->id, $data['database']),
|
||||
]);
|
||||
|
||||
if ($database->exists) {
|
||||
throw new DisplayException('A database with those details already exists in the system.');
|
||||
}
|
||||
|
||||
$database->username = sprintf('s%d_%s', $server->id, str_random(10));
|
||||
$database->remote = $data['connection'];
|
||||
$database->password = Crypt::encrypt(str_random(20));
|
||||
|
||||
$database->save();
|
||||
} catch (\Exception $ex) {
|
||||
DB::rollBack();
|
||||
throw $ex;
|
||||
}
|
||||
|
||||
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\'',
|
||||
$database->username, $database->remote, Crypt::decrypt($database->password)
|
||||
));
|
||||
DB::connection('dynamic')->statement(sprintf(
|
||||
'GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, ALTER, INDEX ON `%s`.* TO `%s`@`%s`',
|
||||
$database->database, $database->username, $database->remote
|
||||
));
|
||||
|
||||
DB::connection('dynamic')->statement('FLUSH PRIVILEGES');
|
||||
|
||||
// Save Everything
|
||||
DB::commit();
|
||||
|
||||
return $database;
|
||||
} catch (\Exception $ex) {
|
||||
try {
|
||||
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');
|
||||
} catch (\Exception $ex) {
|
||||
}
|
||||
|
||||
DB::rollBack();
|
||||
throw $ex;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the password for a given database.
|
||||
*
|
||||
* @param int $id
|
||||
* @param string $password
|
||||
* @return void
|
||||
*
|
||||
* @todo Fix logic behind resetting passwords.
|
||||
*/
|
||||
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);
|
||||
|
||||
// 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)))
|
||||
// but no garuntees that will work correctly with every system.
|
||||
DB::connection('dynamic')->statement(sprintf('DROP USER IF EXISTS `%s`@`%s`', $database->username, $database->remote));
|
||||
DB::connection('dynamic')->statement(sprintf(
|
||||
'CREATE USER `%s`@`%s` IDENTIFIED BY \'%s\'',
|
||||
$database->username, $database->remote, $password
|
||||
));
|
||||
DB::connection('dynamic')->statement(sprintf(
|
||||
'GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, ALTER, INDEX ON `%s`.* TO `%s`@`%s`',
|
||||
$database->database, $database->username, $database->remote
|
||||
));
|
||||
DB::connection('dynamic')->statement('FLUSH PRIVILEGES');
|
||||
|
||||
$database->save();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Drops a database from the associated database host.
|
||||
*
|
||||
* @param int $id
|
||||
* @return void
|
||||
*/
|
||||
public function drop($id)
|
||||
{
|
||||
$database = Database::with('host')->findOrFail($id);
|
||||
$database->host->setDynamicConnection();
|
||||
|
||||
DB::transaction(function () use ($database) {
|
||||
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');
|
||||
|
||||
$database->delete();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a database host from the system if it has no associated databases.
|
||||
*
|
||||
* @param int $id
|
||||
* @return void
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
*/
|
||||
public function delete($id)
|
||||
{
|
||||
$host = DatabaseHost::withCount('databases')->findOrFail($id);
|
||||
|
||||
if ($host->databases_count > 0) {
|
||||
throw new DisplayException('You cannot delete a database host that has active databases attached to it.');
|
||||
}
|
||||
|
||||
$host->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new Database Host to the system.
|
||||
*
|
||||
* @param array $data
|
||||
* @return \Pterodactyl\Models\DatabaseHost
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayValidationException
|
||||
*/
|
||||
public function add(array $data)
|
||||
{
|
||||
if (isset($data['host'])) {
|
||||
$data['host'] = gethostbyname($data['host']);
|
||||
}
|
||||
|
||||
$validator = Validator::make($data, [
|
||||
'name' => 'required|string|max:255',
|
||||
'host' => 'required|ip|unique:database_hosts,host',
|
||||
'port' => 'required|numeric|between:1,65535',
|
||||
'username' => 'required|string|max:32',
|
||||
'password' => 'required|string',
|
||||
'node_id' => 'sometimes|required|exists:nodes,id',
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
throw new DisplayValidationException(json_encode($validator->errors()));
|
||||
}
|
||||
|
||||
return DB::transaction(function () use ($data) {
|
||||
$host = new DatabaseHost;
|
||||
$host->password = Crypt::encrypt($data['password']);
|
||||
|
||||
$host->fill([
|
||||
'name' => $data['name'],
|
||||
'host' => $data['host'],
|
||||
'port' => $data['port'],
|
||||
'username' => $data['username'],
|
||||
'max_databases' => null,
|
||||
'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;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a Database Host on the system.
|
||||
*
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @return \Pterodactyl\Models\DatabaseHost
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayValidationException
|
||||
*/
|
||||
public function update($id, array $data)
|
||||
{
|
||||
$host = DatabaseHost::findOrFail($id);
|
||||
|
||||
if (isset($data['host'])) {
|
||||
$data['host'] = gethostbyname($data['host']);
|
||||
}
|
||||
|
||||
$validator = Validator::make($data, [
|
||||
'name' => 'sometimes|required|string|max:255',
|
||||
'host' => 'sometimes|required|ip|unique:database_hosts,host,' . $host->id,
|
||||
'port' => 'sometimes|required|numeric|between:1,65535',
|
||||
'username' => 'sometimes|required|string|max:32',
|
||||
'password' => 'sometimes|required|string',
|
||||
'node_id' => 'sometimes|required|exists:nodes,id',
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
throw new DisplayValidationException(json_encode($validator->errors()));
|
||||
}
|
||||
|
||||
return DB::transaction(function () use ($data, $host) {
|
||||
if (isset($data['password'])) {
|
||||
$host->password = Crypt::encrypt($data['password']);
|
||||
}
|
||||
$host->fill($data)->save();
|
||||
|
||||
// Check that we can still connect with these details.
|
||||
$host->setDynamicConnection();
|
||||
DB::connection('dynamic')->select('SELECT 1 FROM dual');
|
||||
|
||||
return $host;
|
||||
});
|
||||
}
|
||||
}
|
73
app/Repositories/Old/HelperRepository.php
Normal file
73
app/Repositories/Old/HelperRepository.php
Normal file
|
@ -0,0 +1,73 @@
|
|||
<?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;
|
||||
|
||||
class HelperRepository
|
||||
{
|
||||
/**
|
||||
* Listing of editable files in the control panel.
|
||||
*
|
||||
* @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
|
||||
* @return string
|
||||
* @deprecated
|
||||
*/
|
||||
public static function bytesToHuman($bytes, $decimals = 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;
|
||||
}
|
||||
}
|
104
app/Repositories/Old/LocationRepository.php
Normal file
104
app/Repositories/Old/LocationRepository.php
Normal file
|
@ -0,0 +1,104 @@
|
|||
<?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 Validator;
|
||||
use Pterodactyl\Models\Location;
|
||||
use Pterodactyl\Exceptions\DisplayException;
|
||||
use Pterodactyl\Exceptions\DisplayValidationException;
|
||||
|
||||
class LocationRepository
|
||||
{
|
||||
/**
|
||||
* Creates a new location on the system.
|
||||
*
|
||||
* @param array $data
|
||||
* @return \Pterodactyl\Models\Location
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayValidationException
|
||||
*/
|
||||
public function create(array $data)
|
||||
{
|
||||
$validator = Validator::make($data, [
|
||||
'short' => 'required|string|between:1,60|unique:locations,short',
|
||||
'long' => 'required|string|between:1,255',
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
throw new DisplayValidationException(json_encode($validator->errors()));
|
||||
}
|
||||
|
||||
return Location::create([
|
||||
'long' => $data['long'],
|
||||
'short' => $data['short'],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifies a location.
|
||||
*
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @return \Pterodactyl\Models\Location
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayValidationException
|
||||
*/
|
||||
public function update($id, array $data)
|
||||
{
|
||||
$location = Location::findOrFail($id);
|
||||
|
||||
$validator = Validator::make($data, [
|
||||
'short' => 'sometimes|required|string|between:1,60|unique:locations,short,' . $location->id,
|
||||
'long' => 'sometimes|required|string|between:1,255',
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
throw new DisplayValidationException(json_encode($validator->errors()));
|
||||
}
|
||||
|
||||
$location->fill($data)->save();
|
||||
|
||||
return $location;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a location from the system.
|
||||
*
|
||||
* @param int $id
|
||||
* @return void
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
*/
|
||||
public function delete($id)
|
||||
{
|
||||
$location = Location::withCount('nodes')->findOrFail($id);
|
||||
|
||||
if ($location->nodes_count > 0) {
|
||||
throw new DisplayException('Cannot delete a location that has nodes assigned to it.');
|
||||
}
|
||||
|
||||
$location->delete();
|
||||
}
|
||||
}
|
291
app/Repositories/Old/NodeRepository.php
Normal file
291
app/Repositories/Old/NodeRepository.php
Normal file
|
@ -0,0 +1,291 @@
|
|||
<?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 DB;
|
||||
use Validator;
|
||||
use IPTools\Network;
|
||||
use Pterodactyl\Models;
|
||||
use Pterodactyl\Services\UuidService;
|
||||
use Pterodactyl\Exceptions\DisplayException;
|
||||
use Pterodactyl\Exceptions\DisplayValidationException;
|
||||
|
||||
class NodeRepository
|
||||
{
|
||||
/**
|
||||
* 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
|
||||
$validator = Validator::make($data, [
|
||||
'name' => 'required|regex:/^([\w .-]{1,100})$/',
|
||||
'location_id' => 'required|numeric|min:1|exists:locations,id',
|
||||
'public' => 'required|numeric|between:0,1',
|
||||
'fqdn' => 'required|string|unique:nodes,fqdn',
|
||||
'scheme' => 'required|regex:/^(http(s)?)$/',
|
||||
'behind_proxy' => 'required|boolean',
|
||||
'memory' => 'required|numeric|min:1',
|
||||
'memory_overallocate' => 'required|numeric|min:-1',
|
||||
'disk' => 'required|numeric|min:1',
|
||||
'disk_overallocate' => 'required|numeric|min:-1',
|
||||
'daemonBase' => 'required|regex:/^([\/][\d\w.\-\/]+)$/',
|
||||
'daemonSFTP' => 'required|numeric|between:1,65535',
|
||||
'daemonListen' => 'required|numeric|between:1,65535',
|
||||
]);
|
||||
|
||||
// Run validator, throw catchable and displayable exception if it fails.
|
||||
// Exception includes a JSON result of failed validation rules.
|
||||
if ($validator->fails()) {
|
||||
throw new DisplayValidationException(json_encode($validator->errors()));
|
||||
}
|
||||
|
||||
// Verify the FQDN if using SSL
|
||||
if (filter_var($data['fqdn'], FILTER_VALIDATE_IP) && $data['scheme'] === 'https') {
|
||||
throw new DisplayException('A fully qualified domain name is required to use a secure comunication method on this node.');
|
||||
}
|
||||
|
||||
// Verify FQDN is resolvable, or if not using SSL that the IP is valid.
|
||||
if (! filter_var(gethostbyname($data['fqdn']), FILTER_VALIDATE_IP)) {
|
||||
throw new DisplayException('The FQDN (or IP Address) provided does not resolve to a valid IP address.');
|
||||
}
|
||||
|
||||
// Should we be nulling the overallocations?
|
||||
$data['memory_overallocate'] = ($data['memory_overallocate'] < 0) ? null : $data['memory_overallocate'];
|
||||
$data['disk_overallocate'] = ($data['disk_overallocate'] < 0) ? null : $data['disk_overallocate'];
|
||||
|
||||
// Set the Secret
|
||||
$uuid = new UuidService;
|
||||
$data['daemonSecret'] = (string) $uuid->generate('nodes', 'daemonSecret');
|
||||
|
||||
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);
|
||||
|
||||
// Validate Fields
|
||||
$validator = $validator = Validator::make($data, [
|
||||
'name' => 'regex:/^([\w .-]{1,100})$/',
|
||||
'location_id' => 'numeric|min:1|exists:locations,id',
|
||||
'public' => 'numeric|between:0,1',
|
||||
'fqdn' => 'string|unique:nodes,fqdn,' . $id,
|
||||
'scheme' => 'regex:/^(http(s)?)$/',
|
||||
'behind_proxy' => 'boolean',
|
||||
'memory' => 'numeric|min:1',
|
||||
'memory_overallocate' => 'numeric|min:-1',
|
||||
'disk' => 'numeric|min:1',
|
||||
'disk_overallocate' => 'numeric|min:-1',
|
||||
'upload_size' => 'numeric|min:0',
|
||||
'daemonBase' => 'sometimes|regex:/^([\/][\d\w.\-\/]+)$/',
|
||||
'daemonSFTP' => 'numeric|between:1,65535',
|
||||
'daemonListen' => 'numeric|between:1,65535',
|
||||
'reset_secret' => 'sometimes|nullable|accepted',
|
||||
]);
|
||||
|
||||
// Run validator, throw catchable and displayable exception if it fails.
|
||||
// Exception includes a JSON result of failed validation rules.
|
||||
if ($validator->fails()) {
|
||||
throw new DisplayValidationException(json_encode($validator->errors()));
|
||||
}
|
||||
|
||||
// Verify the FQDN
|
||||
if (isset($data['fqdn'])) {
|
||||
|
||||
// Verify the FQDN if using SSL
|
||||
if ((isset($data['scheme']) && $data['scheme'] === 'https') || (! isset($data['scheme']) && $node->scheme === 'https')) {
|
||||
if (filter_var($data['fqdn'], FILTER_VALIDATE_IP)) {
|
||||
throw new DisplayException('A fully qualified domain name is required to use secure comunication on this node.');
|
||||
}
|
||||
}
|
||||
|
||||
// Verify FQDN is resolvable, or if not using SSL that the IP is valid.
|
||||
if (! filter_var(gethostbyname($data['fqdn']), FILTER_VALIDATE_IP)) {
|
||||
throw new DisplayException('The FQDN (or IP Address) provided does not resolve to a valid IP address.');
|
||||
}
|
||||
}
|
||||
|
||||
// Should we be nulling the overallocations?
|
||||
if (isset($data['memory_overallocate'])) {
|
||||
$data['memory_overallocate'] = ($data['memory_overallocate'] < 0) ? null : $data['memory_overallocate'];
|
||||
}
|
||||
|
||||
if (isset($data['disk_overallocate'])) {
|
||||
$data['disk_overallocate'] = ($data['disk_overallocate'] < 0) ? null : $data['disk_overallocate'];
|
||||
}
|
||||
|
||||
// Set the Secret
|
||||
if (isset($data['reset_secret']) && ! is_null($data['reset_secret'])) {
|
||||
$uuid = new UuidService;
|
||||
$data['daemonSecret'] = (string) $uuid->generate('nodes', 'daemonSecret');
|
||||
unset($data['reset_secret']);
|
||||
}
|
||||
|
||||
$oldDaemonKey = $node->daemonSecret;
|
||||
$node->update($data);
|
||||
try {
|
||||
$node->guzzleClient(['X-Access-Token' => $oldDaemonKey])->request('PATCH', '/config', [
|
||||
'json' => [
|
||||
'web' => [
|
||||
'listen' => $node->daemonListen,
|
||||
'ssl' => [
|
||||
'enabled' => (! $node->behind_proxy && $node->scheme === 'https'),
|
||||
],
|
||||
],
|
||||
'sftp' => [
|
||||
'path' => $node->daemonBase,
|
||||
'port' => $node->daemonSFTP,
|
||||
],
|
||||
'remote' => [
|
||||
'base' => config('app.url'),
|
||||
],
|
||||
'uploads' => [
|
||||
'size_limit' => $node->upload_size,
|
||||
],
|
||||
'keys' => [
|
||||
$node->daemonSecret,
|
||||
],
|
||||
],
|
||||
]);
|
||||
} catch (\Exception $ex) {
|
||||
throw new DisplayException('Failed to update the node configuration, however your changes have been saved to the database. You will need to manually update the configuration file for the node to apply these changes.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds allocations to a provided node.
|
||||
*
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @return void
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\DisplayValidationException
|
||||
*/
|
||||
public function addAllocations($id, array $data)
|
||||
{
|
||||
$node = Models\Node::findOrFail($id);
|
||||
|
||||
$validator = Validator::make($data, [
|
||||
'allocation_ip' => 'required|string',
|
||||
'allocation_alias' => 'sometimes|required|string|max:255',
|
||||
'allocation_ports' => 'required|array',
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
throw new DisplayValidationException(json_encode($validator->errors()));
|
||||
}
|
||||
|
||||
$explode = explode('/', $data['allocation_ip']);
|
||||
if (count($explode) !== 1) {
|
||||
if (! ctype_digit($explode[1]) || ($explode[1] > 32 || $explode[1] < 25)) {
|
||||
throw new DisplayException('CIDR notation only allows masks between /32 and /25.');
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
if (! ctype_digit($port) && ! preg_match('/^(\d{1,5})-(\d{1,5})$/', $port)) {
|
||||
throw new DisplayException('The mapping for <code>' . $port . '</code> is invalid and cannot be processed.');
|
||||
}
|
||||
|
||||
if (preg_match('/^(\d{1,5})-(\d{1,5})$/', $port, $matches)) {
|
||||
$block = range($matches[1], $matches[2]);
|
||||
|
||||
if (count($block) > 1000) {
|
||||
throw new DisplayException('Adding more than 1000 ports at once is not supported. Please use a smaller port range.');
|
||||
}
|
||||
|
||||
foreach ($block as $unit) {
|
||||
// Insert into Database
|
||||
Models\Allocation::firstOrCreate([
|
||||
'node_id' => $node->id,
|
||||
'ip' => $ip,
|
||||
'port' => $unit,
|
||||
'ip_alias' => isset($data['allocation_alias']) ? $data['allocation_alias'] : null,
|
||||
'server_id' => null,
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
// Insert into Database
|
||||
Models\Allocation::firstOrCreate([
|
||||
'node_id' => $node->id,
|
||||
'ip' => $ip,
|
||||
'port' => $port,
|
||||
'ip_alias' => isset($data['allocation_alias']) ? $data['allocation_alias'] : null,
|
||||
'server_id' => null,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
if ($node->servers_count > 0) {
|
||||
throw new DisplayException('You cannot delete a node with servers currently attached to it.');
|
||||
}
|
||||
|
||||
DB::transaction(function () use ($node) {
|
||||
// Unlink Database Servers
|
||||
Models\DatabaseHost::where('node_id', $node->id)->update(['node_id' => null]);
|
||||
|
||||
// Delete Allocations
|
||||
Models\Allocation::where('node_id', $node->id)->delete();
|
||||
|
||||
// Delete Node
|
||||
$node->delete();
|
||||
});
|
||||
}
|
||||
}
|
241
app/Repositories/Old/OptionRepository.php
Normal file
241
app/Repositories/Old/OptionRepository.php
Normal file
|
@ -0,0 +1,241 @@
|
|||
<?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 DB;
|
||||
use Validator;
|
||||
use InvalidArgumentException;
|
||||
use Pterodactyl\Models\ServiceOption;
|
||||
use Pterodactyl\Exceptions\DisplayException;
|
||||
use Pterodactyl\Exceptions\DisplayValidationException;
|
||||
|
||||
class OptionRepository
|
||||
{
|
||||
/**
|
||||
* Store the requested service option.
|
||||
*
|
||||
* @var \Pterodactyl\Models\ServiceOption
|
||||
*/
|
||||
protected $model;
|
||||
|
||||
/**
|
||||
* OptionRepository constructor.
|
||||
*
|
||||
* @param null|int|\Pterodactyl\Models\ServiceOption $option
|
||||
*/
|
||||
public function __construct($option = null)
|
||||
{
|
||||
if (is_null($option)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($option instanceof ServiceOption) {
|
||||
$this->model = $option;
|
||||
} else {
|
||||
if (! is_numeric($option)) {
|
||||
throw new InvalidArgumentException(
|
||||
sprintf('Variable passed to constructor must be integer or instance of \Pterodactyl\Models\ServiceOption.')
|
||||
);
|
||||
}
|
||||
|
||||
$this->model = ServiceOption::findOrFail($option);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the eloquent model for the given repository.
|
||||
*
|
||||
* @return null|\Pterodactyl\Models\ServiceOption
|
||||
*/
|
||||
public function getModel()
|
||||
{
|
||||
return $this->model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the currently assigned model by re-initalizing the class.
|
||||
*
|
||||
* @param null|int|\Pterodactyl\Models\ServiceOption $option
|
||||
* @return $this
|
||||
*/
|
||||
public function setModel($option)
|
||||
{
|
||||
self::__construct($option);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new service option on the system.
|
||||
*
|
||||
* @param array $data
|
||||
* @return \Pterodactyl\Models\ServiceOption
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\DisplayValidationException
|
||||
*/
|
||||
public function create(array $data)
|
||||
{
|
||||
$validator = Validator::make($data, [
|
||||
'service_id' => 'required|numeric|exists:services,id',
|
||||
'name' => 'required|string|max:255',
|
||||
'description' => 'required|string',
|
||||
'tag' => 'required|alpha_num|max:60|unique:service_options,tag',
|
||||
'docker_image' => 'sometimes|string|max:255',
|
||||
'startup' => 'sometimes|nullable|string',
|
||||
'config_from' => 'sometimes|required|numeric|exists:service_options,id',
|
||||
'config_startup' => 'required_without:config_from|json',
|
||||
'config_stop' => 'required_without:config_from|string|max:255',
|
||||
'config_logs' => 'required_without:config_from|json',
|
||||
'config_files' => 'required_without:config_from|json',
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
throw new DisplayValidationException(json_encode($validator->errors()));
|
||||
}
|
||||
|
||||
if (isset($data['config_from'])) {
|
||||
if (! ServiceOption::where('service_id', $data['service_id'])->where('id', $data['config_from'])->first()) {
|
||||
throw new DisplayException('The `configuration from` directive must be a child of the assigned service.');
|
||||
}
|
||||
}
|
||||
|
||||
return $this->setModel(ServiceOption::create($data))->getModel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a service option from the system.
|
||||
*
|
||||
* @param int $id
|
||||
* @return void
|
||||
*
|
||||
* @throws \Exception
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function delete($id)
|
||||
{
|
||||
$this->model->load('variables', 'servers');
|
||||
|
||||
if ($this->model->servers->count() > 0) {
|
||||
throw new DisplayException('You cannot delete a service option that has servers associated with it.');
|
||||
}
|
||||
|
||||
DB::transaction(function () use ($option) {
|
||||
foreach ($option->variables as $variable) {
|
||||
(new VariableRepository)->delete($variable->id);
|
||||
}
|
||||
|
||||
$option->delete();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a service option in the database which can then be used
|
||||
* on nodes.
|
||||
*
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @return \Pterodactyl\Models\ServiceOption
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\DisplayValidationException
|
||||
*/
|
||||
public function update($id, array $data)
|
||||
{
|
||||
$option = ServiceOption::findOrFail($id);
|
||||
|
||||
// Due to code limitations (at least when I am writing this currently)
|
||||
// we have to make an assumption that if config_from is not passed
|
||||
// that we should be telling it that no config is wanted anymore.
|
||||
//
|
||||
// This really is only an issue if we open API access to this function,
|
||||
// in which case users will always need to pass `config_from` in order
|
||||
// to keep it assigned.
|
||||
if (! isset($data['config_from']) && ! is_null($option->config_from)) {
|
||||
$option->config_from = null;
|
||||
}
|
||||
|
||||
$validator = Validator::make($data, [
|
||||
'name' => 'sometimes|required|string|max:255',
|
||||
'description' => 'sometimes|required|string',
|
||||
'tag' => 'sometimes|required|string|max:255|unique:service_options,tag,' . $option->id,
|
||||
'docker_image' => 'sometimes|required|string|max:255',
|
||||
'startup' => 'sometimes|required|string',
|
||||
'config_from' => 'sometimes|required|numeric|exists:service_options,id',
|
||||
]);
|
||||
|
||||
$validator->sometimes([
|
||||
'config_startup', 'config_logs', 'config_files',
|
||||
], 'required_without:config_from|json', function ($input) use ($option) {
|
||||
return ! (! $input->config_from && ! is_null($option->config_from));
|
||||
});
|
||||
|
||||
$validator->sometimes('config_stop', 'required_without:config_from|string|max:255', function ($input) use ($option) {
|
||||
return ! (! $input->config_from && ! is_null($option->config_from));
|
||||
});
|
||||
|
||||
if ($validator->fails()) {
|
||||
throw new DisplayValidationException(json_encode($validator->errors()));
|
||||
}
|
||||
|
||||
if (isset($data['config_from'])) {
|
||||
if (! ServiceOption::where('service_id', $option->service_id)->where('id', $data['config_from'])->first()) {
|
||||
throw new DisplayException('The `configuration from` directive must be a child of the assigned service.');
|
||||
}
|
||||
}
|
||||
|
||||
$option->fill($data)->save();
|
||||
|
||||
return $option;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a service option's scripts in the database.
|
||||
*
|
||||
* @param array $data
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
*/
|
||||
public function scripts(array $data)
|
||||
{
|
||||
$data['script_install'] = empty($data['script_install']) ? null : $data['script_install'];
|
||||
|
||||
if (isset($data['copy_script_from']) && ! empty($data['copy_script_from'])) {
|
||||
$select = ServiceOption::whereNull('copy_script_from')
|
||||
->where('id', $data['copy_script_from'])
|
||||
->where('service_id', $this->model->service_id)
|
||||
->first();
|
||||
|
||||
if (! $select) {
|
||||
throw new DisplayException('The service option selected to copy a script from either does not exist, or is copying from a higher level.');
|
||||
}
|
||||
} else {
|
||||
$data['copy_script_from'] = null;
|
||||
}
|
||||
|
||||
$this->model->fill($data)->save();
|
||||
}
|
||||
}
|
239
app/Repositories/Old/PackRepository.php
Normal file
239
app/Repositories/Old/PackRepository.php
Normal file
|
@ -0,0 +1,239 @@
|
|||
<?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 DB;
|
||||
use Uuid;
|
||||
use Storage;
|
||||
use Validator;
|
||||
use Pterodactyl\Models\Pack;
|
||||
use Pterodactyl\Services\UuidService;
|
||||
use Pterodactyl\Exceptions\DisplayException;
|
||||
use Pterodactyl\Exceptions\DisplayValidationException;
|
||||
|
||||
class PackRepository
|
||||
{
|
||||
/**
|
||||
* Creates a new pack on the system.
|
||||
*
|
||||
* @param array $data
|
||||
* @return \Pterodactyl\Models\Pack
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\DisplayValidationException
|
||||
*/
|
||||
public function create(array $data)
|
||||
{
|
||||
$validator = Validator::make($data, [
|
||||
'name' => 'required|string',
|
||||
'version' => 'required|string',
|
||||
'description' => 'sometimes|nullable|string',
|
||||
'selectable' => 'sometimes|required|boolean',
|
||||
'visible' => 'sometimes|required|boolean',
|
||||
'locked' => 'sometimes|required|boolean',
|
||||
'option_id' => 'required|exists:service_options,id',
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
throw new DisplayValidationException(json_encode($validator->errors()));
|
||||
}
|
||||
|
||||
if (isset($data['file_upload'])) {
|
||||
if (! $data['file_upload']->isValid()) {
|
||||
throw new DisplayException('The file provided does not appear to be valid.');
|
||||
}
|
||||
|
||||
if (! in_array($data['file_upload']->getMimeType(), ['application/gzip', 'application/x-gzip'])) {
|
||||
throw new DisplayException('The file provided (' . $data['file_upload']->getMimeType() . ') does not meet the required filetype of application/gzip.');
|
||||
}
|
||||
}
|
||||
|
||||
return DB::transaction(function () use ($data) {
|
||||
$uuid = new UuidService();
|
||||
|
||||
$pack = new Pack;
|
||||
$pack->uuid = $uuid->generate('packs', 'uuid');
|
||||
$pack->fill([
|
||||
'option_id' => $data['option_id'],
|
||||
'name' => $data['name'],
|
||||
'version' => $data['version'],
|
||||
'description' => (empty($data['description'])) ? null : $data['description'],
|
||||
'selectable' => isset($data['selectable']),
|
||||
'visible' => isset($data['visible']),
|
||||
'locked' => isset($data['locked']),
|
||||
])->save();
|
||||
|
||||
if (! $pack->exists) {
|
||||
throw new DisplayException('Model does not exist after creation. Did an event prevent it from saving?');
|
||||
}
|
||||
|
||||
Storage::makeDirectory('packs/' . $pack->uuid);
|
||||
if (isset($data['file_upload'])) {
|
||||
$data['file_upload']->storeAs('packs/' . $pack->uuid, 'archive.tar.gz');
|
||||
}
|
||||
|
||||
return $pack;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new pack on the system given a template file.
|
||||
*
|
||||
* @param array $data
|
||||
* @return \Pterodactyl\Models\Pack
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
*/
|
||||
public function createWithTemplate(array $data)
|
||||
{
|
||||
if (! isset($data['file_upload'])) {
|
||||
throw new DisplayException('No template file was found submitted with this request.');
|
||||
}
|
||||
|
||||
if (! $data['file_upload']->isValid()) {
|
||||
throw new DisplayException('The file provided does not appear to be valid.');
|
||||
}
|
||||
|
||||
if (! in_array($data['file_upload']->getMimeType(), [
|
||||
'application/zip',
|
||||
'text/plain',
|
||||
'application/json',
|
||||
])) {
|
||||
throw new DisplayException('The file provided (' . $data['file_upload']->getMimeType() . ') does not meet the required filetypes of application/zip or application/json.');
|
||||
}
|
||||
|
||||
if ($data['file_upload']->getMimeType() === 'application/zip') {
|
||||
$zip = new \ZipArchive;
|
||||
if (! $zip->open($data['file_upload']->path())) {
|
||||
throw new DisplayException('The uploaded archive was unable to be opened.');
|
||||
}
|
||||
|
||||
$isTar = $zip->locateName('archive.tar.gz');
|
||||
|
||||
if (! $zip->locateName('import.json') || ! $isTar) {
|
||||
throw new DisplayException('This contents of the provided archive were in an invalid format.');
|
||||
}
|
||||
|
||||
$json = json_decode($zip->getFromName('import.json'));
|
||||
$pack = $this->create([
|
||||
'name' => $json->name,
|
||||
'version' => $json->version,
|
||||
'description' => $json->description,
|
||||
'option_id' => $data['option_id'],
|
||||
'selectable' => $json->selectable,
|
||||
'visible' => $json->visible,
|
||||
'locked' => $json->locked,
|
||||
]);
|
||||
|
||||
if (! $zip->extractTo(storage_path('app/packs/' . $pack->uuid), 'archive.tar.gz')) {
|
||||
$pack->delete();
|
||||
throw new DisplayException('Unable to extract the archive file to the correct location.');
|
||||
}
|
||||
|
||||
$zip->close();
|
||||
|
||||
return $pack;
|
||||
} else {
|
||||
$json = json_decode(file_get_contents($data['file_upload']->path()));
|
||||
|
||||
return $this->create([
|
||||
'name' => $json->name,
|
||||
'version' => $json->version,
|
||||
'description' => $json->description,
|
||||
'option_id' => $data['option_id'],
|
||||
'selectable' => $json->selectable,
|
||||
'visible' => $json->visible,
|
||||
'locked' => $json->locked,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a pack on the system.
|
||||
*
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @return \Pterodactyl\Models\Pack
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\DisplayValidationException
|
||||
*/
|
||||
public function update($id, array $data)
|
||||
{
|
||||
$validator = Validator::make($data, [
|
||||
'name' => 'sometimes|required|string',
|
||||
'option_id' => 'sometimes|required|exists:service_options,id',
|
||||
'version' => 'sometimes|required|string',
|
||||
'description' => 'sometimes|string',
|
||||
'selectable' => 'sometimes|required|boolean',
|
||||
'visible' => 'sometimes|required|boolean',
|
||||
'locked' => 'sometimes|required|boolean',
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
throw new DisplayValidationException(json_encode($validator->errors()));
|
||||
}
|
||||
|
||||
$pack = Pack::withCount('servers')->findOrFail($id);
|
||||
|
||||
if ($pack->servers_count > 0 && (isset($data['option_id']) && (int) $data['option_id'] !== $pack->option_id)) {
|
||||
throw new DisplayException('You cannot modify the associated option if servers are attached to a pack.');
|
||||
}
|
||||
|
||||
$pack->fill([
|
||||
'name' => isset($data['name']) ? $data['name'] : $pack->name,
|
||||
'option_id' => isset($data['option_id']) ? $data['option_id'] : $pack->option_id,
|
||||
'version' => isset($data['version']) ? $data['version'] : $pack->version,
|
||||
'description' => (empty($data['description'])) ? null : $data['description'],
|
||||
'selectable' => isset($data['selectable']),
|
||||
'visible' => isset($data['visible']),
|
||||
'locked' => isset($data['locked']),
|
||||
])->save();
|
||||
|
||||
return $pack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a pack and files from the system.
|
||||
*
|
||||
* @param int $id
|
||||
* @return void
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
*/
|
||||
public function delete($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.');
|
||||
}
|
||||
|
||||
DB::transaction(function () use ($pack) {
|
||||
$pack->delete();
|
||||
Storage::deleteDirectory('packs/' . $pack->uuid);
|
||||
});
|
||||
}
|
||||
}
|
135
app/Repositories/Old/ServiceRepository.php
Normal file
135
app/Repositories/Old/ServiceRepository.php
Normal file
|
@ -0,0 +1,135 @@
|
|||
<?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 DB;
|
||||
use Validator;
|
||||
use Pterodactyl\Models\Service;
|
||||
use Pterodactyl\Exceptions\DisplayException;
|
||||
use Pterodactyl\Exceptions\DisplayValidationException;
|
||||
|
||||
class ServiceRepository
|
||||
{
|
||||
/**
|
||||
* Creates a new service on the system.
|
||||
*
|
||||
* @param array $data
|
||||
* @return \Pterodactyl\Models\Service
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayValidationException
|
||||
*/
|
||||
public function create(array $data)
|
||||
{
|
||||
$validator = Validator::make($data, [
|
||||
'name' => 'required|string|min:1|max:255',
|
||||
'description' => 'required|nullable|string',
|
||||
'folder' => 'required|unique:services,folder|regex:/^[\w.-]{1,50}$/',
|
||||
'startup' => 'required|nullable|string',
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
throw new DisplayValidationException(json_encode($validator->errors()));
|
||||
}
|
||||
|
||||
return DB::transaction(function () use ($data) {
|
||||
$service = new Service;
|
||||
$service->author = config('pterodactyl.service.author');
|
||||
$service->fill([
|
||||
'name' => $data['name'],
|
||||
'description' => (isset($data['description'])) ? $data['description'] : null,
|
||||
'folder' => $data['folder'],
|
||||
'startup' => (isset($data['startup'])) ? $data['startup'] : null,
|
||||
'index_file' => Service::defaultIndexFile(),
|
||||
])->save();
|
||||
|
||||
// It is possible for an event to return false or throw an exception
|
||||
// which won't necessarily be detected by this transaction.
|
||||
//
|
||||
// This check ensures the model was actually saved.
|
||||
if (! $service->exists) {
|
||||
throw new \Exception('Service model was created however the response appears to be invalid. Did an event fire wrongly?');
|
||||
}
|
||||
|
||||
return $service;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a service.
|
||||
*
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @return \Pterodactyl\Models\Service
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayValidationException
|
||||
*/
|
||||
public function update($id, array $data)
|
||||
{
|
||||
$service = Service::findOrFail($id);
|
||||
|
||||
$validator = Validator::make($data, [
|
||||
'name' => 'sometimes|required|string|min:1|max:255',
|
||||
'description' => 'sometimes|required|nullable|string',
|
||||
'folder' => 'sometimes|required|regex:/^[\w.-]{1,50}$/',
|
||||
'startup' => 'sometimes|required|nullable|string',
|
||||
'index_file' => 'sometimes|required|string',
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
throw new DisplayValidationException(json_encode($validator->errors()));
|
||||
}
|
||||
|
||||
return DB::transaction(function () use ($data, $service) {
|
||||
$service->fill($data)->save();
|
||||
|
||||
return $service;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a service and associated files and options.
|
||||
*
|
||||
* @param int $id
|
||||
* @return void
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
*/
|
||||
public function delete($id)
|
||||
{
|
||||
$service = Service::withCount('servers')->with('options')->findOrFail($id);
|
||||
|
||||
if ($service->servers_count > 0) {
|
||||
throw new DisplayException('You cannot delete a service that has servers associated with it.');
|
||||
}
|
||||
|
||||
DB::transaction(function () use ($service) {
|
||||
foreach ($service->options as $option) {
|
||||
(new OptionRepository)->delete($option->id);
|
||||
}
|
||||
|
||||
$service->delete();
|
||||
});
|
||||
}
|
||||
}
|
264
app/Repositories/Old/SubuserRepository.php
Normal file
264
app/Repositories/Old/SubuserRepository.php
Normal file
|
@ -0,0 +1,264 @@
|
|||
<?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 DB;
|
||||
use Validator;
|
||||
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;
|
||||
|
||||
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 = [
|
||||
's:get',
|
||||
's:console',
|
||||
];
|
||||
|
||||
/**
|
||||
* Creates a new subuser on the server.
|
||||
*
|
||||
* @param int $sid
|
||||
* @param array $data
|
||||
* @return \Pterodactyl\Models\Subuser
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\DisplayValidationException
|
||||
*/
|
||||
public function create($sid, array $data)
|
||||
{
|
||||
$server = Server::with('node')->findOrFail($sid);
|
||||
|
||||
$validator = Validator::make($data, [
|
||||
'permissions' => 'required|array',
|
||||
'email' => 'required|email',
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
throw new DisplayValidationException(json_encode($validator->errors()));
|
||||
}
|
||||
|
||||
DB::beginTransaction();
|
||||
|
||||
try {
|
||||
// Determine if this user exists or if we need to make them an account.
|
||||
$user = User::where('email', $data['email'])->first();
|
||||
if (! $user) {
|
||||
try {
|
||||
$repo = new oldUserRepository;
|
||||
$user = $repo->create([
|
||||
'email' => $data['email'],
|
||||
'username' => str_random(8),
|
||||
'name_first' => 'Unassigned',
|
||||
'name_last' => 'Name',
|
||||
'root_admin' => false,
|
||||
]);
|
||||
} catch (\Exception $ex) {
|
||||
throw $ex;
|
||||
}
|
||||
} elseif ($server->owner_id === $user->id) {
|
||||
throw new DisplayException('You cannot add the owner of a server as a subuser.');
|
||||
} 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 = Subuser::create([
|
||||
'user_id' => $user->id,
|
||||
'server_id' => $server->id,
|
||||
'daemonSecret' => (string) $uuid->generate('servers', 'uuid'),
|
||||
]);
|
||||
|
||||
$perms = Permission::listPermissions(true);
|
||||
$daemonPermissions = $this->coreDaemonPermissions;
|
||||
|
||||
foreach ($data['permissions'] as $permission) {
|
||||
if (array_key_exists($permission, $perms)) {
|
||||
// Build the daemon permissions array for sending.
|
||||
if (! is_null($perms[$permission])) {
|
||||
array_push($daemonPermissions, $perms[$permission]);
|
||||
}
|
||||
|
||||
Permission::create([
|
||||
'subuser_id' => $subuser->id,
|
||||
'permission' => $permission,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
// Contact Daemon
|
||||
// We contact even if they don't have any daemon permissions to overwrite
|
||||
// if they did have them previously.
|
||||
|
||||
$server->node->guzzleClient([
|
||||
'X-Access-Server' => $server->uuid,
|
||||
'X-Access-Token' => $server->node->daemonSecret,
|
||||
])->request('PATCH', '/server', [
|
||||
'json' => [
|
||||
'keys' => [
|
||||
$subuser->daemonSecret => $daemonPermissions,
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
DB::commit();
|
||||
|
||||
return $subuser;
|
||||
} 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) {
|
||||
DB::rollBack();
|
||||
throw $ex;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Revokes a users permissions on a server.
|
||||
*
|
||||
* @param int $id
|
||||
* @return void
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
*/
|
||||
public function delete($id)
|
||||
{
|
||||
$subuser = Subuser::with('server.node')->findOrFail($id);
|
||||
$server = $subuser->server;
|
||||
|
||||
DB::beginTransaction();
|
||||
|
||||
try {
|
||||
$server->node->guzzleClient([
|
||||
'X-Access-Server' => $server->uuid,
|
||||
'X-Access-Token' => $server->node->daemonSecret,
|
||||
])->request('PATCH', '/server', [
|
||||
'json' => [
|
||||
'keys' => [
|
||||
$subuser->daemonSecret => [],
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
foreach ($subuser->permissions as &$permission) {
|
||||
$permission->delete();
|
||||
}
|
||||
$subuser->delete();
|
||||
DB::commit();
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates permissions for a given subuser.
|
||||
*
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @return void
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\DisplayValidationException
|
||||
*/
|
||||
public function update($id, array $data)
|
||||
{
|
||||
$validator = Validator::make($data, [
|
||||
'permissions' => 'required|array',
|
||||
'user' => 'required|exists:users,id',
|
||||
'server' => 'required|exists:servers,id',
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
throw new DisplayValidationException(json_encode($validator->all()));
|
||||
}
|
||||
|
||||
$subuser = Subuser::with('server.node')->findOrFail($id);
|
||||
$server = $subuser->server;
|
||||
|
||||
DB::beginTransaction();
|
||||
|
||||
try {
|
||||
foreach ($subuser->permissions as &$permission) {
|
||||
$permission->delete();
|
||||
}
|
||||
|
||||
$perms = Permission::listPermissions(true);
|
||||
$daemonPermissions = $this->coreDaemonPermissions;
|
||||
|
||||
foreach ($data['permissions'] as $permission) {
|
||||
if (array_key_exists($permission, $perms)) {
|
||||
// Build the daemon permissions array for sending.
|
||||
if (! is_null($perms[$permission])) {
|
||||
array_push($daemonPermissions, $perms[$permission]);
|
||||
}
|
||||
Permission::create([
|
||||
'subuser_id' => $subuser->id,
|
||||
'permission' => $permission,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
// Contact Daemon
|
||||
// We contact even if they don't have any daemon permissions to overwrite
|
||||
// if they did have them previously.
|
||||
$server->node->guzzleClient([
|
||||
'X-Access-Server' => $server->uuid,
|
||||
'X-Access-Token' => $server->node->daemonSecret,
|
||||
])->request('PATCH', '/server', [
|
||||
'json' => [
|
||||
'keys' => [
|
||||
$subuser->daemonSecret => $daemonPermissions,
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
DB::commit();
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
}
|
163
app/Repositories/Old/TaskRepository.php
Normal file
163
app/Repositories/Old/TaskRepository.php
Normal file
|
@ -0,0 +1,163 @@
|
|||
<?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(),
|
||||
]);
|
||||
}
|
||||
}
|
171
app/Repositories/Old/VariableRepository.php
Normal file
171
app/Repositories/Old/VariableRepository.php
Normal file
|
@ -0,0 +1,171 @@
|
|||
<?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 DB;
|
||||
use Validator;
|
||||
use Pterodactyl\Models\ServiceOption;
|
||||
use Pterodactyl\Models\ServiceVariable;
|
||||
use Pterodactyl\Exceptions\DisplayException;
|
||||
use Pterodactyl\Exceptions\DisplayValidationException;
|
||||
|
||||
class VariableRepository
|
||||
{
|
||||
/**
|
||||
* Create a new service variable.
|
||||
*
|
||||
* @param int $option
|
||||
* @param array $data
|
||||
* @return \Pterodactyl\Models\ServiceVariable
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\DisplayValidationException
|
||||
*/
|
||||
public function create($option, array $data)
|
||||
{
|
||||
$option = ServiceOption::select('id')->findOrFail($option);
|
||||
|
||||
$validator = Validator::make($data, [
|
||||
'name' => 'required|string|min:1|max:255',
|
||||
'description' => 'sometimes|nullable|string',
|
||||
'env_variable' => 'required|regex:/^[\w]{1,255}$/',
|
||||
'default_value' => 'string',
|
||||
'options' => 'sometimes|required|array',
|
||||
'rules' => 'bail|required|string',
|
||||
]);
|
||||
|
||||
// Ensure the default value is allowed by the rules provided.
|
||||
$validator->sometimes('default_value', $data['rules'] ?? null, function ($input) {
|
||||
return $input->default_value;
|
||||
});
|
||||
|
||||
if ($validator->fails()) {
|
||||
throw new DisplayValidationException(json_encode($validator->errors()));
|
||||
}
|
||||
|
||||
if (in_array($data['env_variable'], ServiceVariable::reservedNames())) {
|
||||
throw new DisplayException('The environment variable name provided is a reserved keyword for the daemon.');
|
||||
}
|
||||
|
||||
$search = ServiceVariable::where('env_variable', $data['env_variable'])->where('option_id', $option->id);
|
||||
if ($search->first()) {
|
||||
throw new DisplayException('The envionment variable name assigned to this variable must be unique for this service option.');
|
||||
}
|
||||
|
||||
if (! isset($data['options']) || ! is_array($data['options'])) {
|
||||
$data['options'] = [];
|
||||
}
|
||||
|
||||
$data['option_id'] = $option->id;
|
||||
$data['user_viewable'] = (in_array('user_viewable', $data['options']));
|
||||
$data['user_editable'] = (in_array('user_editable', $data['options']));
|
||||
|
||||
// Remove field that isn't used.
|
||||
unset($data['options']);
|
||||
|
||||
return ServiceVariable::create($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a specified option variable as well as all server
|
||||
* variables currently assigned.
|
||||
*
|
||||
* @param int $id
|
||||
* @return void
|
||||
*/
|
||||
public function delete($id)
|
||||
{
|
||||
$variable = ServiceVariable::with('serverVariable')->findOrFail($id);
|
||||
|
||||
DB::transaction(function () use ($variable) {
|
||||
foreach ($variable->serverVariable as $v) {
|
||||
$v->delete();
|
||||
}
|
||||
|
||||
$variable->delete();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a given service variable.
|
||||
*
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @return \Pterodactyl\Models\ServiceVariable
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\DisplayValidationException
|
||||
*/
|
||||
public function update($id, array $data)
|
||||
{
|
||||
$variable = ServiceVariable::findOrFail($id);
|
||||
|
||||
$validator = Validator::make($data, [
|
||||
'name' => 'sometimes|required|string|min:1|max:255',
|
||||
'description' => 'sometimes|nullable|string',
|
||||
'env_variable' => 'sometimes|required|regex:/^[\w]{1,255}$/',
|
||||
'default_value' => 'string',
|
||||
'options' => 'sometimes|required|array',
|
||||
'rules' => 'bail|sometimes|required|string|min:1',
|
||||
]);
|
||||
|
||||
// Ensure the default value is allowed by the rules provided.
|
||||
$rules = (isset($data['rules'])) ? $data['rules'] : $variable->rules;
|
||||
$validator->sometimes('default_value', $rules, function ($input) {
|
||||
return $input->default_value;
|
||||
});
|
||||
|
||||
if ($validator->fails()) {
|
||||
throw new DisplayValidationException(json_encode($validator->errors()));
|
||||
}
|
||||
|
||||
if (isset($data['env_variable'])) {
|
||||
if (in_array($data['env_variable'], ServiceVariable::reservedNames())) {
|
||||
throw new DisplayException('The environment variable name provided is a reserved keyword for the daemon.');
|
||||
}
|
||||
|
||||
$search = ServiceVariable::where('env_variable', $data['env_variable'])
|
||||
->where('option_id', $variable->option_id)
|
||||
->where('id', '!=', $variable->id);
|
||||
if ($search->first()) {
|
||||
throw new DisplayException('The envionment variable name assigned to this variable must be unique for this service option.');
|
||||
}
|
||||
}
|
||||
|
||||
if (! isset($data['options']) || ! is_array($data['options'])) {
|
||||
$data['options'] = [];
|
||||
}
|
||||
|
||||
$data['user_viewable'] = (in_array('user_viewable', $data['options']));
|
||||
$data['user_editable'] = (in_array('user_editable', $data['options']));
|
||||
|
||||
// Remove field that isn't used.
|
||||
unset($data['options']);
|
||||
|
||||
$variable->fill($data)->save();
|
||||
|
||||
return $variable;
|
||||
}
|
||||
}
|
1035
app/Repositories/Old/old_ServerRepository.php
Normal file
1035
app/Repositories/Old/old_ServerRepository.php
Normal file
File diff suppressed because it is too large
Load diff
180
app/Repositories/Old/old_UserRepository.php
Normal file
180
app/Repositories/Old/old_UserRepository.php
Normal file
|
@ -0,0 +1,180 @@
|
|||
<?php
|
||||
/**
|
||||
* Pterodactyl - Panel
|
||||
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>
|
||||
* Some Modifications (c) 2015 Dylan Seidt <dylan.seidt@gmail.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 DB;
|
||||
use Auth;
|
||||
use Hash;
|
||||
use Settings;
|
||||
use Validator;
|
||||
use Pterodactyl\Models;
|
||||
use Pterodactyl\Services\UuidService;
|
||||
use Pterodactyl\Exceptions\DisplayException;
|
||||
use Pterodactyl\Exceptions\DisplayValidationException;
|
||||
|
||||
class old_UserRepository
|
||||
{
|
||||
/**
|
||||
* Creates a user on the panel. Returns the created user's ID.
|
||||
*
|
||||
* @param array $data
|
||||
* @return \Pterodactyl\Models\User
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayValidationException
|
||||
*/
|
||||
public function create(array $data)
|
||||
{
|
||||
$validator = Validator::make($data, [
|
||||
'email' => 'required|email|unique:users,email',
|
||||
'username' => 'required|string|between:1,255|unique:users,username|' . Models\User::USERNAME_RULES,
|
||||
'name_first' => 'required|string|between:1,255',
|
||||
'name_last' => 'required|string|between:1,255',
|
||||
'password' => 'sometimes|nullable|' . Models\User::PASSWORD_RULES,
|
||||
'root_admin' => 'required|boolean',
|
||||
'custom_id' => 'sometimes|nullable|unique:users,id',
|
||||
]);
|
||||
|
||||
// Run validator, throw catchable and displayable exception if it fails.
|
||||
// Exception includes a JSON result of failed validation rules.
|
||||
if ($validator->fails()) {
|
||||
throw new DisplayValidationException(json_encode($validator->errors()));
|
||||
}
|
||||
|
||||
DB::beginTransaction();
|
||||
|
||||
try {
|
||||
$user = new Models\User;
|
||||
$uuid = new UuidService;
|
||||
|
||||
// Support for API Services
|
||||
if (isset($data['custom_id']) && ! is_null($data['custom_id'])) {
|
||||
$user->id = $token;
|
||||
}
|
||||
|
||||
// UUIDs are not mass-fillable.
|
||||
$user->uuid = $uuid->generate('users', 'uuid');
|
||||
|
||||
$user->fill([
|
||||
'email' => $data['email'],
|
||||
'username' => $data['username'],
|
||||
'name_first' => $data['name_first'],
|
||||
'name_last' => $data['name_last'],
|
||||
'password' => (empty($data['password'])) ? 'unset' : Hash::make($data['password']),
|
||||
'root_admin' => $data['root_admin'],
|
||||
'language' => Settings::get('default_language', 'en'),
|
||||
]);
|
||||
$user->save();
|
||||
|
||||
DB::commit();
|
||||
|
||||
return $user;
|
||||
} catch (\Exception $ex) {
|
||||
DB::rollBack();
|
||||
throw $ex;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a user on the panel.
|
||||
*
|
||||
* @param int $id
|
||||
* @param array $data
|
||||
* @return \Pterodactyl\Models\User
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayValidationException
|
||||
*/
|
||||
public function update($id, array $data)
|
||||
{
|
||||
$user = Models\User::findOrFail($id);
|
||||
|
||||
$validator = Validator::make($data, [
|
||||
'email' => 'sometimes|required|email|unique:users,email,' . $id,
|
||||
'username' => 'sometimes|required|string|between:1,255|unique:users,username,' . $user->id . '|' . Models\User::USERNAME_RULES,
|
||||
'name_first' => 'sometimes|required|string|between:1,255',
|
||||
'name_last' => 'sometimes|required|string|between:1,255',
|
||||
'password' => 'sometimes|nullable|' . Models\User::PASSWORD_RULES,
|
||||
'root_admin' => 'sometimes|required|boolean',
|
||||
'language' => 'sometimes|required|string|min:1|max:5',
|
||||
'use_totp' => 'sometimes|required|boolean',
|
||||
'totp_secret' => 'sometimes|required|size:16',
|
||||
]);
|
||||
|
||||
// Run validator, throw catchable and displayable exception if it fails.
|
||||
// Exception includes a JSON result of failed validation rules.
|
||||
if ($validator->fails()) {
|
||||
throw new DisplayValidationException(json_encode($validator->errors()));
|
||||
}
|
||||
|
||||
// The password and root_admin fields are not mass assignable.
|
||||
if (! empty($data['password'])) {
|
||||
$data['password'] = Hash::make($data['password']);
|
||||
} else {
|
||||
unset($data['password']);
|
||||
}
|
||||
|
||||
$user->fill($data)->save();
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a user on the panel.
|
||||
*
|
||||
* @param int $id
|
||||
* @return void
|
||||
* @todo Move user self-deletion checking to the controller, rather than the repository.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
*/
|
||||
public function delete($id)
|
||||
{
|
||||
if (Models\Server::where('owner_id', $id)->count() > 0) {
|
||||
throw new DisplayException('Cannot delete a user with active servers attached to thier account.');
|
||||
}
|
||||
|
||||
if (! is_null(Auth::user()) && (int) Auth::user()->id === (int) $id) {
|
||||
throw new DisplayException('Cannot delete your own account.');
|
||||
}
|
||||
|
||||
DB::beginTransaction();
|
||||
|
||||
try {
|
||||
foreach (Models\Subuser::with('permissions')->where('user_id', $id)->get() as &$subuser) {
|
||||
foreach ($subuser->permissions as &$permission) {
|
||||
$permission->delete();
|
||||
}
|
||||
|
||||
$subuser->delete();
|
||||
}
|
||||
|
||||
Models\User::destroy($id);
|
||||
DB::commit();
|
||||
} catch (\Exception $ex) {
|
||||
DB::rollBack();
|
||||
throw $ex;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue