Model fixing, moving things around to improve code.

Adds unique UUID generator, moves functions into repositories for
adding servers and users, cleans up code, adding more comments.
This commit is contained in:
Dane Everitt 2015-12-13 22:22:16 -05:00
parent 01eaeaf178
commit 22b0bbf6ce
8 changed files with 333 additions and 250 deletions

View file

@ -3,16 +3,8 @@
namespace Pterodactyl\Models;
use Auth;
use DB;
use Debugbar;
use Validator;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Exceptions\AccountNotFoundException;
use Pterodactyl\Exceptions\DisplayValidationException;
use Pterodactyl\Models;
use Pterodactyl\Models\Subuser;
use Illuminate\Database\Eloquent\Model;
class Server extends Model
@ -50,18 +42,6 @@ class Server extends Model
self::$user = Auth::user();
}
protected static function generateSFTPUsername($name)
{
$name = preg_replace('/\s+/', '', $name);
if (strlen($name) > 6) {
return strtolower('ptdl-' . substr($name, 0, 6) . '_' . str_random(5));
}
return strtolower('ptdl-' . $name . '_' . str_random((11 - strlen($name))));
}
/**
* Determine if we need to change the server's daemonSecret value to
* match that of the user if they are a subuser.
@ -76,7 +56,7 @@ class Server extends Model
return $server->daemonSecret;
}
$subuser = Models\Subuser::where('server_id', $server->id)->where('user_id', self::$user->id)->first();
$subuser = Subuser::where('server_id', $server->id)->where('user_id', self::$user->id)->first();
if (is_null($subuser)) {
return null;
@ -101,7 +81,7 @@ class Server extends Model
->where('active', 1);
if (self::$user->root_admin !== 1) {
$query->whereIn('servers.id', Models\Subuser::accessServers());
$query->whereIn('servers.id', Subuser::accessServers());
}
return $query->get();
@ -124,7 +104,7 @@ class Server extends Model
$query = self::where('uuidShort', $uuid)->where('active', 1);
if (self::$user->root_admin !== 1) {
$query->whereIn('servers.id', Models\Subuser::accessServers());
$query->whereIn('servers.id', Subuser::accessServers());
}
$result = $query->first();
@ -158,84 +138,4 @@ class Server extends Model
}
/**
* 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.
*/
public static function addServer(array $data)
{
// Validate Fields
$validator = Validator::make($data, [
'owner' => 'required|email|exists:users,email',
'node' => 'required|numeric|min:1|exists:nodes,id',
'name' => 'required|regex:([\w -]{4,35})',
'memory' => 'required|numeric|min:1',
'disk' => 'required|numeric|min:1',
'cpu' => 'required|numeric|min:0',
'io' => 'required|numeric|min:10|max:1000',
'ip' => 'required|ip',
'port' => 'required|numeric|min:1|max:65535',
'service' => 'required|numeric|min:1|exists:services,id',
'option' => 'required|numeric|min:1|exists:service_options,id',
'custom_image_name' => 'required_if:use_custom_image,on',
]);
// 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()->all()));
}
// Get the User ID; user exists since we passed the 'exists:users,email' part of the validation
$user = Models\User::select('id')->where('email', $data['owner'])->first();
// Verify IP & Port are a.) free and b.) assigned to the node.
// We know the node exists because of 'exists:nodes,id' in the validation
$node = Models\Node::find($data['node']);
$allocation = Models\Allocation::where('ip', $data['ip'])->where('port', $data['port'])->where('node', $data['node'])->whereNull('assigned_to')->first();
// Something failed in the query, either that combo doesn't exist, or it is in use.
if (!$allocation) {
throw new DisplayException('The selected IP/Port combination (' . $data['ip'] . ':' . $data['port'] . ') is either already in use, or unavaliable for this node.');
}
// Validate those Service Option Variables
// We know the service and option exists because of the validation.
// We need to verify that the option exists for the service, and then check for
// any required variable fields. (fields are labeled env_<env_variable>)
$option = Models\ServiceOptions::where('id', $data['option'])->where('parent_service', $data['service'])->first();
if (!$option) {
throw new DisplayException('The requested service option does not exist for the specified service.');
}
// Check those Variables
$variables = Models\ServiceVariables::where('option_id', $data['option'])->get();
if ($variables) {
foreach($variables as $variable) {
// Is the variable required?
if (!$data['env_' . $variable->env_variable]) {
if ($variable->required === 1) {
throw new DisplayException('A required service option variable field (env_' . $variable->env_variable . ') was missing from the request.');
}
$data['env_' . $variable->env_variable] = $variable->default_value;
continue;
}
// Check aganist Regex Pattern
if (!is_null($variable->regex) && !preg_match($variable->regex, $data['env_' . $variable->env_variable])) {
throw new DisplayException('Failed to validate service option variable field (env_' . $variable->env_variable . ') aganist regex (' . $variable->regex . ').');
}
continue;
}
}
return self::generateSFTPUsername($data['name']);
}
}

View file

@ -2,6 +2,7 @@
namespace Pterodactyl\Models;
use Hash;
use Google2FA;
use Pterodactyl\Exceptions\AccountNotFoundException;
use Pterodactyl\Exceptions\DisplayException;
@ -47,51 +48,21 @@ class User extends Model implements AuthenticatableContract,
return $this->hasMany(Permission::class);
}
/**
* Sets the TOTP secret for an account.
*
* @param int $id Account ID for which we want to generate a TOTP secret
* @return string
*/
public static function setTotpSecret($id)
{
$totpSecretKey = Google2FA::generateSecretKey();
$user = User::find($id);
if (!$user) {
throw new AccountNotFoundException('An account with that ID (' . $id . ') does not exist in the system.');
}
$user->totp_secret = $totpSecretKey;
$user->save();
return $totpSecretKey;
}
/**
* Enables or disables TOTP on an account if the token is valid.
*
* @param int $id Account ID for which we want to generate a TOTP secret
* @param int $token The token that we want to verify.
* @return boolean
*/
public static function toggleTotp($id, $token)
public function toggleTotp($token)
{
$user = User::find($id);
if (!$user) {
throw new AccountNotFoundException('An account with that ID (' . $id . ') does not exist in the system.');
}
if (!Google2FA::verifyKey($user->totp_secret, $token)) {
if (!Google2FA::verifyKey($this->totp_secret, $token)) {
return false;
}
$user->use_totp = ($user->use_totp === 1) ? 0 : 1;
$user->save();
$this->use_totp = !$this->use_totp;
$this->save();
return true;
@ -104,51 +75,19 @@ class User extends Model implements AuthenticatableContract,
* - at least one lowercase character
* - at least one number
*
* @param int $id The ID of the account to update the password on.
* @param string $password The raw password to set the account password to.
* @param string $regex The regex to use when validating the password. Defaults to '((?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,})'.
* @return void
*/
public static function setPassword($id, $password, $regex = '((?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,})')
public function setPassword($password, $regex = '((?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,})')
{
$user = User::find($id);
if (!$user) {
throw new AccountNotFoundException('An account with that ID (' . $id . ') does not exist in the system.');
}
if (!preg_match($regex, $password)) {
throw new DisplayException('The password passed did not meet the minimum password requirements.');
}
$user->password = password_hash($password, PASSWORD_BCRYPT);
$user->save();
return;
}
/**
* Updates the email address for an account.
*
* @param int $id
* @param string $email
* @return void
*/
public static function setEmail($id, $email)
{
$user = User::find($id);
if (!$user) {
throw new AccountNotFoundException('An account with that ID (' . $id . ') does not exist in the system.');
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
throw new DisplayException('The email provided (' . $email . ') was not valid.');
}
$user->email = $email;
$user->save();
$this->password = Hash::make($password);
$this->save();
return;