Merge branch 'develop' into fix/trusted-proxies

sorry
This commit is contained in:
Jakob Schrettenbrunner 2017-02-01 20:35:10 +01:00
commit 24650b67be
341 changed files with 13312 additions and 7936 deletions

8
.babelrc Normal file
View file

@ -0,0 +1,8 @@
{
"presets": ["es2015"],
"compact": true,
"minified": true,
"only": "public/themes/pterodactyl/js/frontend/files/src/*.js",
"sourceMaps": "inline",
"comments": false
}

12
.editorconfig Normal file
View file

@ -0,0 +1,12 @@
root = true
[*]
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 4
charset = utf-8
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false

View file

@ -1,12 +1,11 @@
APP_ENV=production
APP_DEBUG=false
APP_KEY=SomeRandomString3232RandomString
APP_THEME=default
APP_THEME=pterodactyl
APP_TIMEZONE=UTC
APP_CLEAR_TASKLOG=720
APP_DELETE_MINUTES=10
CONSOLE_PUSH_FREQ=250
CONSOLE_PUSH_COUNT=10
APP_URL=http://yoursite.com/
DB_HOST=localhost
DB_PORT=3306

View file

@ -1,61 +1,6 @@
<!-- The checkboxes below can be clicked once you submit this report if you'd like -->
<!-- You can also use "- [x]" to mark it as checked. -->
## Product
Please check the corresponding boxes below for which products this is about.
Please describe your issue in full below. Include what products are affected, as well as what version(s) you are running. Please also include information about your system, such as `uname -a` and `php -v` and `docker info` if applicable.
- [ ] Panel
- [ ] Daemon
- [ ] Dockerfile(s) [Please list if so: __ ]
If you're just making a suggestion, be descriptive, and link to any issues that might be releated as well.
## Type
- [ ] Bug or Issue
- [ ] Feature Request
- [ ] Enhancement
- [ ] Other
<!-- You only need to fill out the information below if this is a bug report. -->
<!-- Please delete this line and everything below if this is NOT a bug report. -->
## What Happens
<!-- Please include a description of what is happening when you encounter this bug. -->
## How to Reproduce
<!-- Please provide us a list of step for how to reproduce this issue. -->
1. Step 1
2. Step 2
3. etc.
## Error Logs
<!-- Please include a paste output of the errors if they are logged. They can be found in: -->
<!-- Panel: /var/www/pterodactyl/html/storage/logs/ Daemon: /srv/daemon/logs -->
<!-- You can also paste them on https://gist.github.com and include their links below. -->
```
error logs
```
## System Information
#### Output of `uname -a`:
```
paste here
```
#### Output of `php -v` (if Panel):
```
paste here
```
#### Output of `node -v` (if Daemon):
```
paste here
```
#### Output of `docker info` and `docker -v` (if Daemon or Dockerfiles):
```
paste here
```
You can delete from this line up.
---------------------

3
.gitignore vendored
View file

@ -9,5 +9,4 @@ Homestead.yaml
Vagrantfile
Vagrantfile
node_modules
.babelrc
node_modules

View file

@ -3,6 +3,100 @@ This file is a running track of new features and fixes to each version of the pa
This project follows [Semantic Versioning](http://semver.org) guidelines.
## v0.6.0-pre.1
### Added
* Remote routes for daemon to contact in order to allow Daemon to retrieve updated service configuration files on boot. Centralizes services to the panel rather than to each daemon.
* Basic service pack implementation to allow assignment of modpacks or software to a server to pre-install applications and allow users to update.
* Users can now have a username as well as client name assigned to their account.
* Ability to create a node through the CLI using `pterodactyl:node` as well as locations via `pterodactyl:location`.
* New theme (AdminLTE) for front-end with tweaks to backend files to work properly with it.
### Fixed
* Bug causing error logs to be spammed if someone timed out on an ajax based page.
* Fixes edge case where specific server names could cause daemon errors due to an invalid SFTP username being created by the panel.
### Changed
* Admin API and base routes for user management now define the fields that should be passed to repositories rather than passing all fields.
* User model now defines mass assignment fields using `$fillable` rather than `$guarded`.
### Deprecated
## v0.5.6 (Bodacious Boreopterus)
### Added
* Added the following languages: Estonian `et`, Dutch `nl`, Norwegian `nb` (partial), Romanian `ro`, and Russian `ru`. Interested in helping us translate the panel into more languages, or improving existing translations? Contact us on Discord and let us know.
* Added missing `strings.password` to language file for English.
* Allow listing of users from the API by passing either the user ID or their email.
### Fixed
* Fixes bug where assigning a variable a default value (or valid value) of `0` would cause the panel to reject the value thinking it did not exist.
* Addresses potential for crash by limiting total ports that can be assigned per-range to 2000.
* Fixes server names requiring at minimum 4 characters. Name can now be 1 to 200 characters long. :pencil2:
* Fixes bug that would allow adding the owner of a server as a subuser for that same server.
* Fixes bug that would allow creating multiple subusers with the same email address.
* Fixes bug where Sponge servers were improperly tagged as a spigot server in the daemon causing issues when booting or modifying configuration files.
* Use transpiled ES6 -> ES5 filemanager code in browsers.
* Fixes service option name displaying the name of a nwly added variable after the variable is added and until the page is refreshed. (see #208)
### Changed
* Filemanager and EULA checking javascript is now written in pure ES6 code rather than as a blade-syntax template. This allows the use of babel to transpile into ES5 as a minified version.
## v0.5.5 (Bodacious Boreopterus)
### Added
* New API route to return allocations given a server ID. This adds support for a community-driven WHMCS module :rocket: available [here](https://github.com/hammerdawn/Pterodactyl-WHMCS).
### Fixed
* Fixes subuser display when trying to edit an existing subuser.
## v0.5.4 (Bodacious Boreopterus)
### Added
* Changing node configuration values now automatically makes a call to the daemon and updates the configuration there. Changing daemon tokens now does not require any intervention, and takes effect immediately. SSL & Port configurations will still require a daemon reboot.
* New button in file manager that triggers the right click menu to enable support on mobile devices and those who cannot right click (blessed be them).
* Support for filtering users when listing all users on the system.
* Container ID and User ID on the daemon are now shown when viewing a server in the panel.
### Changed
* File uploads now account for a maximum file size that is assigned for the daemon, and gives cleaner errors when that limit is reached.
* File upload limit can now be controlled from the panel.
* Updates regex and default values for some Minecraft services to reflect current technology.
### Fixed
* Fixes potential for generated password to not meet own validation requirements.
* Fixes some regex checking issues with newer versions of Minecraft.
## v0.5.3 (Bodacious Boreopterus)
### Fixed
* Fixed an error that occurred when viewing a node listing when no nodes were created yet due to a mis-declared variable. Also fixes a bug that would have all nodes trying to connect to the daemon using the same secret token on the node listing, causing only the last node to display properly.
* Fixes a bug that displayed the panel version rather than the daemon version when viewing a node.
* Fixes a multiplicator being applied to an overallocation field rather than a storage space field when adding a node.
### Changed
* Added a few new configuration variables for nodes to the default config, as well as a variable that will be used in future versions of the daemon.
## v0.5.2 (Bodacious Boreopterus)
### Fixed
* Time axis on server graphs is corrected to show the minutes rather than the current month.
* Node deletion now works correctly and deletes allocations as well.
* Fixes a bug that would leave orphaned databases on the system if there was an error during creation.
* Fixes an issue that could occur if a UUID contained `#e#` formatting within it when it comes to creating databases.
* Fixed node status display to account for updated daemon security changes.
* Fixes default language being selected as German (defaults to English now).
* Fixes bug preventing the deletion of database servers.
### Changed
* Using `node:<name>` when filtering servers now properly filters the servers by node name, rather than looking for the node ID.
* Using `owner:<email>` when filtering servers now properly filters by the owner's email rather than ID.
* Added some quick help buttons to the admin index page for getting support or checking the documentation.
* Panel now displays `Pterodactyl Panel` as the company name if one is not set.
### Added
* Added basic information about the daemon when viewing a node, including the host OS and version, CPU count, and the daemon version.
* Added version checking for the daemon and panel that alerts admins when daemons or the panel is out of date.
* Added multiplicator support to certain memory and disk fields that allow users to enter `10g` and have it converted to MB automatically.
## v0.5.1 (Bodacious Boreopterus)
### Fixed
* Fixes a bug that allowed a user to bypass 2FA authentication if using the correct username and password for an account.
## v0.5.0 (Bodacious Boreopterus)
After nearly a month in the works, version `v0.5.0` is finally here! 🎉

View file

@ -1,7 +1,7 @@
# The MIT License (MIT)
```
Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
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

View file

@ -6,7 +6,7 @@ Support for using Pterodactyl can be found on our [wiki](https://github.com/Pter
## License
```
Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
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
@ -33,6 +33,8 @@ A huge thanks to [PhraseApp](https://phraseapp.com) who provide us the software
Ace Editor - [license](https://github.com/ajaxorg/ace/blob/master/LICENSE) - [homepage](https://ace.c9.io)
AdminLTE - [license](https://github.com/almasaeed2010/AdminLTE/blob/master/LICENSE) - [homepage](https://almsaeedstudio.com)
Animate.css - [license](https://github.com/daneden/animate.css/blob/master/LICENSE) - [homepage](http://daneden.github.io/animate.css/)
Async.js - [license](https://github.com/caolan/async/blob/master/LICENSE) - [homepage](https://github.com/caolan/async/)
@ -57,8 +59,12 @@ jQuery Terminal - [license](https://github.com/jcubic/jquery.terminal/blob/maste
Lodash - [license](https://github.com/lodash/lodash/blob/master/LICENSE) - [homepage](https://lodash.com/)
Select2 - [license](https://github.com/select2/select2/blob/master/LICENSE.md) - [homepage](https://select2.github.io)
Socket.io - [license](https://github.com/socketio/socket.io/blob/master/LICENSE) - [homepage](http://socket.io)
Socket.io File Upload - [license](https://github.com/vote539/socketio-file-upload/blob/master/server.js#L1-L27) - [homepage](https://github.com/vote539/socketio-file-upload)
SweetAlert - [license](https://github.com/t4t5/sweetalert/blob/master/LICENSE) - [homepage](http://t4t5.github.io/sweetalert/)
Typeahead — [license](https://github.com/bassjobsen/Bootstrap-3-Typeahead/blob/master/bootstrap3-typeahead.js) — [homepage](https://github.com/bassjobsen/Bootstrap-3-Typeahead)

View file

@ -0,0 +1,75 @@
<?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\Console\Commands;
use Illuminate\Console\Command;
use Pterodactyl\Repositories\LocationRepository;
class AddLocation extends Command
{
protected $data = [];
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'pterodactyl:location
{--short= : The shortcode name of this location (ex. us1).}
{--long= : A longer description of this location.}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Creates a new location on the system via the CLI.';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$this->data['short'] = (is_null($this->option('short'))) ? $this->ask('Location Short Code') : $this->option('short');
$this->data['long'] = (is_null($this->option('long'))) ? $this->ask('Location Description') : $this->option('long');
$repo = new LocationRepository;
$id = $repo->create($this->data);
$this->info('Location ' . $this->data['short'] . ' created with ID: ' . $id);
}
}

View file

@ -0,0 +1,112 @@
<?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\Console\Commands;
use Illuminate\Console\Command;
use Pterodactyl\Models\Location;
use Pterodactyl\Repositories\NodeRepository;
class AddNode extends Command
{
protected $data = [];
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'pterodactyl:node
{--name= : Name of the node.}
{--location= : The shortcode of the location to add this node to.}
{--fqdn= : The fully-qualified domain for the node.}
{--ssl= : Should the daemon use SSL for connections (T/F).}
{--memory= : The total memory available on this node for servers.}
{--disk= : The total disk space available on this node for servers.}
{--daemonBase= : The directory in which server files will be stored.}
{--daemonListen= : The port the daemon will listen on for connections.}
{--daemonSFTP= : The port to be used for SFTP conncetions to the daemon.}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Adds a new node to the system via the CLI.';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$locations = Location::all(['id', 'short', 'long']);
$this->data['name'] = (is_null($this->option('name'))) ? $this->ask('Node Name') : $this->option('name');
if (is_null($this->option('location'))) {
$this->table(['ID', 'Short Code', 'Description'], $locations->toArray());
$selectedLocation = $this->anticipate('Node Location (Short Name)', $locations->pluck('short')->toArray());
} else {
$selectedLocation = $this->option('location');
}
$this->data['location'] = $locations->where('short', $selectedLocation)->first()->id;
if (is_null($this->option('fqdn'))) {
$this->line('Please enter domain name (e.g node.example.com) to be used for connecting to the daemon. An IP address may only be used if you are not using SSL for this node.');
$this->data['fqdn'] = $this->ask('Fully Qualified Domain Name');
} else {
$this->data['fqdn'] = $this->option('fqdn');
}
$useSSL = (is_null($this->option('ssl'))) ? $this->confirm('Use SSL', true) : $this->option('ssl');
$this->data['scheme'] = ($useSSL) ? 'https' : 'http';
$this->data['memory'] = (is_null($this->option('memory'))) ? $this->ask('Total Memory (in MB)') : $this->option('memory');
$this->data['memory_overallocate'] = 0;
$this->data['disk'] = (is_null($this->option('disk'))) ? $this->ask('Total Disk Space (in MB)') : $this->option('disk');
$this->data['disk_overallocate'] = 0;
$this->data['public'] = 1;
$this->data['daemonBase'] = (is_null($this->option('daemonBase'))) ? $this->ask('Daemon Server File Location', '/srv/daemon-data') : $this->option('daemonBase');
$this->data['daemonListen'] = (is_null($this->option('daemonListen'))) ? $this->ask('Daemon Listening Port', 8080) : $this->option('daemonListen');
$this->data['daemonSFTP'] = (is_null($this->option('daemonSFTP'))) ? $this->ask('Daemon SFTP Port', 2022) : $this->option('daemonSFTP');
$repo = new NodeRepository;
$id = $repo->create($this->data);
$this->info('Node created with ID: ' . $id);
}
}

View file

@ -0,0 +1,74 @@
<?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\Console\Commands;
use Carbon;
use Storage;
use Illuminate\Console\Command;
class CleanServiceBackup extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'pterodactyl:cleanservices';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Cleans .bak files assocaited with service backups whene editing files through the panel.';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$files = Storage::files('services/.bak');
foreach ($files as $file) {
$lastModified = Carbon::createFromTimestamp(Storage::lastModified($file));
if ($lastModified->diffInMinutes(Carbon::now()) > 5) {
$this->info('Deleting ' . $file);
Storage::delete($file);
}
}
}
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,10 +21,10 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Console\Commands;
use DB;
use Illuminate\Console\Command;
class ClearServices extends Command
@ -60,8 +60,7 @@ class ClearServices extends Command
*/
public function handle()
{
if (!$this->confirm('This is a destructive operation, are you sure you wish to continue?')) {
if (! $this->confirm('This is a destructive operation, are you sure you wish to continue?')) {
$this->error('Canceling.');
exit();
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,19 +21,16 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Console\Commands;
use DB;
use Carbon;
use Pterodactyl\Models;
use Illuminate\Console\Command;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Pterodactyl\Jobs\SendScheduledTask;
class ClearTasks extends Command
{
use DispatchesJobs;
/**

View file

@ -28,6 +28,6 @@ class Inspire extends Command
*/
public function handle()
{
$this->comment(PHP_EOL.Inspiring::quote().PHP_EOL);
$this->comment(PHP_EOL . Inspiring::quote() . PHP_EOL);
}
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,11 +21,10 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Console\Commands;
use Hash;
use Illuminate\Console\Command;
use Pterodactyl\Repositories\UserRepository;
class MakeUser extends Command
@ -36,6 +35,9 @@ class MakeUser extends Command
* @var string
*/
protected $signature = 'pterodactyl:user
{--firstname= : First name to use for this account.}
{--lastname= : Last name to use for this account.}
{--username= : Username to use for this account.}
{--email= : Email address to use for this account.}
{--password= : Password to assign to the user.}
{--admin= : Boolean flag for if user should be an admin.}';
@ -64,19 +66,23 @@ class MakeUser extends Command
*/
public function handle()
{
$email = is_null($this->option('email')) ? $this->ask('Email') : $this->option('email');
$password = is_null($this->option('password')) ? $this->secret('Password') : $this->option('password');
$data['name_first'] = is_null($this->option('firstname')) ? $this->ask('First Name') : $this->option('firstname');
$data['name_last'] = is_null($this->option('lastname')) ? $this->ask('Last Name') : $this->option('lastname');
$data['username'] = is_null($this->option('username')) ? $this->ask('Username') : $this->option('username');
$data['email'] = is_null($this->option('email')) ? $this->ask('Email') : $this->option('email');
$data['password'] = is_null($this->option('password')) ? $this->secret('Password') : $this->option('password');
$password_confirmation = is_null($this->option('password')) ? $this->secret('Confirm Password') : $this->option('password');
if ($password !== $password_confirmation) {
if ($data['password'] !== $password_confirmation) {
return $this->error('The passwords provided did not match!');
}
$admin = is_null($this->option('admin')) ? $this->confirm('Is this user a root administrator?') : $this->option('admin');
$data['root_admin'] = is_null($this->option('admin')) ? $this->confirm('Is this user a root administrator?') : $this->option('admin');
try {
$user = new UserRepository;
$user->create($email, $password, $admin);
$user->create($data);
return $this->info('User successfully created.');
} catch (\Exception $ex) {
return $this->error($ex->getMessage());

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,19 +21,17 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Console\Commands;
use DB;
use Carbon;
use Pterodactyl\Models;
use Illuminate\Console\Command;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Pterodactyl\Jobs\SendScheduledTask;
use Illuminate\Foundation\Bus\DispatchesJobs;
class RunTasks extends Command
{
use DispatchesJobs;
/**

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,8 +21,10 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Console\Commands;
use Version;
use Illuminate\Console\Command;
class ShowVersion extends Command
@ -58,6 +60,6 @@ class ShowVersion extends Command
*/
public function handle()
{
$this->info('You are running Pterodactyl Panel ' . config('app.version'));
$this->info('You are running Pterodactyl Panel v' . Version::getCurrentPanel() . ' (' . ((Version::isLatestPanel()) ? 'Up to Date' : 'Latest: ' . Version::getDaemon()) . ')');
}
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,6 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Console\Commands;
use Illuminate\Console\Command;
@ -66,7 +67,7 @@ class UpdateEmailSettings extends Command
{
$variables = [];
$file = base_path() . '/.env';
if (!file_exists($file)) {
if (! file_exists($file)) {
$this->error('Missing environment file! It appears that you have not installed this panel correctly.');
exit();
}
@ -75,35 +76,35 @@ class UpdateEmailSettings extends Command
$this->table([
'Option',
'Description'
'Description',
], [
[
'smtp',
'SMTP Server Email'
'SMTP Server Email',
],
[
'mail',
'PHP\'s Internal Mail Server'
'PHP\'s Internal Mail Server',
],
[
'mailgun',
'Mailgun Email Service'
'Mailgun Email Service',
],
[
'mandrill',
'Mandrill Transactional Email Service'
'Mandrill Transactional Email Service',
],
[
'postmark',
'Postmark Transactional Email Service'
]
'Postmark Transactional Email Service',
],
]);
$variables['MAIL_DRIVER'] = is_null($this->option('driver')) ? $this->choice('Which email driver would you like to use?', [
'smtp',
'mail',
'mailgun',
'mandrill',
'postmark'
'postmark',
]) : $this->option('driver');
switch ($variables['MAIL_DRIVER']) {

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,6 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Console\Commands;
use Uuid;
@ -66,10 +67,9 @@ class UpdateEnvironment extends Command
*/
public function handle()
{
$variables = [];
$file = base_path() . '/.env';
if (!file_exists($file)) {
if (! file_exists($file)) {
$this->error('Missing environment file! It appears that you have not installed this panel correctly.');
exit();
}
@ -77,12 +77,12 @@ class UpdateEnvironment extends Command
$envContents = file_get_contents($file);
$this->info('Simply leave blank and press enter to fields that you do not wish to update.');
if (!env('SERVICE_AUTHOR', false)) {
if (! env('SERVICE_AUTHOR', false)) {
$this->info('No service author set, setting one now.');
$variables['SERVICE_AUTHOR'] = env('SERVICE_AUTHOR', (string) Uuid::generate(4));
}
if (!env('QUEUE_STANDARD', false) || !env('QUEUE_DRIVER', false)) {
if (! env('QUEUE_STANDARD', false) || ! env('QUEUE_DRIVER', false)) {
$this->info('Setting default queue settings.');
$variables['QUEUE_DRIVER'] = env('QUEUE_DRIVER', 'database');
$variables['QUEUE_HIGH'] = env('QUEUE_HIGH', 'high');
@ -91,25 +91,25 @@ class UpdateEnvironment extends Command
}
if (is_null($this->option('dbhost'))) {
$variables['DB_HOST'] = $this->anticipate('Database Host', [ 'localhost', '127.0.0.1', env('DB_HOST') ], env('DB_HOST'));
$variables['DB_HOST'] = $this->anticipate('Database Host', ['localhost', '127.0.0.1', env('DB_HOST')], env('DB_HOST'));
} else {
$variables['DB_HOST'] = $this->option('dbhost');
}
if (is_null($this->option('dbport'))) {
$variables['DB_PORT'] = $this->anticipate('Database Port', [ 3306, env('DB_PORT') ], env('DB_PORT'));
$variables['DB_PORT'] = $this->anticipate('Database Port', [3306, env('DB_PORT')], env('DB_PORT'));
} else {
$variables['DB_PORT'] = $this->option('dbport');
}
if (is_null($this->option('dbname'))) {
$variables['DB_DATABASE'] = $this->anticipate('Database Name', [ 'pterodactyl', 'homestead', ENV('DB_DATABASE') ], env('DB_DATABASE'));
$variables['DB_DATABASE'] = $this->anticipate('Database Name', ['pterodactyl', 'homestead', ENV('DB_DATABASE')], env('DB_DATABASE'));
} else {
$variables['DB_DATABASE'] = $this->option('dbname');
}
if (is_null($this->option('dbuser'))) {
$variables['DB_USERNAME'] = $this->anticipate('Database Username', [ ENV('DB_DATABASE') ], env('DB_USERNAME'));
$variables['DB_USERNAME'] = $this->anticipate('Database Username', [ENV('DB_DATABASE')], env('DB_USERNAME'));
} else {
$variables['DB_USERNAME'] = $this->option('dbuser');
}
@ -122,7 +122,7 @@ class UpdateEnvironment extends Command
}
if (is_null($this->option('url'))) {
$variables['APP_URL'] = $this->ask('Panel URL', env('APP_URL'));
$variables['APP_URL'] = $this->ask('Panel URL (include http(s)://)', env('APP_URL'));
} else {
$variables['APP_URL'] = $this->option('url');
}

View file

@ -21,6 +21,9 @@ class Kernel extends ConsoleKernel
\Pterodactyl\Console\Commands\ClearTasks::class,
\Pterodactyl\Console\Commands\ClearServices::class,
\Pterodactyl\Console\Commands\UpdateEmailSettings::class,
\Pterodactyl\Console\Commands\CleanServiceBackup::class,
\Pterodactyl\Console\Commands\AddNode::class,
\Pterodactyl\Console\Commands\AddLocation::class,
];
/**
@ -33,5 +36,6 @@ class Kernel extends ConsoleKernel
{
$schedule->command('pterodactyl:tasks')->everyMinute()->withoutOverlapping();
$schedule->command('pterodactyl:tasks:clearlog')->twiceDaily(3, 15);
$schedule->command('pterodactyl:cleanservices')->twiceDaily(1, 13);
}
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,11 +21,13 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Events;
namespace Pterodactyl\Events\Server;
use Pterodactyl\Models\Server;
use Illuminate\Queue\SerializesModels;
class ServerDeleted
class Created
{
use SerializesModels;
@ -36,9 +38,8 @@ class ServerDeleted
*
* @return void
*/
public function __construct($id)
public function __construct(Server $server)
{
$this->server = $id;
$this->server = $server;
}
}

View file

@ -1,8 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* Translated by Jakob Schrettenbrunner <dev@schrej.net>
* 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
@ -22,23 +21,25 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
return [
/*
|--------------------------------------------------------------------------
| Password Reminder Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are the default lines which match reasons
| that are given by the password broker for a password update attempt
| has failed, such as for an invalid token or invalid new password.
|
*/
namespace Pterodactyl\Events\Server;
'password' => 'Dein Passwort muss länger als 6 Zeichen sein und mit der Wiederolung übereinstimmen.',
'reset' => 'Dein Passwort wurde zurückgesetzt!',
'sent' => 'Du erhältst eine E-Mail mit dem Zurücksetzungslink!',
'token' => 'Dieses Paswortrücksetzungstoken ist ungültig.',
'user' => 'Wir können keinen Nutzer mit dieser Email Adresse finden.',
use Pterodactyl\Models\Server;
use Illuminate\Queue\SerializesModels;
];
class Creating
{
use SerializesModels;
public $server;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(Server $server)
{
$this->server = $server;
}
}

View file

@ -0,0 +1,45 @@
<?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\Events\Server;
use Pterodactyl\Models\Server;
use Illuminate\Queue\SerializesModels;
class Deleted
{
use SerializesModels;
public $server;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(Server $server)
{
$this->server = $server;
}
}

View file

@ -0,0 +1,45 @@
<?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\Events\Server;
use Pterodactyl\Models\Server;
use Illuminate\Queue\SerializesModels;
class Deleting
{
use SerializesModels;
public $server;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(Server $server)
{
$this->server = $server;
}
}

View file

@ -0,0 +1,45 @@
<?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\Events\User;
use Pterodactyl\Models\User;
use Illuminate\Queue\SerializesModels;
class Created
{
use SerializesModels;
public $user;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(User $user)
{
$this->user = $user;
}
}

View file

@ -0,0 +1,45 @@
<?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\Events\User;
use Pterodactyl\Models\User;
use Illuminate\Queue\SerializesModels;
class Creating
{
use SerializesModels;
public $user;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(User $user)
{
$this->user = $user;
}
}

View file

@ -0,0 +1,45 @@
<?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\Events\User;
use Pterodactyl\Models\User;
use Illuminate\Queue\SerializesModels;
class Deleted
{
use SerializesModels;
public $user;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(User $user)
{
$this->user = $user;
}
}

View file

@ -0,0 +1,45 @@
<?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\Events\User;
use Pterodactyl\Models\User;
use Illuminate\Queue\SerializesModels;
class Deleting
{
use SerializesModels;
public $user;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(User $user)
{
$this->user = $user;
}
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,9 +21,9 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Exceptions;
class AccountNotFoundException extends \Exception
{
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,13 +21,13 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Exceptions;
use Log;
class DisplayException extends \Exception
{
private $_logging = null;
public function __construct($message, $log = null)
@ -44,5 +44,4 @@ class DisplayException extends \Exception
{
return $this->_logging;
}
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,6 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Exceptions;
class DisplayValidationException extends \Exception

View file

@ -3,12 +3,8 @@
namespace Pterodactyl\Exceptions;
use Log;
use Exception;
use DisplayException;
use DisplayValidationException;
use AccountNotFoundException;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
@ -50,13 +46,12 @@ class Handler extends ExceptionHandler
*/
public function render($request, Exception $exception)
{
if ($request->isXmlHttpRequest() || $request->ajax() || $request->is('remote/*')) {
if ($request->expectsJson()) {
$response = response()->json([
'error' => ($exception instanceof DisplayException) ? $exception->getMessage() : 'An unhandled error occured while attempting to process this request.'
], 500);
'error' => ($exception instanceof DisplayException) ? $exception->getMessage() : 'An unhandled error occured while attempting to process this request.',
], ($this->isHttpException($exception)) ? $exception->getStatusCode() : 500);
// parent::render() will log it, we are bypassing it in this case.
Log::error($exception);
parent::report($exception);
}
return (isset($response)) ? $response : parent::render($request, $exception);
@ -74,7 +69,7 @@ class Handler extends ExceptionHandler
if ($request->expectsJson()) {
return response()->json(['error' => 'Unauthenticated.'], 401);
}
return redirect()->guest('/auth/login');
}
}

35
app/Facades/Version.php Normal file
View file

@ -0,0 +1,35 @@
<?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\Facades;
use Illuminate\Support\Facades\Facade;
class Version extends Facade
{
protected static function getFacadeAccessor()
{
return '\Pterodactyl\Services\VersionService';
}
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,6 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Http\Controllers\API;
use Dingo\Api\Routing\Helpers;

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,6 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Http\Controllers\API;
use DB;
@ -32,14 +33,13 @@ use Pterodactyl\Models\Location;
*/
class LocationController extends BaseController
{
public function __construct()
{
//
}
/**
* List All Locations
* List All Locations.
*
* Lists all locations currently on the system.
*
@ -47,18 +47,13 @@ class LocationController extends BaseController
* @Versions({"v1"})
* @Response(200)
*/
public function list(Request $request)
public function lists(Request $request)
{
$locations = Location::select('locations.*', DB::raw('GROUP_CONCAT(nodes.id) as nodes'))
return Location::select('locations.*', DB::raw('GROUP_CONCAT(nodes.id) as nodes'))
->join('nodes', 'locations.id', '=', 'nodes.location')
->groupBy('locations.id')
->get();
foreach($locations as &$location) {
$location->nodes = explode(',', $location->nodes);
}
return $locations->toArray();
->get()->each(function ($location) {
$location->nodes = explode(',', $location->nodes);
})->all();
}
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,18 +21,15 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Http\Controllers\API;
use Illuminate\Http\Request;
use Pterodactyl\Models;
use Pterodactyl\Transformers\NodeTransformer;
use Pterodactyl\Transformers\AllocationTransformer;
use Pterodactyl\Repositories\NodeRepository;
use Pterodactyl\Exceptions\DisplayValidationException;
use Pterodactyl\Exceptions\DisplayException;
use Illuminate\Http\Request;
use Dingo\Api\Exception\ResourceException;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Repositories\NodeRepository;
use Pterodactyl\Exceptions\DisplayValidationException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException;
@ -42,14 +39,13 @@ use Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException;
*/
class NodeController extends BaseController
{
public function __construct()
{
//
}
/**
* List All Nodes
* List All Nodes.
*
* Lists all nodes currently on the system.
*
@ -60,13 +56,13 @@ class NodeController extends BaseController
* })
* @Response(200)
*/
public function list(Request $request)
public function lists(Request $request)
{
return Models\Node::all()->toArray();
}
/**
* Create a New Node
* Create a New Node.
*
* @Post("/nodes")
* @Versions({"v1"})
@ -102,7 +98,8 @@ class NodeController extends BaseController
try {
$node = new NodeRepository;
$new = $node->create($request->all());
return [ 'id' => $new ];
return ['id' => $new];
} catch (DisplayValidationException $ex) {
throw new ResourceException('A validation error occured.', json_decode($ex->getMessage(), true));
} catch (DisplayException $ex) {
@ -113,7 +110,7 @@ class NodeController extends BaseController
}
/**
* List Specific Node
* List Specific Node.
*
* Lists specific fields about a server or all fields pertaining to that node.
*
@ -129,16 +126,16 @@ class NodeController extends BaseController
{
$node = Models\Node::where('id', $id);
if (!is_null($request->input('fields'))) {
foreach(explode(',', $request->input('fields')) as $field) {
if (!empty($field)) {
if (! is_null($request->input('fields'))) {
foreach (explode(',', $request->input('fields')) as $field) {
if (! empty($field)) {
$node->addSelect($field);
}
}
}
try {
if (!$node->first()) {
if (! $node->first()) {
throw new NotFoundHttpException('No node by that ID was found.');
}
@ -146,8 +143,8 @@ class NodeController extends BaseController
'node' => $node->first(),
'allocations' => [
'assigned' => Models\Allocation::where('node', $id)->whereNotNull('assigned_to')->get(),
'unassigned' => Models\Allocation::where('node', $id)->whereNull('assigned_to')->get()
]
'unassigned' => Models\Allocation::where('node', $id)->whereNull('assigned_to')->get(),
],
];
} catch (NotFoundHttpException $ex) {
throw $ex;
@ -158,77 +155,105 @@ class NodeController extends BaseController
public function config(Request $request, $id)
{
if (!$request->secure()) {
if (! $request->secure()) {
throw new BadRequestHttpException('This API route can only be accessed using a secure connection.');
}
$node = Models\Node::where('id', $id)->first();
if (!$node) {
if (! $node) {
throw new NotFoundHttpException('No node by that ID was found.');
}
return [
'web' => [
'listen' => $node->daemonListen,
'host' => '0.0.0.0',
'ssl' => [
'enabled' => ($node->scheme === 'https'),
'certificate' => '/etc/certs/' . $node->fqdn . '/fullchain.pem',
'key' => '/etc/certs/' . $node->fqdn . '/privkey.pem'
]
'key' => '/etc/certs/' . $node->fqdn . '/privkey.pem',
],
],
'docker' => [
'socket' => '/var/run/docker.sock',
'autoupdate_images' => true
'autoupdate_images' => true,
],
'sftp' => [
'path' => $node->daemonBase,
'port' => (int) $node->daemonSFTP,
'container' => '0x0000'
'container' => 'ptdl-sftp',
],
'query' => [
'kill_on_fail' => true,
'fail_limit' => 5,
],
'logger' => [
'path' => 'logs/',
'src' => false,
'level' => 'info',
'period' => '1d',
'count' => 3
'count' => 3,
],
'remote' => [
'base' => config('app.url'),
'download' => route('remote.download'),
'installed' => route('remote.install')
'installed' => route('remote.install'),
],
'uploads' => [
'maximumSize' => 100000000
'size_limit' => $node->upload_size,
],
'keys' => [
$node->daemonSecret
$node->daemonSecret,
],
'query' => [
'kill_on_fail' => true,
'fail_limit' => 3
]
];
}
/**
* List all Node Allocations
*
* Returns a listing of all allocations for every node.
*
* @Get("/nodes/allocations")
* @Versions({"v1"})
* @Response(200)
*/
/**
* List all Node Allocations.
*
* Returns a listing of all allocations for every node.
*
* @Get("/nodes/allocations")
* @Versions({"v1"})
* @Response(200)
*/
public function allocations(Request $request)
{
$allocations = Models\Allocation::all();
if ($allocations->count() < 1) {
throw new NotFoundHttpException('No allocations have been created.');
}
return $allocations;
}
/**
* List Node Allocation based on assigned to ID.
*
* Returns a listing of the allocation for the specified server id.
*
* @Get("/nodes/allocations/{id}")
* @Versions({"v1"})
* @Response(200)
*/
public function allocationsView(Request $request, $id)
{
$query = Models\Allocation::where('assigned_to', $id)->get();
try {
if (empty($query)) {
throw new NotFoundHttpException('No allocations for that server were found.');
}
return $query;
} catch (NotFoundHttpException $ex) {
throw $ex;
} catch (\Exception $ex) {
throw new BadRequestHttpException('There was an issue with the fields passed in the request.');
}
}
/**
* Delete Node
* Delete Node.
*
* @Delete("/nodes/{id}")
* @Versions({"v1"})
@ -242,12 +267,12 @@ class NodeController extends BaseController
try {
$node = new NodeRepository;
$node->delete($id);
return $this->response->noContent();
} catch (DisplayException $ex) {
throw new ResourceException($ex->getMessage());
} catch(\Exception $e) {
} catch (\Exception $e) {
throw new ServiceUnavailableHttpException('An error occured while attempting to delete this node.');
}
}
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,18 +21,16 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Http\Controllers\API;
use Illuminate\Http\Request;
namespace Pterodactyl\Http\Controllers\API;
use Log;
use Pterodactyl\Models;
use Pterodactyl\Transformers\ServerTransformer;
use Pterodactyl\Repositories\ServerRepository;
use Pterodactyl\Exceptions\DisplayValidationException;
use Pterodactyl\Exceptions\DisplayException;
use Illuminate\Http\Request;
use Dingo\Api\Exception\ResourceException;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Repositories\ServerRepository;
use Pterodactyl\Exceptions\DisplayValidationException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException;
@ -42,14 +40,13 @@ use Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException;
*/
class ServerController extends BaseController
{
public function __construct()
{
//
}
/**
* List All Servers
* List All Servers.
*
* Lists all servers currently on the system.
*
@ -60,24 +57,25 @@ class ServerController extends BaseController
* })
* @Response(200)
*/
public function list(Request $request)
public function lists(Request $request)
{
return Models\Server::all()->toArray();
}
/**
* Create Server
*
* @Post("/servers")
* @Versions({"v1"})
* @Response(201)
* Create Server.
*
* @Post("/servers")
* @Versions({"v1"})
* @Response(201)
*/
public function create(Request $request)
{
try {
$server = new ServerRepository;
$new = $server->create($request->all());
return [ 'id' => $new ];
return ['id' => $new];
} catch (DisplayValidationException $ex) {
throw new ResourceException('A validation error occured.', json_decode($ex->getMessage(), true));
} catch (DisplayException $ex) {
@ -89,7 +87,7 @@ class ServerController extends BaseController
}
/**
* List Specific Server
* List Specific Server.
*
* Lists specific fields about a server or all fields pertaining to that server.
*
@ -105,16 +103,16 @@ class ServerController extends BaseController
{
$query = Models\Server::where('id', $id);
if (!is_null($request->input('fields'))) {
foreach(explode(',', $request->input('fields')) as $field) {
if (!empty($field)) {
if (! is_null($request->input('fields'))) {
foreach (explode(',', $request->input('fields')) as $field) {
if (! empty($field)) {
$query->addSelect($field);
}
}
}
try {
if (!$query->first()) {
if (! $query->first()) {
throw new NotFoundHttpException('No server by that ID was found.');
}
@ -126,8 +124,8 @@ class ServerController extends BaseController
$response = $client->request('GET', '/servers', [
'headers' => [
'X-Access-Token' => $node->daemonSecret
]
'X-Access-Token' => $node->daemonSecret,
],
]);
// Only return the daemon token if the request is using HTTPS
@ -140,14 +138,14 @@ class ServerController extends BaseController
}
return $server->toArray();
} catch (NotFoundHttpException $ex) {
throw $ex;
} catch (\GuzzleHttp\Exception\TransferException $ex) {
// Couldn't hit the daemon, return what we have though.
$server->daemon = [
'error' => 'There was an error encountered while attempting to connect to the remote daemon.'
'error' => 'There was an error encountered while attempting to connect to the remote daemon.',
];
return $server->toArray();
} catch (\Exception $ex) {
throw new BadRequestHttpException('There was an issue with the fields passed in the request.');
@ -155,7 +153,7 @@ class ServerController extends BaseController
}
/**
* Update Server configuration
* Update Server configuration.
*
* Updates display information on panel.
*
@ -179,6 +177,7 @@ class ServerController extends BaseController
try {
$server = new ServerRepository;
$server->updateDetails($id, $request->all());
return Models\Server::findOrFail($id);
} catch (DisplayValidationException $ex) {
throw new ResourceException('A validation error occured.', json_decode($ex->getMessage(), true));
@ -190,7 +189,7 @@ class ServerController extends BaseController
}
/**
* Update Server Build Configuration
* Update Server Build Configuration.
*
* Updates server build information on panel and on node.
*
@ -221,10 +220,9 @@ class ServerController extends BaseController
public function build(Request $request, $id)
{
try {
throw new BadRequestHttpException('There was an error while attempting to add this node to the system.');
$server = new ServerRepository;
$server->changeBuild($id, $request->all());
return Models\Server::findOrFail($id);
} catch (DisplayValidationException $ex) {
throw new ResourceException('A validation error occured.', json_decode($ex->getMessage(), true));
@ -236,7 +234,7 @@ class ServerController extends BaseController
}
/**
* Suspend Server
* Suspend Server.
*
* @Post("/servers/{id}/suspend")
* @Versions({"v1"})
@ -250,6 +248,7 @@ class ServerController extends BaseController
try {
$server = new ServerRepository;
$server->suspend($id);
return $this->response->noContent();
} catch (DisplayException $ex) {
throw new ResourceException($ex->getMessage());
@ -259,7 +258,7 @@ class ServerController extends BaseController
}
/**
* Unsuspend Server
* Unsuspend Server.
*
* @Post("/servers/{id}/unsuspend")
* @Versions({"v1"})
@ -273,6 +272,7 @@ class ServerController extends BaseController
try {
$server = new ServerRepository;
$server->unsuspend($id);
return $this->response->noContent();
} catch (DisplayException $ex) {
throw new ResourceException($ex->getMessage());
@ -282,7 +282,7 @@ class ServerController extends BaseController
}
/**
* Delete Server
* Delete Server.
*
* @Delete("/servers/{id}/{force}")
* @Versions({"v1"})
@ -297,12 +297,12 @@ class ServerController extends BaseController
try {
$server = new ServerRepository;
$server->deleteServer($id, $force);
return $this->response->noContent();
} catch (DisplayException $ex) {
throw new ResourceException($ex->getMessage());
} catch(\Exception $e) {
} catch (\Exception $e) {
throw new ServiceUnavailableHttpException('An error occured while attempting to delete this server.');
}
}
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,13 +21,11 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Http\Controllers\API;
use Illuminate\Http\Request;
use Pterodactyl\Models;
use Pterodactyl\Transformers\ServiceTransformer;
use Illuminate\Http\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
@ -35,13 +33,12 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
*/
class ServiceController extends BaseController
{
public function __construct()
{
//
}
public function list(Request $request)
public function lists(Request $request)
{
return Models\Service::all()->toArray();
}
@ -49,20 +46,16 @@ class ServiceController extends BaseController
public function view(Request $request, $id)
{
$service = Models\Service::find($id);
if (!$service) {
if (! $service) {
throw new NotFoundHttpException('No service by that ID was found.');
}
$options = Models\ServiceOptions::select('id', 'name', 'description', 'tag', 'docker_image')->where('parent_service', $service->id)->get();
foreach($options as &$opt) {
$opt->variables = Models\ServiceVariables::where('option_id', $opt->id)->get();
}
return [
'service' => $service,
'options' => $options
'options' => Models\ServiceOptions::select('id', 'name', 'description', 'tag', 'docker_image')
->where('parent_service', $service->id)
->with('variables')
->get(),
];
}
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,38 +21,31 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Http\Controllers\API\User;
use Auth;
use Dingo;
use Pterodactyl\Models;
use Illuminate\Http\Request;
use Pterodactyl\Http\Controllers\API\BaseController;
class InfoController extends BaseController
{
public function me(Request $request)
{
$servers = Models\Server::getUserServers();
$response = [];
foreach($servers as &$server) {
$response = array_merge($response, [[
return Models\Server::getUserServers()->map(function ($server) {
return [
'id' => $server->uuidShort,
'uuid' => $server->uuid,
'name' => $server->name,
'node' => $server->nodeName,
'ip' => [
'set' => $server->ip,
'alias' => $server->ip_alias
'alias' => $server->ip_alias,
],
'port' => $server->port,
'service' => $server->a_serviceName,
'option' => $server->a_serviceOptionName
]]);
}
return $response;
'option' => $server->a_serviceOptionName,
];
})->all();
}
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,18 +21,17 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Http\Controllers\API\User;
use Auth;
use Log;
use Auth;
use Pterodactyl\Models;
use Illuminate\Http\Request;
use Pterodactyl\Http\Controllers\API\BaseController;
class ServerController extends BaseController
{
public function info(Request $request, $uuid)
{
$server = Models\Server::getByUUID($uuid);
@ -43,28 +42,29 @@ class ServerController extends BaseController
$response = $client->request('GET', '/server', [
'headers' => [
'X-Access-Token' => $server->daemonSecret,
'X-Access-Server' => $server->uuid
]
'X-Access-Server' => $server->uuid,
],
]);
$json = json_decode($response->getBody());
$daemon = [
'status' => $json->status,
'stats' => $json->proc,
'query' => $json->query
'query' => $json->query,
];
} catch (\Exception $ex) {
$daemon = [
'error' => 'An error was encountered while trying to connect to the daemon to collece information. It might be offline.'
'error' => 'An error was encountered while trying to connect to the daemon to collece information. It might be offline.',
];
Log::error($ex);
}
$allocations = Models\Allocation::select('id', 'ip', 'port', 'ip_alias as alias')->where('assigned_to', $server->id)->get();
foreach($allocations as &$allocation) {
foreach ($allocations as &$allocation) {
$allocation->default = ($allocation->id === $server->allocation);
unset($allocation->id);
}
return [
'uuidShort' => $server->uuidShort,
'uuid' => $server->uuid,
@ -76,23 +76,22 @@ class ServerController extends BaseController
'disk' => $server->disk,
'io' => $server->io,
'cpu' => $server->cpu,
'oom_disabled' => (bool) $server->oom_disabled
'oom_disabled' => (bool) $server->oom_disabled,
],
'allocations' => $allocations,
'sftp' => [
'username' => (Auth::user()->can('view-sftp', $server)) ? $server->username : null
'username' => (Auth::user()->can('view-sftp', $server)) ? $server->username : null,
],
'daemon' => [
'token' => ($request->secure()) ? $server->daemonSecret : false,
'response' => $daemon
]
'response' => $daemon,
],
];
}
public function power(Request $request, $uuid)
{
$server = Models\Server::getByUUID($uuid);
$node = Models\Node::getByID($server->node);
$client = Models\Node::guzzleRequest($server->node);
Auth::user()->can('power-' . $request->input('action'), $server);
@ -100,12 +99,12 @@ class ServerController extends BaseController
$res = $client->request('PUT', '/server/power', [
'headers' => [
'X-Access-Server' => $server->uuid,
'X-Access-Token' => $server->daemonSecret
'X-Access-Token' => $server->daemonSecret,
],
'exceptions' => false,
'json' => [
'action' => $request->input('action')
]
'action' => $request->input('action'),
],
]);
if ($res->getStatusCode() !== 204) {

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,18 +21,15 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Http\Controllers\API;
use Illuminate\Http\Request;
use Dingo\Api\Exception\ResourceException;
use Pterodactyl\Models;
use Pterodactyl\Transformers\UserTransformer;
use Pterodactyl\Repositories\UserRepository;
use Pterodactyl\Exceptions\DisplayValidationException;
use Illuminate\Http\Request;
use Dingo\Api\Exception\ResourceException;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Repositories\UserRepository;
use Pterodactyl\Exceptions\DisplayValidationException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException;
@ -42,14 +39,12 @@ use Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException;
*/
class UserController extends BaseController
{
public function __construct()
{
}
/**
* List All Users
* List All Users.
*
* Lists all users currently on the system.
*
@ -60,13 +55,13 @@ class UserController extends BaseController
* })
* @Response(200)
*/
public function list(Request $request)
public function lists(Request $request)
{
return Models\User::all()->toArray();
}
/**
* List Specific User
* List Specific User.
*
* Lists specific fields about a user or all fields pertaining to that user.
*
@ -80,24 +75,24 @@ class UserController extends BaseController
*/
public function view(Request $request, $id)
{
$query = Models\User::where('id', $id);
$query = Models\User::where((is_numeric($id) ? 'id' : 'email'), $id);
if (!is_null($request->input('fields'))) {
foreach(explode(',', $request->input('fields')) as $field) {
if (!empty($field)) {
if (! is_null($request->input('fields'))) {
foreach (explode(',', $request->input('fields')) as $field) {
if (! empty($field)) {
$query->addSelect($field);
}
}
}
try {
if (!$query->first()) {
if (! $query->first()) {
throw new NotFoundHttpException('No user by that ID was found.');
}
$user = $query->first();
$userArray = $user->toArray();
$userArray['servers'] = Models\Server::select('id', 'uuid', 'node', 'suspended')->where('owner', $user->id)->get();
$userArray['servers'] = Models\Server::select('id', 'uuid', 'node', 'suspended')->where('owner', $user->id)->get();
return $userArray;
} catch (NotFoundHttpException $ex) {
@ -105,11 +100,10 @@ class UserController extends BaseController
} catch (\Exception $ex) {
throw new BadRequestHttpException('There was an issue with the fields passed in the request.');
}
}
/**
* Create a New User
* Create a New User.
*
* @Post("/users")
* @Versions({"v1"})
@ -128,8 +122,12 @@ class UserController extends BaseController
{
try {
$user = new UserRepository;
$create = $user->create($request->only([
'email', 'username', 'name_first', 'name_last', 'password', 'root_admin', 'custom_id',
]));
$create = $user->create($request->input('email'), $request->input('password'), $request->input('admin'), $request->input('custom_id'));
return [ 'id' => $create ];
return ['id' => $create];
} catch (DisplayValidationException $ex) {
throw new ResourceException('A validation error occured.', json_decode($ex->getMessage(), true));
} catch (DisplayException $ex) {
@ -140,7 +138,7 @@ class UserController extends BaseController
}
/**
* Update an Existing User
* Update an Existing User.
*
* The data sent in the request will be used to update the existing user on the system.
*
@ -161,7 +159,10 @@ class UserController extends BaseController
{
try {
$user = new UserRepository;
$user->update($id, $request->all());
$user->update($id, $request->only([
'username', 'email', 'name_first', 'name_last', 'password', 'root_admin', 'language',
]));
return Models\User::findOrFail($id);
} catch (DisplayValidationException $ex) {
throw new ResourceException('A validation error occured.', json_decode($ex->getMessage(), true));
@ -173,7 +174,7 @@ class UserController extends BaseController
}
/**
* Delete a User
* Delete a User.
*
* @Delete("/users/{id}")
* @Versions({"v1"})
@ -191,6 +192,7 @@ class UserController extends BaseController
try {
$user = new UserRepository;
$user->delete($id);
return $this->response->noContent();
} catch (DisplayException $ex) {
throw new ResourceException($ex->getMessage());
@ -198,5 +200,4 @@ class UserController extends BaseController
throw new ServiceUnavailableHttpException('Unable to delete this user due to an error.');
}
}
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,20 +21,19 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Http\Controllers\Admin;
use Alert;
use Settings;
use Validator;
use Pterodactyl\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Pterodactyl\Http\Controllers\Controller;
class BaseController extends Controller
{
/**
* Controller Constructor
* Controller Constructor.
*/
public function __construct()
{
@ -57,7 +56,7 @@ class BaseController extends Controller
'company' => 'required|between:1,256',
'default_language' => 'required|alpha_dash|min:2|max:5',
'email_from' => 'required|email',
'email_sender_name' => 'required|between:1,256'
'email_sender_name' => 'required|between:1,256',
]);
if ($validator->fails()) {
@ -70,8 +69,7 @@ class BaseController extends Controller
Settings::set('email_sender_name', $request->input('email_sender_name'));
Alert::success('Settings have been successfully updated.')->flash();
return redirect()->route('admin.settings');
}
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,25 +21,23 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Http\Controllers\Admin;
use Alert;
use DB;
use Log;
use Alert;
use Pterodactyl\Models;
use Pterodactyl\Repositories\DatabaseRepository;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Exceptions\DisplayValidationException;
use Pterodactyl\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Http\Controllers\Controller;
use Pterodactyl\Repositories\DatabaseRepository;
use Pterodactyl\Exceptions\DisplayValidationException;
class DatabaseController extends Controller
{
/**
* Controller Constructor
* Controller Constructor.
*/
public function __construct()
{
@ -63,7 +61,7 @@ class DatabaseController extends Controller
'nodes.name as a_linkedNode',
DB::raw('(SELECT COUNT(*) FROM `databases` WHERE `databases`.`db_server` = database_servers.id) as c_databases')
)->leftJoin('nodes', 'nodes.id', '=', 'database_servers.linked_node')
->paginate(20)
->paginate(20),
]);
}
@ -72,7 +70,7 @@ class DatabaseController extends Controller
return view('admin.databases.new', [
'nodes' => Models\Node::select('nodes.id', 'nodes.name', 'locations.long as a_location')
->join('locations', 'locations.id', '=', 'nodes.location')
->get()
->get(),
]);
}
@ -81,12 +79,13 @@ class DatabaseController extends Controller
try {
$repo = new DatabaseRepository;
$repo->add($request->except([
'_token'
'_token',
]));
Alert::success('Successfully added a new database server to the system.')->flash();
return redirect()->route('admin.databases', [
'tab' => 'tab_dbservers'
'tab' => 'tab_dbservers',
]);
} catch (DisplayValidationException $ex) {
return redirect()->route('admin.databases.new')->withErrors(json_decode($ex->getMessage()))->withInput();
@ -97,6 +96,7 @@ class DatabaseController extends Controller
Log::error($ex);
Alert::danger('An error occurred while attempting to delete this database server from the system.')->flash();
}
return redirect()->route('admin.databases.new')->withInput();
}
}
@ -108,8 +108,9 @@ class DatabaseController extends Controller
$repo->drop($id);
} catch (\Exception $ex) {
Log::error($ex);
return response()->json([
'error' => ($ex instanceof DisplayException) ? $ex->getMessage() : 'An error occurred while attempting to delete this database from the system.'
'error' => ($ex instanceof DisplayException) ? $ex->getMessage() : 'An error occurred while attempting to delete this database from the system.',
], 500);
}
}
@ -121,10 +122,10 @@ class DatabaseController extends Controller
$repo->delete($id);
} catch (\Exception $ex) {
Log::error($ex);
return response()->json([
'error' => ($ex instanceof DisplayException) ? $ex->getMessage() : 'An error occurred while attempting to delete this database server from the system.'
'error' => ($ex instanceof DisplayException) ? $ex->getMessage() : 'An error occurred while attempting to delete this database server from the system.',
], 500);
}
}
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,23 +21,20 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Http\Controllers\Admin;
use DB;
use Alert;
use Pterodactyl\Models;
use Pterodactyl\Repositories\LocationRepository;
use Pterodactyl\Http\Controllers\Controller;
use Pterodactyl\Exceptions\DisplayValidationException;
use Pterodactyl\Exceptions\DisplayException;
use Illuminate\Http\Request;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Http\Controllers\Controller;
use Pterodactyl\Repositories\LocationRepository;
use Pterodactyl\Exceptions\DisplayValidationException;
class LocationsController extends Controller
{
public function __construct()
{
//
@ -50,7 +47,7 @@ class LocationsController extends Controller
'locations.*',
DB::raw('(SELECT COUNT(*) FROM nodes WHERE nodes.location = locations.id) as a_nodeCount'),
DB::raw('(SELECT COUNT(*) FROM servers WHERE servers.node IN (SELECT nodes.id FROM nodes WHERE nodes.location = locations.id)) as a_serverCount')
)->paginate(20)
)->paginate(20),
]);
}
@ -62,19 +59,20 @@ class LocationsController extends Controller
DB::raw('(SELECT COUNT(*) FROM servers WHERE servers.node IN (SELECT nodes.id FROM nodes WHERE nodes.location = locations.id)) as a_serverCount')
)->where('id', $id)->first();
if (!$model) {
if (! $model) {
return response()->json([
'error' => 'No location with that ID exists on the system.'
'error' => 'No location with that ID exists on the system.',
], 404);
}
if ($model->a_nodeCount > 0 || $model->a_serverCount > 0) {
return response()->json([
'error' => 'You cannot remove a location that is currently assigned to a node or server.'
'error' => 'You cannot remove a location that is currently assigned to a node or server.',
], 422);
}
$model->delete();
return response('', 204);
}
@ -83,10 +81,11 @@ class LocationsController extends Controller
try {
$location = new LocationRepository;
$location->edit($id, $request->all());
return response('', 204);
} catch (DisplayValidationException $ex) {
return response()->json([
'error' => 'There was a validation error while processing this request. Location descriptions must be between 1 and 255 characters, and the location code must be between 1 and 10 characters with no spaces or special characters.'
'error' => 'There was a validation error while processing this request. Location descriptions must be between 1 and 255 characters, and the location code must be between 1 and 10 characters with no spaces or special characters.',
], 422);
} catch (\Exception $ex) {
// This gets caught and processed into JSON anyways.
@ -99,9 +98,10 @@ class LocationsController extends Controller
try {
$location = new LocationRepository;
$id = $location->create($request->except([
'_token'
'_token',
]));
Alert::success('New location successfully added.')->flash();
return redirect()->route('admin.locations');
} catch (DisplayValidationException $ex) {
return redirect()->route('admin.locations')->withErrors(json_decode($ex->getMessage()))->withInput();
@ -111,7 +111,7 @@ class LocationsController extends Controller
Log::error($ex);
Alert::danger('An unhandled exception occured while attempting to add this location. Please try again.')->flash();
}
return redirect()->route('admin.locations')->withInput();
}
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,27 +21,25 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Http\Controllers\Admin;
use Alert;
use Debugbar;
use Log;
use DB;
use Log;
use Alert;
use Carbon;
use Validator;
use Pterodactyl\Models;
use Pterodactyl\Repositories\NodeRepository;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Exceptions\DisplayValidationException;
use Pterodactyl\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Http\Controllers\Controller;
use Pterodactyl\Repositories\NodeRepository;
use Pterodactyl\Exceptions\DisplayValidationException;
class NodesController extends Controller
{
/**
* Controller Constructor
* Controller Constructor.
*/
public function __construct()
{
@ -50,7 +48,7 @@ class NodesController extends Controller
public function getScript(Request $request, $id)
{
return response()->view('admin.nodes.remote.deploy', [ 'node' => Models\Node::findOrFail($id) ])->header('Content-Type', 'text/plain');
return response()->view('admin.nodes.remote.deploy', ['node' => Models\Node::findOrFail($id)])->header('Content-Type', 'text/plain');
}
public function getIndex(Request $request)
@ -66,13 +64,14 @@ class NodesController extends Controller
public function getNew(Request $request)
{
if (!Models\Location::all()->count()) {
if (! Models\Location::all()->count()) {
Alert::warning('You must add a location before you can add a new node.')->flash();
return redirect()->route('admin.locations');
}
return view('admin.nodes.new', [
'locations' => Models\Location::all()
'locations' => Models\Location::all(),
]);
}
@ -81,12 +80,14 @@ class NodesController extends Controller
try {
$node = new NodeRepository;
$new = $node->create($request->except([
'_token'
'_token',
]));
Alert::success('Successfully created new node. <strong>Before you can add any servers you need to first assign some IP addresses and ports.</strong>')->flash();
Alert::info('<strong>To simplify the node setup you can generate a token on the configuration tab.</strong>')->flash();
return redirect()->route('admin.nodes.view', [
'id' => $new,
'tab' => 'tab_allocation'
'tab' => 'tab_allocation',
]);
} catch (DisplayValidationException $e) {
return redirect()->route('admin.nodes.new')->withErrors(json_decode($e->getMessage()))->withInput();
@ -96,6 +97,7 @@ class NodesController extends Controller
Log::error($e);
Alert::danger('An unhandled exception occured while attempting to add this node. Please try again.')->flash();
}
return redirect()->route('admin.nodes.new')->withInput();
}
@ -129,12 +131,13 @@ class NodesController extends Controller
try {
$node = new NodeRepository;
$node->update($id, $request->except([
'_token'
'_token',
]));
Alert::success('Successfully update this node\'s information. If you changed any daemon settings you will need to restart it now.')->flash();
return redirect()->route('admin.nodes.view', [
'id' => $id,
'tab' => 'tab_settings'
'tab' => 'tab_settings',
]);
} catch (DisplayValidationException $e) {
return redirect()->route('admin.nodes.view', $id)->withErrors(json_decode($e->getMessage()))->withInput();
@ -144,9 +147,10 @@ class NodesController extends Controller
Log::error($e);
Alert::danger('An unhandled exception occured while attempting to edit this node. Please try again.')->flash();
}
return redirect()->route('admin.nodes.view', [
'id' => $id,
'tab' => 'tab_settings'
'tab' => 'tab_settings',
])->withInput();
}
@ -155,9 +159,10 @@ class NodesController extends Controller
$query = Models\Allocation::where('node', $node)->whereNull('assigned_to')->where('id', $allocation)->delete();
if ((int) $query === 0) {
return response()->json([
'error' => 'Unable to find an allocation matching those details to delete.'
'error' => 'Unable to find an allocation matching those details to delete.',
], 400);
}
return response('', 204);
}
@ -166,21 +171,23 @@ class NodesController extends Controller
$query = Models\Allocation::where('node', $node)->whereNull('assigned_to')->where('ip', $request->input('ip'))->delete();
if ((int) $query === 0) {
Alert::danger('There was an error while attempting to delete allocations on that IP.')->flash();
return redirect()->route('admin.nodes.view', [
'id' => $node,
'tab' => 'tab_allocations'
'tab' => 'tab_allocations',
]);
}
Alert::success('Deleted all unallocated ports for <code>' . $request->input('ip') . '</code>.')->flash();
return redirect()->route('admin.nodes.view', [
'id' => $node,
'tab' => 'tab_allocation'
'tab' => 'tab_allocation',
]);
}
public function setAlias(Request $request, $node)
{
if (!$request->input('allocation')) {
if (! $request->input('allocation')) {
return response('Missing required parameters.', 422);
}
@ -198,36 +205,36 @@ class NodesController extends Controller
public function getAllocationsJson(Request $request, $id)
{
$allocations = Models\Allocation::select('ip')->where('node', $id)->groupBy('ip')->get();
return response()->json($allocations);
}
public function postAllocations(Request $request, $id)
{
$validator = Validator::make($request->all(), [
'allocate_ip.*' => 'required|string',
'allocate_port.*' => 'required'
'allocate_port.*' => 'required',
]);
if ($validator->fails()) {
return redirect()->route('admin.nodes.view', [
'id' => $id,
'tab' => 'tab_allocation'
'tab' => 'tab_allocation',
])->withErrors($validator->errors())->withInput();
}
$processedData = [];
foreach($request->input('allocate_ip') as $ip) {
if (!array_key_exists($ip, $processedData)) {
foreach ($request->input('allocate_ip') as $ip) {
if (! array_key_exists($ip, $processedData)) {
$processedData[$ip] = [];
}
}
foreach($request->input('allocate_port') as $portid => $ports) {
foreach ($request->input('allocate_port') as $portid => $ports) {
if (array_key_exists($portid, $request->input('allocate_ip'))) {
$json = json_decode($ports);
if (json_last_error() === 0 && !empty($json)) {
foreach($json as &$parsed) {
if (json_last_error() === 0 && ! empty($json)) {
foreach ($json as &$parsed) {
array_push($processedData[$request->input('allocate_ip')[$portid]], $parsed->value);
}
}
@ -246,27 +253,49 @@ class NodesController extends Controller
} finally {
return redirect()->route('admin.nodes.view', [
'id' => $id,
'tab' => 'tab_allocation'
'tab' => 'tab_allocation',
]);
}
}
public function deleteNode(Request $request, $id)
{
$node = Models\Node::findOrFail($id);
$servers = Models\Server::where('node', $id)->count();
if ($servers > 0) {
Alert::danger('You cannot delete a node with servers currently attached to it.')->flash();
return redirect()->route('admin.nodes.view', [
'id' => $id,
'tab' => 'tab_delete'
]);
try {
$repo = new NodeRepository;
$repo->delete($id);
Alert::success('Successfully deleted the requested node from the panel.')->flash();
return redirect()->route('admin.nodes');
} catch (DisplayException $e) {
Alert::danger($e->getMessage())->flash();
} catch (\Exception $e) {
Log::error($e);
Alert::danger('An unhandled exception occured while attempting to delete this node. Please try again.')->flash();
}
$node->delete();
Alert::success('Node successfully deleted.')->flash();
return redirect()->route('admin.nodes');
return redirect()->route('admin.nodes.view', [
'id' => $id,
'tab' => 'tab_delete',
]);
}
public function getConfigurationToken(Request $request, $id)
{
// Check if Node exists. Will lead to 404 if not.
Models\Node::findOrFail($id);
// Create a token
$token = new Models\NodeConfigurationToken();
$token->node = $id;
$token->token = str_random(32);
$token->expires_at = Carbon::now()->addMinutes(5); // Expire in 5 Minutes
$token->save();
$token_response = [
'token' => $token->token,
'expires_at' => $token->expires_at->toDateTimeString(),
];
return response()->json($token_response, 200);
}
}

View file

@ -0,0 +1,244 @@
<?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\Http\Controllers\Admin;
use DB;
use Log;
use Alert;
use Storage;
use Pterodactyl\Models;
use Illuminate\Http\Request;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Http\Controllers\Controller;
use Pterodactyl\Repositories\ServiceRepository\Pack;
use Pterodactyl\Exceptions\DisplayValidationException;
class PackController extends Controller
{
public function __construct()
{
//
}
protected function formatServices()
{
$options = Models\ServiceOptions::select(
'services.name AS p_service',
'service_options.id',
'service_options.name'
)->join('services', 'services.id', '=', 'service_options.parent_service')->get();
$array = [];
foreach ($options as &$option) {
if (! array_key_exists($option->p_service, $array)) {
$array[$option->p_service] = [];
}
$array[$option->p_service] = array_merge($array[$option->p_service], [[
'id' => $option->id,
'name' => $option->name,
]]);
}
return $array;
}
public function listAll(Request $request)
{
return view('admin.services.packs.index', [
'services' => Models\Service::all(),
]);
}
public function listByOption(Request $request, $id)
{
$option = Models\ServiceOptions::findOrFail($id);
return view('admin.services.packs.byoption', [
'packs' => Models\ServicePack::where('option', $option->id)->get(),
'service' => Models\Service::findOrFail($option->parent_service),
'option' => $option,
]);
}
public function listByService(Request $request, $id)
{
return view('admin.services.packs.byservice', [
'service' => Models\Service::findOrFail($id),
'options' => Models\ServiceOptions::select(
'service_options.id',
'service_options.name',
DB::raw('(SELECT COUNT(id) FROM service_packs WHERE service_packs.option = service_options.id) AS p_count')
)->where('parent_service', $id)->get(),
]);
}
public function new(Request $request, $opt = null)
{
return view('admin.services.packs.new', [
'services' => $this->formatServices(),
'packFor' => $opt,
]);
}
public function create(Request $request)
{
try {
$repo = new Pack;
$id = $repo->create($request->except([
'_token',
]));
Alert::success('Successfully created new service!')->flash();
return redirect()->route('admin.services.packs.edit', $id)->withInput();
} catch (DisplayValidationException $ex) {
return redirect()->route('admin.services.packs.new', $request->input('option'))->withErrors(json_decode($ex->getMessage()))->withInput();
} catch (DisplayException $ex) {
Alert::danger($ex->getMessage())->flash();
} catch (\Exception $ex) {
Log::error($ex);
Alert::danger('An error occured while attempting to add a new service pack.')->flash();
}
return redirect()->route('admin.services.packs.new', $request->input('option'))->withInput();
}
public function edit(Request $request, $id)
{
$pack = Models\ServicePack::findOrFail($id);
$option = Models\ServiceOptions::select('id', 'parent_service', 'name')->where('id', $pack->option)->first();
return view('admin.services.packs.edit', [
'pack' => $pack,
'services' => $this->formatServices(),
'files' => Storage::files('packs/' . $pack->uuid),
'service' => Models\Service::findOrFail($option->parent_service),
'option' => $option,
]);
}
public function update(Request $request, $id)
{
if (! is_null($request->input('action_delete'))) {
try {
$repo = new Pack;
$repo->delete($id);
Alert::success('The requested service pack has been deleted from the system.')->flash();
return redirect()->route('admin.services.packs');
} catch (DisplayException $ex) {
Alert::danger($ex->getMessage())->flash();
} catch (\Exception $ex) {
Log::error($ex);
Alert::danger('An error occured while attempting to delete this pack.')->flash();
}
return redirect()->route('admin.services.packs.edit', $id);
} else {
try {
$repo = new Pack;
$repo->update($id, $request->except([
'_token',
]));
Alert::success('Service pack has been successfully updated.')->flash();
} catch (DisplayValidationException $ex) {
return redirect()->route('admin.services.packs.edit', $id)->withErrors(json_decode($ex->getMessage()))->withInput();
} catch (\Exception $ex) {
Log::error($ex);
Alert::danger('An error occured while attempting to add edit this pack.')->flash();
}
return redirect()->route('admin.services.packs.edit', $id);
}
}
public function export(Request $request, $id, $files = false)
{
$pack = Models\ServicePack::findOrFail($id);
$json = [
'name' => $pack->name,
'version' => $pack->version,
'description' => $pack->dscription,
'selectable' => (bool) $pack->selectable,
'visible' => (bool) $pack->visible,
];
$filename = tempnam(sys_get_temp_dir(), 'pterodactyl_');
if ((bool) $files) {
$zip = new \ZipArchive;
if (! $zip->open($filename, \ZipArchive::CREATE)) {
abort(503, 'Unable to open file for writing.');
}
$files = Storage::files('packs/' . $pack->uuid);
foreach ($files as $file) {
$zip->addFile(storage_path('app/' . $file), basename(storage_path('app/' . $file)));
}
$zip->addFromString('import.json', json_encode($json, JSON_PRETTY_PRINT));
$zip->close();
return response()->download($filename, 'pack-' . $pack->name . '.zip')->deleteFileAfterSend(true);
} else {
$fp = fopen($filename, 'a+');
fwrite($fp, json_encode($json, JSON_PRETTY_PRINT));
fclose($fp);
return response()->download($filename, 'pack-' . $pack->name . '.json', [
'Content-Type' => 'application/json',
])->deleteFileAfterSend(true);
}
}
public function uploadForm(Request $request, $for = null)
{
return view('admin.services.packs.upload', [
'services' => $this->formatServices(),
'for' => $for,
]);
}
public function postUpload(Request $request)
{
try {
$repo = new Pack;
$id = $repo->createWithTemplate($request->except([
'_token',
]));
Alert::success('Successfully created new service!')->flash();
return redirect()->route('admin.services.packs.edit', $id)->withInput();
} catch (DisplayValidationException $ex) {
return redirect()->back()->withErrors(json_decode($ex->getMessage()))->withInput();
} catch (DisplayException $ex) {
Alert::danger($ex->getMessage())->flash();
} catch (\Exception $ex) {
Log::error($ex);
Alert::danger('An error occured while attempting to add a new service pack.')->flash();
}
return redirect()->back();
}
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,28 +21,24 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Http\Controllers\Admin;
use Alert;
use Debugbar;
use DB;
use Log;
use Alert;
use Pterodactyl\Models;
use Illuminate\Http\Request;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Http\Controllers\Controller;
use Pterodactyl\Repositories\ServerRepository;
use Pterodactyl\Repositories\DatabaseRepository;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Exceptions\DisplayValidationException;
use Pterodactyl\Http\Controllers\Controller;
use Illuminate\Http\Request;
class ServersController extends Controller
{
/**
* Controller Constructor
* Controller Constructor.
*/
public function __construct()
{
@ -62,20 +58,29 @@ class ServersController extends Controller
->join('users', 'servers.owner', '=', 'users.id')
->join('allocations', 'servers.allocation', '=', 'allocations.id');
if ($request->input('filter') && !is_null($request->input('filter'))) {
if ($request->input('filter') && ! is_null($request->input('filter'))) {
preg_match_all('/[^\s"\']+|"([^"]*)"|\'([^\']*)\'/', urldecode($request->input('filter')), $matches);
foreach($matches[0] as $match) {
foreach ($matches[0] as $match) {
$match = str_replace('"', '', $match);
if (strpos($match, ':')) {
list($field, $term) = explode(':', $match);
$field = (strpos($field, '.')) ? $field : 'servers.' . $field;
if ($field === 'node') {
$field = 'nodes.name';
} elseif ($field === 'owner') {
$field = 'users.email';
} elseif (! strpos($field, '.')) {
$field = 'servers.' . $field;
}
$query->orWhere($field, 'LIKE', '%' . $term . '%');
} else {
$query->where('servers.name', 'LIKE', '%' . $match . '%');
$query->orWhere('servers.username', 'LIKE', '%' . $match . '%');
$query->orWhere('users.email', 'LIKE', '%' . $match . '%');
$query->orWhere('allocations.port', 'LIKE', '%' . $match . '%');
$query->orWhere('allocations.ip', 'LIKE', '%' . $match . '%');
$query->orWhere([
['servers.username', 'LIKE', '%' . $match . '%'],
['users.email', 'LIKE', '%' . $match . '%'],
['allocations.port', 'LIKE', '%' . $match . '%'],
['allocations.ip', 'LIKE', '%' . $match . '%'],
]);
}
}
}
@ -98,7 +103,7 @@ class ServersController extends Controller
}
return view('admin.servers.index', [
'servers' => $servers
'servers' => $servers,
]);
}
@ -106,7 +111,7 @@ class ServersController extends Controller
{
return view('admin.servers.new', [
'locations' => Models\Location::all(),
'services' => Models\Service::all()
'services' => Models\Service::all(),
]);
}
@ -114,9 +119,7 @@ class ServersController extends Controller
{
$server = Models\Server::withTrashed()->select(
'servers.*',
'nodes.name as a_nodeName',
'users.email as a_ownerEmail',
'locations.long as a_locationName',
'services.name as a_serviceName',
DB::raw('IFNULL(service_options.executable, services.executable) as a_serviceExecutable'),
'service_options.docker_image',
@ -126,19 +129,24 @@ class ServersController extends Controller
'allocations.ip_alias'
)->join('nodes', 'servers.node', '=', 'nodes.id')
->join('users', 'servers.owner', '=', 'users.id')
->join('locations', 'nodes.location', '=', 'locations.id')
->join('services', 'servers.service', '=', 'services.id')
->join('service_options', 'servers.option', '=', 'service_options.id')
->join('allocations', 'servers.allocation', '=', 'allocations.id')
->where('servers.id', $id)
->first();
if (!$server) {
if (! $server) {
return abort(404);
}
return view('admin.servers.view', [
'server' => $server,
'node' => Models\Node::select(
'nodes.*',
'locations.long as a_locationName'
)->join('locations', 'nodes.location', '=', 'locations.id')
->where('nodes.id', $server->node)
->first(),
'assigned' => Models\Allocation::where('assigned_to', $id)->orderBy('ip', 'asc')->orderBy('port', 'asc')->get(),
'unassigned' => Models\Allocation::where('node', $server->node)->whereNull('assigned_to')->orderBy('ip', 'asc')->orderBy('port', 'asc')->get(),
'startup' => Models\ServiceVariables::select('service_variables.*', 'server_variables.variable_value as a_serverValue')
@ -150,28 +158,29 @@ class ServersController extends Controller
->where('server_id', $server->id)
->join('database_servers', 'database_servers.id', '=', 'databases.db_server')
->get(),
'db_servers' => Models\DatabaseServer::all()
'db_servers' => Models\DatabaseServer::all(),
]);
}
public function postNewServer(Request $request)
{
try {
$server = new ServerRepository;
$response = $server->create($request->all());
return redirect()->route('admin.servers.view', [ 'id' => $response ]);
return redirect()->route('admin.servers.view', ['id' => $response]);
} catch (DisplayValidationException $ex) {
return redirect()->route('admin.servers.new')->withErrors(json_decode($ex->getMessage()))->withInput();
} catch (DisplayException $ex) {
Alert::danger($ex->getMessage())->flash();
return redirect()->route('admin.servers.new')->withInput();
} catch (\Exception $ex) {
Log::error($ex);
Alert::danger('An unhandled exception occured while attemping to add this server. Please try again.')->flash();
return redirect()->route('admin.servers.new')->withInput();
}
}
/**
@ -182,15 +191,13 @@ class ServersController extends Controller
*/
public function postNewServerGetNodes(Request $request)
{
if(!$request->input('location')) {
if (! $request->input('location')) {
return response()->json([
'error' => 'Missing location in request.'
'error' => 'Missing location in request.',
], 500);
}
return response()->json(Models\Node::select('id', 'name', 'public')->where('location', $request->input('location'))->get());
}
/**
@ -201,25 +208,24 @@ class ServersController extends Controller
*/
public function postNewServerGetIps(Request $request)
{
if(!$request->input('node')) {
if (! $request->input('node')) {
return response()->json([
'error' => 'Missing node in request.'
'error' => 'Missing node in request.',
], 500);
}
$ips = Models\Allocation::where('node', $request->input('node'))->whereNull('assigned_to')->get();
$listing = [];
foreach($ips as &$ip) {
foreach ($ips as &$ip) {
if (array_key_exists($ip->ip, $listing)) {
$listing[$ip->ip] = array_merge($listing[$ip->ip], [$ip->port]);
} else {
$listing[$ip->ip] = [$ip->port];
}
}
return response()->json($listing);
return response()->json($listing);
}
/**
@ -230,16 +236,15 @@ class ServersController extends Controller
*/
public function postNewServerServiceOptions(Request $request)
{
if(!$request->input('service')) {
if (! $request->input('service')) {
return response()->json([
'error' => 'Missing service in request.'
'error' => 'Missing service in request.',
], 500);
}
$service = Models\Service::select('executable', 'startup')->where('id', $request->input('service'))->first();
return response()->json(Models\ServiceOptions::select('id', 'name', 'docker_image')->where('parent_service', $request->input('service'))->orderBy('name', 'asc')->get());
return response()->json(Models\ServiceOptions::select('id', 'name', 'docker_image')->where('parent_service', $request->input('service'))->orderBy('name', 'asc')->get());
}
/**
@ -248,12 +253,11 @@ class ServersController extends Controller
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Contracts\View\View
*/
public function postNewServerServiceVariables(Request $request)
public function postNewServerOptionDetails(Request $request)
{
if(!$request->input('option')) {
if (! $request->input('option')) {
return response()->json([
'error' => 'Missing option in request.'
'error' => 'Missing option in request.',
], 500);
}
@ -265,30 +269,28 @@ class ServersController extends Controller
->first();
return response()->json([
'packs' => Models\ServicePack::select('id', 'name', 'version')->where('option', $request->input('option'))->where('selectable', true)->get(),
'variables' => Models\ServiceVariables::where('option_id', $request->input('option'))->get(),
'exec' => $option->executable,
'startup' => $option->startup
'startup' => $option->startup,
]);
}
public function postUpdateServerDetails(Request $request, $id)
{
try {
$server = new ServerRepository;
$server->updateDetails($id, [
'owner' => $request->input('owner'),
'name' => $request->input('name'),
'reset_token' => ($request->input('reset_token', false) === 'on') ? true : false
'reset_token' => ($request->input('reset_token', false) === 'on') ? true : false,
]);
Alert::success('Server details were successfully updated.')->flash();
} catch (DisplayValidationException $ex) {
return redirect()->route('admin.servers.view', [
'id' => $id,
'tab' => 'tab_details'
'tab' => 'tab_details',
])->withErrors(json_decode($ex->getMessage()))->withInput();
} catch (DisplayException $ex) {
Alert::danger($ex->getMessage())->flash();
@ -299,21 +301,22 @@ class ServersController extends Controller
return redirect()->route('admin.servers.view', [
'id' => $id,
'tab' => 'tab_details'
'tab' => 'tab_details',
])->withInput();
}
public function postUpdateContainerDetails(Request $request, $id) {
public function postUpdateContainerDetails(Request $request, $id)
{
try {
$server = new ServerRepository;
$server->updateContainer($id, [
'image' => $request->input('docker_image')
'image' => $request->input('docker_image'),
]);
Alert::success('Successfully updated this server\'s docker image.')->flash();
} catch (DisplayValidationException $ex) {
return redirect()->route('admin.servers.view', [
'id' => $id,
'tab' => 'tab_details'
'tab' => 'tab_details',
])->withErrors(json_decode($ex->getMessage()))->withInput();
} catch (DisplayException $ex) {
Alert::danger($ex->getMessage())->flash();
@ -324,11 +327,12 @@ class ServersController extends Controller
return redirect()->route('admin.servers.view', [
'id' => $id,
'tab' => 'tab_details'
'tab' => 'tab_details',
]);
}
public function postUpdateServerToggleBuild(Request $request, $id) {
public function postUpdateServerToggleBuild(Request $request, $id)
{
$server = Models\Server::findOrFail($id);
$node = Models\Node::findOrFail($server->node);
$client = Models\Node::guzzleRequest($server->node);
@ -337,8 +341,8 @@ class ServersController extends Controller
$res = $client->request('POST', '/server/rebuild', [
'headers' => [
'X-Access-Server' => $server->uuid,
'X-Access-Token' => $node->daemonSecret
]
'X-Access-Token' => $node->daemonSecret,
],
]);
Alert::success('A rebuild has been queued successfully. It will run the next time this server is booted.')->flash();
} catch (\GuzzleHttp\Exception\TransferException $ex) {
@ -348,14 +352,13 @@ class ServersController extends Controller
return redirect()->route('admin.servers.view', [
'id' => $id,
'tab' => 'tab_manage'
'tab' => 'tab_manage',
]);
}
public function postUpdateServerUpdateBuild(Request $request, $id)
{
try {
$server = new ServerRepository;
$server->changeBuild($id, [
'default' => $request->input('default'),
@ -370,13 +373,14 @@ class ServersController extends Controller
} catch (DisplayValidationException $ex) {
return redirect()->route('admin.servers.view', [
'id' => $id,
'tab' => 'tab_build'
'tab' => 'tab_build',
])->withErrors(json_decode($ex->getMessage()))->withInput();
} catch (DisplayException $ex) {
Alert::danger($ex->getMessage())->flash();
return redirect()->route('admin.servers.view', [
'id' => $id,
'tab' => 'tab_build'
'tab' => 'tab_build',
]);
} catch (\Exception $ex) {
Log::error($ex);
@ -385,7 +389,7 @@ class ServersController extends Controller
return redirect()->route('admin.servers.view', [
'id' => $id,
'tab' => 'tab_build'
'tab' => 'tab_build',
]);
}
@ -395,16 +399,18 @@ class ServersController extends Controller
$server = new ServerRepository;
$server->deleteServer($id, $force);
Alert::success('Server has been marked for deletion on the system.')->flash();
return redirect()->route('admin.servers');
} catch (DisplayException $ex) {
Alert::danger($ex->getMessage())->flash();
} catch(\Exception $ex) {
} catch (\Exception $ex) {
Log::error($ex);
Alert::danger('An unhandled exception occured while attemping to delete this server. Please try again.')->flash();
}
return redirect()->route('admin.servers.view', [
'id' => $id,
'tab' => 'tab_delete'
'tab' => 'tab_delete',
]);
}
@ -416,13 +422,13 @@ class ServersController extends Controller
Alert::success('Server status was successfully toggled.')->flash();
} catch (DisplayException $ex) {
Alert::danger($ex->getMessage())->flash();
} catch(\Exception $ex) {
} catch (\Exception $ex) {
Log::error($ex);
Alert::danger('An unhandled exception occured while attemping to toggle this servers status.')->flash();
} finally {
return redirect()->route('admin.servers.view', [
'id' => $id,
'tab' => 'tab_manage'
'tab' => 'tab_manage',
]);
}
}
@ -432,18 +438,18 @@ class ServersController extends Controller
try {
$server = new ServerRepository;
$server->updateStartup($id, $request->except([
'_token'
'_token',
]), true);
Alert::success('Server startup variables were successfully updated.')->flash();
} catch (\Pterodactyl\Exceptions\DisplayException $e) {
Alert::danger($e->getMessage())->flash();
} catch(\Exception $e) {
} catch (\Exception $e) {
Log::error($e);
Alert::danger('An unhandled exception occured while attemping to update startup variables for this server. Please try again.')->flash();
} finally {
return redirect()->route('admin.servers.view', [
'id' => $id,
'tab' => 'tab_startup'
'tab' => 'tab_startup',
])->withInput();
}
}
@ -453,13 +459,13 @@ class ServersController extends Controller
try {
$repo = new DatabaseRepository;
$repo->create($id, $request->except([
'_token'
'_token',
]));
Alert::success('Added new database to this server.')->flash();
} catch (DisplayValidationException $ex) {
return redirect()->route('admin.servers.view', [
'id' => $id,
'tab' => 'tab_database'
'tab' => 'tab_database',
])->withInput()->withErrors(json_decode($ex->getMessage()))->withInput();
} catch (\Exception $ex) {
Log::error($ex);
@ -468,7 +474,7 @@ class ServersController extends Controller
return redirect()->route('admin.servers.view', [
'id' => $id,
'tab' => 'tab_database'
'tab' => 'tab_database',
])->withInput();
}
@ -480,13 +486,13 @@ class ServersController extends Controller
Alert::success('Server has been suspended on the system. All running processes have been stopped and will not be startable until it is un-suspended.');
} catch (DisplayException $e) {
Alert::danger($e->getMessage())->flash();
} catch(\Exception $e) {
} catch (\Exception $e) {
Log::error($e);
Alert::danger('An unhandled exception occured while attemping to suspend this server. Please try again.')->flash();
} finally {
return redirect()->route('admin.servers.view', [
'id' => $id,
'tab' => 'tab_manage'
'tab' => 'tab_manage',
]);
}
}
@ -499,13 +505,13 @@ class ServersController extends Controller
Alert::success('Server has been unsuspended on the system. Access has been re-enabled.');
} catch (DisplayException $e) {
Alert::danger($e->getMessage())->flash();
} catch(\Exception $e) {
} catch (\Exception $e) {
Log::error($e);
Alert::danger('An unhandled exception occured while attemping to unsuspend this server. Please try again.')->flash();
} finally {
return redirect()->route('admin.servers.view', [
'id' => $id,
'tab' => 'tab_manage'
'tab' => 'tab_manage',
]);
}
}
@ -514,27 +520,31 @@ class ServersController extends Controller
{
try {
$repo = new ServerRepository;
if (!is_null($request->input('cancel'))) {
if (! is_null($request->input('cancel'))) {
$repo->cancelDeletion($id);
Alert::success('Server deletion has been cancelled. This server will remain suspended until you unsuspend it.')->flash();
return redirect()->route('admin.servers.view', $id);
} else if(!is_null($request->input('delete'))) {
} elseif (! is_null($request->input('delete'))) {
$repo->deleteNow($id);
Alert::success('Server was successfully deleted from the system.')->flash();
return redirect()->route('admin.servers');
} else if(!is_null($request->input('force_delete'))) {
} elseif (! is_null($request->input('force_delete'))) {
$repo->deleteNow($id, true);
Alert::success('Server was successfully force deleted from the system.')->flash();
return redirect()->route('admin.servers');
}
} catch (DisplayException $ex) {
Alert::danger($ex->getMessage())->flash();
return redirect()->route('admin.servers.view', $id);
} catch (\Exception $ex) {
Log::error($ex);
Alert::danger('An unhandled error occured while attempting to perform this action.')->flash();
return redirect()->route('admin.servers.view', $id);
}
}
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,24 +21,22 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Http\Controllers\Admin;
use Alert;
use DB;
use Log;
use Validator;
use Alert;
use Storage;
use Pterodactyl\Models;
use Pterodactyl\Repositories\ServiceRepository;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Exceptions\DisplayValidationException;
use Pterodactyl\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Http\Controllers\Controller;
use Pterodactyl\Repositories\ServiceRepository;
use Pterodactyl\Exceptions\DisplayValidationException;
class ServiceController extends Controller
{
public function __construct()
{
//
@ -50,7 +48,7 @@ class ServiceController extends Controller
'services' => Models\Service::select(
'services.*',
DB::raw('(SELECT COUNT(*) FROM servers WHERE servers.service = services.id) as c_servers')
)->get()
)->get(),
]);
}
@ -64,9 +62,10 @@ class ServiceController extends Controller
try {
$repo = new ServiceRepository\Service;
$id = $repo->create($request->except([
'_token'
'_token',
]));
Alert::success('Successfully created new service!')->flash();
return redirect()->route('admin.services.service', $id);
} catch (DisplayValidationException $ex) {
return redirect()->route('admin.services.new')->withErrors(json_decode($ex->getMessage()))->withInput();
@ -76,6 +75,7 @@ class ServiceController extends Controller
Log::error($ex);
Alert::danger('An error occured while attempting to add a new service.')->flash();
}
return redirect()->route('admin.services.new')->withInput();
}
@ -86,7 +86,7 @@ class ServiceController extends Controller
'options' => Models\ServiceOptions::select(
'service_options.*',
DB::raw('(SELECT COUNT(*) FROM servers WHERE servers.option = service_options.id) as c_servers')
)->where('parent_service', $service)->get()
)->where('parent_service', $service)->get(),
]);
}
@ -95,7 +95,7 @@ class ServiceController extends Controller
try {
$repo = new ServiceRepository\Service;
$repo->update($service, $request->except([
'_token'
'_token',
]));
Alert::success('Successfully updated this service.')->flash();
} catch (DisplayValidationException $ex) {
@ -106,6 +106,7 @@ class ServiceController extends Controller
Log::error($ex);
Alert::danger('An error occurred while attempting to update this service.')->flash();
}
return redirect()->route('admin.services.service', $service)->withInput();
}
@ -115,6 +116,7 @@ class ServiceController extends Controller
$repo = new ServiceRepository\Service;
$repo->delete($service);
Alert::success('Successfully deleted that service.')->flash();
return redirect()->route('admin.services');
} catch (DisplayException $ex) {
Alert::danger($ex->getMessage())->flash();
@ -122,12 +124,14 @@ class ServiceController extends Controller
Log::error($ex);
Alert::danger('An error was encountered while attempting to delete that service.')->flash();
}
return redirect()->route('admin.services.service', $service);
}
public function getOption(Request $request, $service, $option)
{
$opt = Models\ServiceOptions::findOrFail($option);
return view('admin.services.options.view', [
'service' => Models\Service::findOrFail($opt->parent_service),
'option' => $opt,
@ -135,7 +139,7 @@ class ServiceController extends Controller
'servers' => Models\Server::select('servers.*', 'users.email as a_ownerEmail')
->join('users', 'users.id', '=', 'servers.owner')
->where('option', $option)
->paginate(10)
->paginate(10),
]);
}
@ -144,7 +148,7 @@ class ServiceController extends Controller
try {
$repo = new ServiceRepository\Option;
$repo->update($option, $request->except([
'_token'
'_token',
]));
Alert::success('Option settings successfully updated.')->flash();
} catch (DisplayValidationException $ex) {
@ -153,6 +157,7 @@ class ServiceController extends Controller
Log::error($ex);
Alert::danger('An error occured while attempting to modify this option.')->flash();
}
return redirect()->route('admin.services.option', [$service, $option])->withInput();
}
@ -164,6 +169,7 @@ class ServiceController extends Controller
$repo->delete($option);
Alert::success('Successfully deleted that option.')->flash();
return redirect()->route('admin.services.service', $service->parent_service);
} catch (DisplayException $ex) {
Alert::danger($ex->getMessage())->flash();
@ -171,6 +177,7 @@ class ServiceController extends Controller
Log::error($ex);
Alert::danger('An error was encountered while attempting to delete this option.')->flash();
}
return redirect()->route('admin.services.option', [$service, $option]);
}
@ -184,18 +191,19 @@ class ServiceController extends Controller
$data = [
'user_viewable' => '0',
'user_editable' => '0',
'required' => '0'
'required' => '0',
];
foreach($request->except(['_token']) as $id => $val) {
$data[str_replace($variable.'_', '', $id)] = $val;
foreach ($request->except(['_token']) as $id => $val) {
$data[str_replace($variable . '_', '', $id)] = $val;
}
$repo->update($variable, $data);
Alert::success('Successfully updated variable.')->flash();
} catch (DisplayValidationException $ex) {
$data = [];
foreach(json_decode($ex->getMessage(), true) as $id => $val) {
$data[$variable.'_'.$id] = $val;
foreach (json_decode($ex->getMessage(), true) as $id => $val) {
$data[$variable . '_' . $id] = $val;
}
return redirect()->route('admin.services.option', [$service, $option])->withErrors((object) $data)->withInput();
} catch (DisplayException $ex) {
Alert::danger($ex->getMessage())->flash();
@ -203,6 +211,7 @@ class ServiceController extends Controller
Log::error($ex);
Alert::danger('An error occurred while attempting to update this service.')->flash();
}
return redirect()->route('admin.services.option', [$service, $option])->withInput();
}
@ -210,7 +219,7 @@ class ServiceController extends Controller
{
return view('admin.services.options.variable', [
'service' => Models\Service::findOrFail($service),
'option' => Models\ServiceOptions::where('parent_service', $service)->where('id', $option)->firstOrFail()
'option' => Models\ServiceOptions::where('parent_service', $service)->where('id', $option)->firstOrFail(),
]);
}
@ -219,10 +228,11 @@ class ServiceController extends Controller
try {
$repo = new ServiceRepository\Variable;
$repo->create($option, $request->except([
'_token'
'_token',
]));
Alert::success('Successfully added new variable to this option.')->flash();
return redirect()->route('admin.services.option', [$service, $option])->withInput();
return redirect()->route('admin.services.option', [$service, $option]);
} catch (DisplayValidationException $ex) {
return redirect()->route('admin.services.option.variable.new', [$service, $option])->withErrors(json_decode($ex->getMessage()))->withInput();
} catch (DisplayException $ex) {
@ -231,6 +241,7 @@ class ServiceController extends Controller
Log::error($ex);
Alert::danger('An error occurred while attempting to add this variable.')->flash();
}
return redirect()->route('admin.services.option.variable.new', [$service, $option])->withInput();
}
@ -246,9 +257,10 @@ class ServiceController extends Controller
try {
$repo = new ServiceRepository\Option;
$id = $repo->create($service, $request->except([
'_token'
'_token',
]));
Alert::success('Successfully created new service option.')->flash();
return redirect()->route('admin.services.option', [$service, $id]);
} catch (DisplayValidationException $ex) {
return redirect()->route('admin.services.option.new', $service)->withErrors(json_decode($ex->getMessage()))->withInput();
@ -256,6 +268,7 @@ class ServiceController extends Controller
Log::error($ex);
Alert::danger('An error occured while attempting to add this service option.')->flash();
}
return redirect()->route('admin.services.option.new', $service)->withInput();
}
@ -271,7 +284,42 @@ class ServiceController extends Controller
Log::error($ex);
Alert::danger('An error occured while attempting to delete that variable.')->flash();
}
return redirect()->route('admin.services.option', [$service, $option]);
}
public function getConfiguration(Request $request, $serviceId)
{
$service = Models\Service::findOrFail($serviceId);
return view('admin.services.config', [
'service' => $service,
'contents' => [
'json' => Storage::get('services/' . $service->file . '/main.json'),
'index' => Storage::get('services/' . $service->file . '/index.js'),
],
]);
}
public function postConfiguration(Request $request, $serviceId)
{
try {
$repo = new ServiceRepository\Service;
$repo->updateFile($serviceId, $request->except([
'_token',
]));
return response('', 204);
} catch (DisplayException $ex) {
return response()->json([
'error' => $ex->getMessage(),
], 503);
} catch (\Exception $ex) {
Log::error($ex);
return response()->json([
'error' => 'An error occured while attempting to save the file.',
], 503);
}
}
}

View file

@ -1,8 +1,8 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* Some Modifications (c) 2015 Dylan Seidt <dylan.seidt@gmail.com>
* 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
@ -22,27 +22,23 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Http\Controllers\Admin;
use Alert;
use Settings;
use Mail;
use Log;
use Pterodactyl\Models\User;
use Pterodactyl\Repositories\UserRepository;
use Pterodactyl\Models\Server;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Exceptions\DisplayValidationException;
use Pterodactyl\Http\Controllers\Controller;
use Alert;
use Illuminate\Http\Request;
use Pterodactyl\Models\User;
use Pterodactyl\Models\Server;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Http\Controllers\Controller;
use Pterodactyl\Repositories\UserRepository;
use Pterodactyl\Exceptions\DisplayValidationException;
class UserController extends Controller
{
/**
* Controller Constructor
* Controller Constructor.
*/
public function __construct()
{
@ -51,8 +47,33 @@ class UserController extends Controller
public function getIndex(Request $request)
{
$query = User::select('users.*');
if ($request->input('filter') && ! is_null($request->input('filter'))) {
preg_match_all('/[^\s"\']+|"([^"]*)"|\'([^\']*)\'/', urldecode($request->input('filter')), $matches);
foreach ($matches[0] as $match) {
$match = str_replace('"', '', $match);
if (strpos($match, ':')) {
list($field, $term) = explode(':', $match);
$query->orWhere($field, 'LIKE', '%' . $term . '%');
} else {
$query->where('email', 'LIKE', '%' . $match . '%');
$query->orWhere([
['uuid', 'LIKE', '%' . $match . '%'],
['root_admin', 'LIKE', '%' . $match . '%'],
]);
}
}
}
try {
$users = $query->paginate(20);
} catch (\Exception $ex) {
Alert::warning('There was an error with the search parameters provided.');
$users = User::all()->paginate(20);
}
return view('admin.users.index', [
'users' => User::paginate(20)
'users' => $users,
]);
}
@ -79,13 +100,15 @@ class UserController extends Controller
$repo = new UserRepository;
$repo->delete($id);
Alert::success('Successfully deleted user from system.')->flash();
return redirect()->route('admin.users');
} catch(DisplayException $ex) {
} catch (DisplayException $ex) {
Alert::danger($ex->getMessage())->flash();
} catch (\Exception $ex) {
Log::error($ex);
Alert::danger('An exception was encountered while attempting to delete this user.')->flash();
}
return redirect()->route('admin.users.view', $id);
}
@ -93,33 +116,39 @@ class UserController extends Controller
{
try {
$user = new UserRepository;
$userid = $user->create($request->input('email'), $request->input('password'));
$userid = $user->create($request->only([
'email',
'password',
'name_first',
'name_last',
'username',
'root_admin',
]));
Alert::success('Account has been successfully created.')->flash();
return redirect()->route('admin.users.view', $userid);
} catch (DisplayValidationException $ex) {
return redirect()->route('admin.users.new')->withErrors(json_decode($ex->getMessage()))->withInput();
} catch (\Exception $ex) {
Log::error($ex);
Alert::danger('An error occured while attempting to add a new user.')->flash();
return redirect()->route('admin.users.new');
}
}
public function updateUser(Request $request, $user)
{
$data = [
'email' => $request->input('email'),
'root_admin' => $request->input('root_admin'),
'password_confirmation' => $request->input('password_confirmation'),
];
if ($request->input('password')) {
$data['password'] = $request->input('password');
}
try {
$repo = new UserRepository;
$repo->update($user, $data);
$repo->update($user, $request->only([
'email',
'password',
'name_first',
'name_last',
'username',
'root_admin',
]));
Alert::success('User account was successfully updated.')->flash();
} catch (DisplayValidationException $ex) {
return redirect()->route('admin.users.view', $user)->withErrors(json_decode($ex->getMessage()));
@ -127,15 +156,16 @@ class UserController extends Controller
Log::error($e);
Alert::danger('An error occured while attempting to update this user.')->flash();
}
return redirect()->route('admin.users.view', $user);
}
public function getJson(Request $request)
{
foreach(User::select('email')->get() as $user) {
foreach (User::select('email')->get() as $user) {
$resp[] = $user->email;
}
return $resp;
}
}

View file

@ -1,8 +1,8 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* Some Modifications (c) 2015 Dylan Seidt <dylan.seidt@gmail.com>
* 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
@ -22,20 +22,15 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Http\Controllers\Auth;
use Pterodactyl\Models\User;
namespace Pterodactyl\Http\Controllers\Auth;
use Auth;
use Alert;
use Validator;
use Pterodactyl\Http\Controllers\Controller;
use PragmaRX\Google2FA\Google2FA;
use Illuminate\Http\Request;
use Illuminate\Foundation\Auth\ThrottlesLogins;
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;
use Pterodactyl\Models\User;
use PragmaRX\Google2FA\Google2FA;
use Pterodactyl\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
class LoginController extends Controller
@ -62,14 +57,14 @@ class LoginController extends Controller
/**
* Lockout time for failed login requests.
*
* @var integer
* @var int
*/
protected $lockoutTime = 120;
/**
* After how many attempts should logins be throttled and locked.
*
* @var integer
* @var int
*/
protected $maxLoginAttempts = 3;
@ -91,7 +86,6 @@ class LoginController extends Controller
*/
public function login(Request $request)
{
$this->validate($request, [
'email' => 'required|email',
'password' => 'required',
@ -99,44 +93,40 @@ class LoginController extends Controller
if ($lockedOut = $this->hasTooManyLoginAttempts($request)) {
$this->fireLockoutEvent($request);
return $this->sendLockoutResponse($request);
}
// Is the email & password valid?
if (!Auth::attempt([
if (! Auth::once([
'email' => $request->input('email'),
'password' => $request->input('password')
'password' => $request->input('password'),
], $request->has('remember'))) {
if (!$lockedOut) {
if (! $lockedOut) {
$this->incrementLoginAttempts($request);
}
return $this->sendFailedLoginResponse($request);
}
$G2FA = new Google2FA();
$user = User::select('use_totp', 'totp_secret')->where('email', $request->input('email'))->first();
// Verify TOTP Token was Valid
if($user->use_totp === 1) {
if(!$G2FA->verifyKey($user->totp_secret, $request->input('totp_token'))) {
Auth::logout();
if (!$lockedOut) {
if (Auth::user()->use_totp === 1) {
$G2FA = new Google2FA();
if (is_null($request->input('totp_token')) || ! $G2FA->verifyKey(Auth::user()->totp_secret, $request->input('totp_token'))) {
if (! $lockedOut) {
$this->incrementLoginAttempts($request);
}
Alert::danger(trans('auth.totp_failed'))->flash();
return $this->sendFailedLoginResponse($request);
return $this->sendFailedLoginResponse($request);
}
}
return $this->sendLoginResponse($request);
// Successfully Authenticated.
Auth::login(Auth::user(), $request->has('remember'));
return $this->sendLoginResponse($request);
}
/**
@ -149,5 +139,4 @@ class LoginController extends Controller
{
return response()->json(User::select('id')->where('email', $request->input('email'))->where('use_totp', 1)->first());
}
}

View file

@ -2,8 +2,8 @@
namespace Pterodactyl\Http\Controllers\Auth;
use Pterodactyl\User;
use Validator;
use Pterodactyl\User;
use Pterodactyl\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\RegistersUsers;

View file

@ -33,8 +33,8 @@ class ResetPasswordController extends Controller
$this->middleware('guest');
}
protected function rules() {
protected function rules()
{
return [
'token' => 'required', 'email' => 'required|email',
'password' => 'required|confirmed|' . User::PASSWORD_RULES,

View file

@ -1,8 +1,8 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* Some Modifications (c) 2015 Dylan Seidt <dylan.seidt@gmail.com>
* 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
@ -22,35 +22,33 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Http\Controllers\Base;
use Alert;
use Log;
use Alert;
use Pterodactyl\Models;
use Illuminate\Http\Request;
use Pterodactyl\Repositories\APIRepository;
use Pterodactyl\Exceptions\DisplayValidationException;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Pterodactyl\Exceptions\DisplayValidationException;
class APIController extends Controller
{
public function index(Request $request)
{
$keys = Models\APIKey::where('user', $request->user()->id)->get();
foreach($keys as &$key) {
foreach ($keys as &$key) {
$key->permissions = Models\APIPermission::where('key_id', $key->id)->get();
}
return view('base.api.index', [
'keys' => $keys
'keys' => $keys,
]);
}
public function new(Request $request)
public function create(Request $request)
{
return view('base.api.new');
}
@ -59,8 +57,9 @@ class APIController extends Controller
{
try {
$repo = new APIRepository($request->user());
$secret = $repo->new($request->except(['_token']));
$secret = $repo->create($request->except(['_token']));
Alert::success('An API Keypair has successfully been generated. The API secret for this public key is shown below and will not be shown again.<br /><br /><code>' . $secret . '</code>')->flash();
return redirect()->route('account.api');
} catch (DisplayValidationException $ex) {
return redirect()->route('account.api.new')->withErrors(json_decode($ex->getMessage()))->withInput();
@ -70,6 +69,7 @@ class APIController extends Controller
Log::error($ex);
Alert::danger('An unhandled exception occured while attempting to add this API key.')->flash();
}
return redirect()->route('account.api.new')->withInput();
}
@ -78,10 +78,11 @@ class APIController extends Controller
try {
$repo = new APIRepository($request->user());
$repo->revoke($key);
return response('', 204);
} catch (\Exception $ex) {
return response()->json([
'error' => 'An error occured while attempting to remove this key.'
'error' => 'An error occured while attempting to remove this key.',
], 503);
}
}

View file

@ -1,8 +1,8 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* Some Modifications (c) 2015 Dylan Seidt <dylan.seidt@gmail.com>
* 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
@ -22,15 +22,16 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Http\Controllers\Base;
use Log;
use Alert;
use Pterodactyl\Models\User;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Pterodactyl\Models\User;
use Pterodactyl\Http\Controllers\Controller;
use Pterodactyl\Repositories\UserRepository;
use Pterodactyl\Exceptions\DisplayValidationException;
class AccountController extends Controller
{
@ -46,64 +47,57 @@ class AccountController extends Controller
}
/**
* Update an account email.
*
* Update details for a users account.
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
* @return void
*/
public function email(Request $request)
public function update(Request $request)
{
$data = [];
$this->validate($request, [
'new_email' => 'required|email',
'password' => 'required'
]);
// Request to update account Password
if ($request->input('do_action') === 'password') {
$this->validate($request, [
'current_password' => 'required',
'new_password' => 'required|confirmed|' . User::PASSWORD_RULES,
'new_password_confirmation' => 'required',
]);
$user = $request->user();
$data['password'] = $request->input('new_password');
if (!password_verify($request->input('password'), $user->password)) {
Alert::danger('The password provided was not valid for this account.')->flash();
return redirect()->route('account');
// Request to update account Email
} elseif ($request->input('do_action') === 'email') {
$data['email'] = $request->input('new_email');
// Request to update account Identity
} elseif ($request->input('do_action') === 'identity') {
$data = $request->only(['name_first', 'name_last', 'username']);
// Unknown, hit em with a 404
} else {
return abort(404);
}
$user->email = $request->input('new_email');
$user->save();
if (
in_array($request->input('do_action'), ['email', 'password'])
&& ! password_verify($request->input('password'), $request->user()->password)
) {
Alert::danger(trans('base.account.invalid_pass'))->flash();
Alert::success('Your email address has successfully been updated.')->flash();
return redirect()->route('account');
}
/**
* Update an account password.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function password(Request $request)
{
$this->validate($request, [
'current_password' => 'required',
'new_password' => 'required|confirmed|different:current_password|' . User::PASSWORD_RULES,
'new_password_confirmation' => 'required'
]);
$user = $request->user();
if (!password_verify($request->input('current_password'), $user->password)) {
Alert::danger('The password provided was not valid for this account.')->flash();
return redirect()->route('account');
}
try {
$user->setPassword($request->input('new_password'));
Alert::success('Your password has successfully been updated.')->flash();
} catch (DisplayException $e) {
Alert::danger($e->getMessage())->flash();
$repo = new UserRepository;
$repo->update($request->user()->id, $data);
Alert::success('Your account details were successfully updated.')->flash();
} catch (DisplayValidationException $ex) {
return redirect()->route('account')->withErrors(json_decode($ex->getMessage()));
} catch (\Exception $ex) {
Log::error($ex);
Alert::danger(trans('base.account.exception'))->flash();
}
return redirect()->route('account');
}
}

View file

@ -1,8 +1,8 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* Some Modifications (c) 2015 Dylan Seidt <dylan.seidt@gmail.com>
* 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
@ -22,18 +22,17 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Http\Controllers\Base;
use Illuminate\Http\Request;
use Pterodactyl\Models\Server;
use Pterodactyl\Http\Controllers\Controller;
use Illuminate\Http\Request;
class IndexController extends Controller
{
/**
* Controller Constructor
* Controller Constructor.
*/
public function __construct()
{
@ -62,7 +61,15 @@ class IndexController extends Controller
public function getPassword(Request $request, $length = 16)
{
$length = ($length < 8) ? 8 : $length;
return str_random($length);
}
$returnable = false;
while (! $returnable) {
$generated = str_random($length);
if (preg_match('/[A-Z]+[a-z]+[0-9]+/', $generated)) {
$returnable = true;
}
}
return $generated;
}
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,33 +21,30 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Http\Controllers\Base;
use Auth;
use Session;
use Pterodactyl\Models\User;
use Illuminate\Http\Request;
use Pterodactyl\Models\User;
use Pterodactyl\Http\Controllers\Controller;
class LanguageController extends Controller
{
protected $languages = [
'de' => 'Danish',
'de' => 'German',
'en' => 'English',
'es' => 'Spanish',
'fr' => 'French',
'it' => 'Italian',
'pl' => 'Polish',
'et' => 'Estonian',
'nb' => 'Norwegian',
'nl' => 'Dutch',
'pt' => 'Portuguese',
'ro' => 'Romanian',
'ru' => 'Russian',
'se' => 'Swedish',
'zh' => 'Chinese',
];
/**
* Controller Constructor
* Controller Constructor.
*/
public function __construct()
{
@ -64,7 +61,7 @@ class LanguageController extends Controller
}
Session::set('applocale', $language);
}
return redirect()->back();
}
}

View file

@ -1,8 +1,8 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* Some Modifications (c) 2015 Dylan Seidt <dylan.seidt@gmail.com>
* 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
@ -22,19 +22,17 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Http\Controllers\Base;
use Google2FA;
use Alert;
use Google2FA;
use Illuminate\Http\Request;
use Pterodactyl\Models\Session;
use Pterodactyl\Http\Controllers\Controller;
use Illuminate\Http\Request;
class SecurityController extends Controller
{
/**
* Returns Security Management Page.
*
@ -44,7 +42,7 @@ class SecurityController extends Controller
public function index(Request $request)
{
return view('base.security', [
'sessions' => Session::where('user_id', $request->user()->id)->get()
'sessions' => Session::where('user_id', $request->user()->id)->get(),
]);
}
@ -57,7 +55,6 @@ class SecurityController extends Controller
*/
public function generateTotp(Request $request)
{
$user = $request->user();
$user->totp_secret = Google2FA::generateSecretKey();
@ -69,9 +66,8 @@ class SecurityController extends Controller
$user->email,
$user->totp_secret
),
'secret' => $user->totp_secret
'secret' => $user->totp_secret,
]);
}
/**
@ -82,18 +78,18 @@ class SecurityController extends Controller
*/
public function setTotp(Request $request)
{
if (!$request->has('token')) {
return response(null, 500);
if (! $request->has('token')) {
return response()->json([
'error' => 'Request is missing token parameter.',
], 500);
}
$user = $request->user();
if($user->toggleTotp($request->input('token'))) {
if ($user->toggleTotp($request->input('token'))) {
return response('true');
}
return response('false');
}
/**
@ -104,27 +100,27 @@ class SecurityController extends Controller
*/
public function disableTotp(Request $request)
{
if (!$request->has('token')) {
if (! $request->has('token')) {
Alert::danger('Missing required `token` field in request.')->flash();
return redirect()->route('account.totp');
return redirect()->route('account.security');
}
$user = $request->user();
if($user->toggleTotp($request->input('token'))) {
if ($user->toggleTotp($request->input('token'))) {
return redirect()->route('account.security');
}
Alert::danger('The TOTP token provided was invalid.')->flash();
return redirect()->route('account.security');
return redirect()->route('account.security');
}
public function revoke(Request $request, $id)
{
$session = Session::where('id', $id)->where('user_id', $request->user()->id)->firstOrFail();
$session->delete();
return redirect()->route('account.security');
}
}

View file

@ -0,0 +1,95 @@
<?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\Http\Controllers\Daemon;
use Storage;
use Pterodactyl\Models;
use Illuminate\Http\Request;
use Pterodactyl\Http\Controllers\Controller;
class PackController extends Controller
{
/**
* Controller Constructor.
*/
public function __construct()
{
//
}
/**
* Pulls an install pack archive from the system.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function pull(Request $request, $uuid)
{
$pack = Models\ServicePack::where('uuid', $uuid)->first();
if (! $pack) {
return response()->json(['error' => 'No such pack.'], 404);
}
if (! Storage::exists('packs/' . $pack->uuid . '/archive.tar.gz')) {
return response()->json(['error' => 'There is no archive available for this pack.'], 503);
}
return response()->download(storage_path('app/packs/' . $pack->uuid . '/archive.tar.gz'));
}
/**
* Returns the hash information for a pack.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function hash(Request $request, $uuid)
{
$pack = Models\ServicePack::where('uuid', $uuid)->first();
if (! $pack) {
return response()->json(['error' => 'No such pack.'], 404);
}
if (! Storage::exists('packs/' . $pack->uuid . '/archive.tar.gz')) {
return response()->json(['error' => 'There is no archive available for this pack.'], 503);
}
return response()->json([
'archive.tar.gz' => sha1_file(storage_path('app/packs/' . $pack->uuid . '/archive.tar.gz')),
]);
}
/**
* Pulls an update pack archive from the system.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function pullUpdate(Request $request)
{
}
}

View file

@ -0,0 +1,79 @@
<?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\Http\Controllers\Daemon;
use Storage;
use Pterodactyl\Models;
use Illuminate\Http\Request;
use Pterodactyl\Http\Controllers\Controller;
class ServiceController extends Controller
{
/**
* Controller Constructor.
*/
public function __construct()
{
//
}
/**
* Returns a listing of all services currently on the system,
* as well as the associated files and the file hashes for
* caching purposes.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function list(Request $request)
{
$response = [];
foreach (Models\Service::all() as &$service) {
$response[$service->file] = [
'main.json' => sha1_file(storage_path('app/services/' . $service->file . '/main.json')),
'index.js' => sha1_file(storage_path('app/services/' . $service->file . '/index.js')),
];
}
return response()->json($response);
}
/**
* Returns the contents of the requested file for the given service.
*
* @param \Illuminate\Http\Request $request
* @param string $service
* @param string $file
* @return \Illuminate\Http\Response
*/
public function pull(Request $request, $service, $file)
{
if (! Storage::exists('services/' . $service . '/' . $file)) {
return response()->json(['error' => 'No such file.'], 404);
}
return response()->file(storage_path('app/services/' . $service . '/' . $file));
}
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,47 +21,48 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Http\Controllers\Remote;
use Carbon\Carbon;
use Pterodactyl\Models;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Services\NotificationService;
use Pterodactyl\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Pterodactyl\Http\Controllers\Controller;
use Pterodactyl\Services\NotificationService;
class RemoteController extends Controller
{
/**
* Controller Constructor
* Controller Constructor.
*/
public function __construct()
{
// No middleware for this route.
}
public function postDownload(Request $request) {
public function postDownload(Request $request)
{
$download = Models\Download::where('token', $request->input('token', '00'))->first();
if (!$download) {
if (! $download) {
return response()->json([
'error' => 'An invalid request token was recieved with this request.'
'error' => 'An invalid request token was recieved with this request.',
], 403);
}
$download->delete();
return response()->json([
'path' => $download->path,
'server' => $download->server
'server' => $download->server,
]);
}
public function postInstall(Request $request)
{
$server = Models\Server::where('uuid', $request->input('server'))->first();
if (!$server) {
if (! $server) {
return response()->json([
'error' => 'No server by that ID was found on the system.'
'error' => 'No server by that ID was found on the system.',
], 422);
}
@ -71,7 +72,7 @@ class RemoteController extends Controller
if (base64_decode($hmac) !== hash_hmac('sha256', $server->uuid, $node->daemonSecret, true)) {
return response()->json([
'error' => 'Signed HMAC was invalid.'
'error' => 'Signed HMAC was invalid.',
], 403);
}
@ -79,16 +80,16 @@ class RemoteController extends Controller
$server->save();
return response()->json([
'message' => 'Recieved!'
'message' => 'Recieved!',
], 200);
}
public function event(Request $request)
{
$server = Models\Server::where('uuid', $request->input('server'))->first();
if (!$server) {
if (! $server) {
return response()->json([
'error' => 'No server by that ID was found on the system.'
'error' => 'No server by that ID was found on the system.',
], 422);
}
@ -97,7 +98,7 @@ class RemoteController extends Controller
$hmac = $request->input('signed');
if (base64_decode($hmac) !== hash_hmac('sha256', $server->uuid, $node->daemonSecret, true)) {
return response()->json([
'error' => 'Signed HMAC was invalid.'
'error' => 'Signed HMAC was invalid.',
], 403);
}
@ -108,4 +109,28 @@ class RemoteController extends Controller
return response('', 201);
}
public function getConfiguration(Request $request, $tokenString)
{
// Try to query the token and the node from the database
try {
$token = Models\NodeConfigurationToken::where('token', $tokenString)->firstOrFail();
$node = Models\Node::findOrFail($token->node);
} catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
return response()->json(['error' => 'token_invalid'], 403);
}
// Check if token is expired
if ($token->expires_at->lt(Carbon::now())) {
$token->delete();
return response()->json(['error' => 'token_expired'], 403);
}
// Delete the token, it's one-time use
$token->delete();
// Manually as getConfigurationAsJson() returns it in correct format already
return response($node->getConfigurationAsJson(), 200)
->header('Content-Type', 'application/json');
}
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,24 +21,20 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Http\Controllers\Server;
use Log;
use Pterodactyl\Models;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Exceptions\DisplayValidationException;
use Pterodactyl\Repositories;
use Pterodactyl\Http\Controllers\Controller;
use Illuminate\Http\Request;
use GuzzleHttp\Client;
use Pterodactyl\Repositories;
use GuzzleHttp\Exception\RequestException;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Http\Controllers\Controller;
use Pterodactyl\Exceptions\DisplayValidationException;
class AjaxController extends Controller
{
/**
* @var array
*/
@ -55,7 +51,7 @@ class AjaxController extends Controller
protected $directory;
/**
* Controller Constructor
* Controller Constructor.
*/
public function __construct()
{
@ -73,7 +69,7 @@ class AjaxController extends Controller
{
$server = Models\Server::getByUUID($uuid);
if (!$server) {
if (! $server) {
return response()->json([], 404);
}
@ -81,14 +77,15 @@ class AjaxController extends Controller
try {
$res = $client->request('GET', '/server', [
'headers' => Models\Server::getGuzzleHeaders($uuid)
'headers' => Models\Server::getGuzzleHeaders($uuid),
]);
if($res->getStatusCode() === 200) {
if ($res->getStatusCode() === 200) {
return response()->json(json_decode($res->getBody()));
}
} catch (RequestException $e) {
//
}
return response()->json([]);
}
@ -101,13 +98,12 @@ class AjaxController extends Controller
*/
public function postDirectoryList(Request $request, $uuid)
{
$server = Models\Server::getByUUID($uuid);
$this->directory = '/' . trim(urldecode($request->input('directory', '/')), '/');
$this->authorize('list-files', $server);
$prevDir = [
'header' => ($this->directory !== '/') ? $this->directory : ''
'header' => ($this->directory !== '/') ? $this->directory : '',
];
if ($this->directory !== '/') {
$prevDir['first'] = true;
@ -116,7 +112,7 @@ class AjaxController extends Controller
// Determine if we should show back links in the file browser.
// This code is strange, and could probably be rewritten much better.
$goBack = explode('/', trim($this->directory, '/'));
if (!empty(array_filter($goBack)) && count($goBack) >= 2) {
if (! empty(array_filter($goBack)) && count($goBack) >= 2) {
$prevDir['show'] = true;
array_pop($goBack);
$prevDir['link'] = '/' . implode('/', $goBack);
@ -131,6 +127,7 @@ class AjaxController extends Controller
return response($ex->getMessage(), 500);
} catch (\Exception $ex) {
Log::error($ex);
return response('An error occured while attempting to load the requested directory, please try again.', 500);
}
@ -139,9 +136,8 @@ class AjaxController extends Controller
'files' => $directoryContents->files,
'folders' => $directoryContents->folders,
'editableMime' => Repositories\HelperRepository::editableFiles(),
'directory' => $prevDir
'directory' => $prevDir,
]);
}
/**
@ -153,7 +149,6 @@ class AjaxController extends Controller
*/
public function postSaveFile(Request $request, $uuid)
{
$server = Models\Server::getByUUID($uuid);
$this->authorize('save-files', $server);
@ -161,39 +156,39 @@ class AjaxController extends Controller
try {
$controller->saveFileContents($request->input('file'), $request->input('contents'));
return response(null, 204);
} catch (DisplayException $ex) {
return response($ex->getMessage(), 500);
} catch (\Exception $ex) {
Log::error($ex);
return response('An error occured while attempting to save this file, please try again.', 500);
}
}
/**
* [postSetPrimary description]
* [postSetPrimary description].
* @param Request $request
* @param string $uuid
* @return \Illuminate\Http\Response
*/
public function postSetPrimary(Request $request, $uuid)
{
$server = Models\Server::getByUUID($uuid);
$this->authorize('set-connection', $server);
if ((int) $request->input('allocation') === $server->allocation) {
return response()->json([
'error' => 'You are already using this as your default connection.'
'error' => 'You are already using this as your default connection.',
], 409);
}
try {
$allocation = Models\Allocation::where('id', $request->input('allocation'))->where('assigned_to', $server->id)->first();
if (!$allocation) {
if (! $allocation) {
return response()->json([
'error' => 'No allocation matching your request was found in the system.'
'error' => 'No allocation matching your request was found in the system.',
], 422);
}
@ -201,6 +196,7 @@ class AjaxController extends Controller
$repo->changeBuild($server->id, [
'default' => $allocation->ip . ':' . $allocation->port,
]);
return response('The default connection for this server has been updated. Please be aware that you will need to restart your server for this change to go into effect.');
} catch (DisplayValidationException $ex) {
return response()->json([
@ -212,8 +208,9 @@ class AjaxController extends Controller
], 503);
} catch (\Exception $ex) {
Log::error($ex);
return response()->json([
'error' => 'An unhandled exception occured while attemping to modify the default connection for this server.'
'error' => 'An unhandled exception occured while attemping to modify the default connection for this server.',
], 503);
}
}
@ -225,21 +222,21 @@ class AjaxController extends Controller
$this->authorize('reset-db-password', $server);
try {
$repo = new Repositories\DatabaseRepository;
$password = str_random(16);
$repo->modifyPassword($request->input('database'), $password);
return response($password);
} catch (\Pterodactyl\Exceptions\DisplayException $ex) {
return response()->json([
'error' => $ex->getMessage(),
], 503);
} catch(\Exception $ex) {
} catch (\Exception $ex) {
Log::error($ex);
return response()->json([
'error' => 'An unhandled error occured while attempting to modify this database\'s password.'
'error' => 'An unhandled error occured while attempting to modify this database\'s password.',
], 503);
}
}
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,30 +21,26 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Http\Controllers\Server;
use Auth;
use DB;
use Log;
use Uuid;
use Alert;
use Log;
use Javascript;
use Pterodactyl\Models;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Exceptions\DisplayValidationException;
use Pterodactyl\Repositories\Daemon\FileRepository;
use Pterodactyl\Repositories\ServerRepository;
use Pterodactyl\Http\Controllers\Controller;
use Illuminate\Http\Request;
use InvalidArgumentException;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Http\Controllers\Controller;
use Pterodactyl\Repositories\ServerRepository;
use Pterodactyl\Repositories\Daemon\FileRepository;
use Pterodactyl\Exceptions\DisplayValidationException;
class ServerController extends Controller
{
/**
* Controller Constructor
* Controller Constructor.
*
* @return void
*/
@ -53,24 +49,6 @@ class ServerController extends Controller
//
}
public function getJavascript(Request $request, $uuid, $folder, $file)
{
$server = Models\Server::getByUUID($uuid);
$info = pathinfo($file);
$routeFile = str_replace('/', '.', $info['dirname']) . '.' . $info['filename'];
try {
return response()->view('server.js.' . $folder . '.' . $routeFile, [
'server' => $server,
'node' => Models\Node::find($server->node)
])->header('Content-Type', 'application/javascript');
} catch (InvalidArgumentException $ex) {
return abort(404);
} catch (\Exception $ex) {
throw $ex;
}
}
/**
* Renders server index page for specified server.
*
@ -80,10 +58,20 @@ class ServerController extends Controller
public function getIndex(Request $request)
{
$server = Models\Server::getByUUID($request->route()->server);
$node = Models\Node::find($server->node);
Javascript::put([
'server' => collect($server->makeVisible('daemonSecret'))->only(['uuid', 'daemonSecret', 'username']),
'node' => collect($node)->only('fqdn', 'scheme', 'daemonListen'),
'meta' => [
'saveFile' => route('server.files.save', $server->uuidShort),
'csrfToken' => csrf_token(),
],
]);
return view('server.index', [
'server' => $server,
'allocations' => Models\Allocation::where('assigned_to', $server->id)->orderBy('ip', 'asc')->orderBy('port', 'asc')->get(),
'node' => Models\Node::find($server->node)
'node' => $node,
]);
}
@ -93,15 +81,34 @@ class ServerController extends Controller
* @param Request $request
* @return \Illuminate\Contracts\View\View
*/
public function getFiles(Request $request)
public function getFiles(Request $request, $uuid)
{
$server = Models\Server::getByUUID($request->route()->server);
$server = Models\Server::getByUUID($uuid);
$this->authorize('list-files', $server);
$node = Models\Node::find($server->node);
Javascript::put([
'server' => collect($server->makeVisible('daemonSecret'))->only('uuid', 'uuidShort', 'daemonSecret'),
'node' => collect($node)->only('fqdn', 'scheme', 'daemonListen'),
'meta' => [
'directoryList' => route('server.files.directory-list', $server->uuidShort),
'csrftoken' => csrf_token(),
],
'permissions' => [
'moveFiles' => $request->user()->can('move-files', $server),
'copyFiles' => $request->user()->can('copy-files', $server),
'compressFiles' => $request->user()->can('compress-files', $server),
'decompressFiles' => $request->user()->can('decompress-files', $server),
'createFiles' => $request->user()->can('create-files', $server),
'downloadFiles' => $request->user()->can('download-files', $server),
'deleteFiles' => $request->user()->can('delete-files', $server),
],
]);
return view('server.files.index', [
'server' => $server,
'node' => Models\Node::find($server->node)
'node' => $node,
]);
}
@ -111,16 +118,21 @@ class ServerController extends Controller
* @param Request $request
* @return \Illuminate\Contracts\View\View
*/
public function getAddFile(Request $request)
public function getAddFile(Request $request, $uuid)
{
$server = Models\Server::getByUUID($request->route()->server);
$server = Models\Server::getByUUID($uuid);
$this->authorize('add-files', $server);
$node = Models\Node::find($server->node);
Javascript::put([
'server' => collect($server->makeVisible('daemonSecret'))->only(['uuid', 'uuidShort', 'daemonSecret', 'username']),
'node' => collect($node)->only('fqdn', 'scheme', 'daemonListen'),
]);
return view('server.files.add', [
'server' => $server,
'node' => Models\Node::find($server->node),
'directory' => (in_array($request->get('dir'), [null, '/', ''])) ? '' : trim($request->get('dir'), '/') . '/'
'node' => $node,
'directory' => (in_array($request->get('dir'), [null, '/', ''])) ? '' : trim($request->get('dir'), '/') . '/',
]);
}
@ -134,9 +146,9 @@ class ServerController extends Controller
*/
public function getEditFile(Request $request, $uuid, $file)
{
$server = Models\Server::getByUUID($uuid);
$this->authorize('edit-files', $server);
$node = Models\Node::find($server->node);
$fileInfo = (object) pathinfo($file);
$controller = new FileRepository($uuid);
@ -145,22 +157,29 @@ class ServerController extends Controller
$fileContent = $controller->returnFileContents($file);
} catch (DisplayException $ex) {
Alert::danger($ex->getMessage())->flash();
return redirect()->route('server.files.index', $uuid);
} catch (\Exception $ex) {
Log::error($ex);
Alert::danger('An error occured while attempting to load the requested file for editing, please try again.')->flash();
return redirect()->route('server.files.index', $uuid);
}
Javascript::put([
'server' => collect($server->makeVisible('daemonSecret'))->only(['uuid', 'uuidShort', 'daemonSecret', 'username']),
'node' => collect($node)->only('fqdn', 'scheme', 'daemonListen'),
'stat' => $fileContent['stat'],
]);
return view('server.files.edit', [
'server' => $server,
'node' => Models\Node::find($server->node),
'node' => $node,
'file' => $file,
'stat' => $fileContent['stat'],
'contents' => $fileContent['file']->content,
'directory' => (in_array($fileInfo->dirname, ['.', './', '/'])) ? '/' : trim($fileInfo->dirname, '/') . '/'
'directory' => (in_array($fileInfo->dirname, ['.', './', '/'])) ? '/' : trim($fileInfo->dirname, '/') . '/',
]);
}
/**
@ -173,7 +192,6 @@ class ServerController extends Controller
*/
public function getDownloadFile(Request $request, $uuid, $file)
{
$server = Models\Server::getByUUID($uuid);
$node = Models\Node::find($server->node);
@ -187,21 +205,39 @@ class ServerController extends Controller
$download->save();
return redirect( $node->scheme . '://' . $node->fqdn . ':' . $node->daemonListen . '/server/file/download/' . $download->token);
return redirect($node->scheme . '://' . $node->fqdn . ':' . $node->daemonListen . '/server/file/download/' . $download->token);
}
/**
* Renders server settings page.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Contracts\View\View
*/
public function getSettings(Request $request, $uuid)
public function getAllocation(Request $request, $uuid)
{
$server = Models\Server::getByUUID($uuid);
$this->authorize('view-allocation', $server);
$node = Models\Node::find($server->node);
Javascript::put([
'server' => collect($server->makeVisible('daemonSecret'))->only(['uuid', 'uuidShort', 'daemonSecret', 'username']),
'node' => collect($node)->only('fqdn', 'scheme', 'daemonListen'),
]);
return view('server.settings.allocation', [
'server' => $server,
'allocations' => Models\Allocation::where('assigned_to', $server->id)->orderBy('ip', 'asc')->orderBy('port', 'asc')->get(),
'node' => $node,
]);
}
public function getStartup(Request $request, $uuid)
{
$server = Models\Server::getByUUID($uuid);
$this->authorize('view-startup', $server);
$node = Models\Node::find($server->node);
$allocation = Models\Allocation::findOrFail($server->allocation);
Javascript::put([
'server' => collect($server->makeVisible('daemonSecret'))->only(['uuid', 'uuidShort', 'daemonSecret', 'username']),
'node' => collect($node)->only('fqdn', 'scheme', 'daemonListen'),
]);
$variables = Models\ServiceVariables::select(
'service_variables.*',
DB::raw('COALESCE(server_variables.variable_value, service_variables.default_value) as a_serverValue')
@ -224,17 +260,13 @@ class ServerController extends Controller
];
$processed = str_replace(array_keys($serverVariables), array_values($serverVariables), $server->startup);
foreach($variables as &$variable) {
foreach ($variables as &$variable) {
$replace = ($variable->user_viewable === 1) ? $variable->a_serverValue : '**';
$processed = str_replace('{{' . $variable->env_variable . '}}', $replace, $processed);
}
return view('server.settings', [
return view('server.settings.startup', [
'server' => $server,
'databases' => Models\Database::select('databases.*', 'database_servers.host as a_host', 'database_servers.port as a_port')
->where('server_id', $server->id)
->join('database_servers', 'database_servers.id', '=', 'databases.db_server')
->get(),
'node' => Models\Node::find($server->node),
'variables' => $variables->where('user_viewable', 1),
'service' => $service,
@ -242,6 +274,44 @@ class ServerController extends Controller
]);
}
public function getDatabases(Request $request, $uuid)
{
$server = Models\Server::getByUUID($uuid);
$this->authorize('view-databases', $server);
$node = Models\Node::find($server->node);
Javascript::put([
'server' => collect($server->makeVisible('daemonSecret'))->only(['uuid', 'uuidShort', 'daemonSecret', 'username']),
'node' => collect($node)->only('fqdn', 'scheme', 'daemonListen'),
]);
return view('server.settings.databases', [
'server' => $server,
'node' => $node,
'databases' => Models\Database::select('databases.*', 'database_servers.host as a_host', 'database_servers.port as a_port')
->where('server_id', $server->id)
->join('database_servers', 'database_servers.id', '=', 'databases.db_server')
->get(),
]);
}
public function getSFTP(Request $request, $uuid)
{
$server = Models\Server::getByUUID($uuid);
$this->authorize('view-sftp', $server);
$node = Models\Node::find($server->node);
Javascript::put([
'server' => collect($server->makeVisible('daemonSecret'))->only(['uuid', 'daemonSecret', 'username']),
'node' => collect($node)->only('fqdn', 'scheme', 'daemonListen'),
]);
return view('server.settings.sftp', [
'server' => $server,
'node' => $node,
]);
}
public function postSettingsSFTP(Request $request, $uuid)
{
$server = Models\Server::getByUUID($uuid);
@ -252,14 +322,15 @@ class ServerController extends Controller
$repo->updateSFTPPassword($server->id, $request->input('sftp_pass'));
Alert::success('Successfully updated this servers SFTP password.')->flash();
} catch (DisplayValidationException $ex) {
return redirect()->route('server.settings', $uuid)->withErrors(json_decode($ex->getMessage()));
return redirect()->route('server.settings.sftp', $uuid)->withErrors(json_decode($ex->getMessage()));
} catch (DisplayException $ex) {
Alert::danger($ex->getMessage())->flash();
} catch (\Exception $ex) {
Log::error($ex);
Alert::danger('An unknown error occured while attempting to update this server\'s SFTP settings.')->flash();
}
return redirect()->route('server.settings', $uuid);
return redirect()->route('server.settings.sftp', $uuid);
}
public function postSettingsStartup(Request $request, $uuid)
@ -270,19 +341,19 @@ class ServerController extends Controller
try {
$repo = new ServerRepository;
$repo->updateStartup($server->id, $request->except([
'_token'
'_token',
]));
Alert::success('Server startup variables were successfully updated.')->flash();
} catch (DisplayException $ex) {
Alert::danger($ex->getMessage())->flash();
} catch(\Exception $ex) {
} catch (\Exception $ex) {
Log::error($ex);
Alert::danger('An unhandled exception occured while attemping to update startup variables for this server. Please try again.')->flash();
}
return redirect()->route('server.settings', [
'uuid' => $uuid,
'tab' => 'tab_startup'
'tab' => 'tab_startup',
]);
}
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,27 +21,25 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Http\Controllers\Server;
use DB;
use Log;
use Auth;
use Alert;
use Log;
use Javascript;
use Pterodactyl\Models;
use Pterodactyl\Repositories\SubuserRepository;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Exceptions\DisplayValidationException;
use Illuminate\Http\Request;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Http\Controllers\Controller;
use Pterodactyl\Repositories\SubuserRepository;
use Pterodactyl\Exceptions\DisplayValidationException;
class SubuserController extends Controller
{
/**
* Controller Constructor
* Controller Constructor.
*
* @return void
*/
@ -54,29 +52,40 @@ class SubuserController extends Controller
{
$server = Models\Server::getByUUID($uuid);
$this->authorize('list-subusers', $server);
$node = Models\Node::find($server->node);
Javascript::put([
'server' => collect($server->makeVisible('daemonSecret'))->only(['uuid', 'uuidShort', 'daemonSecret', 'username']),
'node' => collect($node)->only('fqdn', 'scheme', 'daemonListen'),
]);
return view('server.users.index', [
'server' => $server,
'node' => Models\Node::find($server->node),
'subusers' => Models\Subuser::select('subusers.*', 'users.email as a_userEmail')
'node' => $node,
'subusers' => Models\Subuser::select('subusers.*', 'users.email', 'users.username', 'users.use_totp')
->join('users', 'users.id', '=', 'subusers.user_id')
->where('server_id', $server->id)
->get()
->get(),
]);
}
public function getView(Request $request, $uuid, $id)
{
$server = Models\Server::getByUUID($uuid);
$this->authorize('view-subuser', $server);
$node = Models\Node::find($server->node);
Javascript::put([
'server' => collect($server->makeVisible('daemonSecret'))->only(['uuid', 'uuidShort', 'daemonSecret', 'username']),
'node' => collect($node)->only('fqdn', 'scheme', 'daemonListen'),
]);
$subuser = Models\Subuser::select('subusers.*', 'users.email as a_userEmail')
->join('users', 'users.id', '=', 'subusers.user_id')
->where(DB::raw('md5(subusers.id)'), $id)->where('subusers.server_id', $server->id)
->first();
if (!$subuser) {
if (! $subuser) {
abort(404);
}
@ -85,13 +94,13 @@ class SubuserController extends Controller
->where('user_id', $subuser->user_id)->where('server_id', $server->id)
->get();
foreach($modelPermissions as &$perm) {
foreach ($modelPermissions as &$perm) {
$permissions[$perm->permission] = true;
}
return view('server.users.view', [
'server' => $server,
'node' => Models\Node::find($server->node),
'node' => $node,
'subuser' => $subuser,
'permissions' => $permissions,
]);
@ -99,17 +108,15 @@ class SubuserController extends Controller
public function postView(Request $request, $uuid, $id)
{
$server = Models\Server::getByUUID($uuid);
$this->authorize('edit-subuser', $server);
$subuser = Models\Subuser::where(DB::raw('md5(id)'), $id)->where('server_id', $server->id)->first();
try {
if (!$subuser) {
if (! $subuser) {
throw new DisplayException('Unable to locate a subuser by that ID.');
} else if ($subuser->user_id === Auth::user()->id) {
} elseif ($subuser->user_id === Auth::user()->id) {
throw new DisplayException('You are not authorized to edit you own account.');
}
@ -117,14 +124,14 @@ class SubuserController extends Controller
$repo->update($subuser->id, [
'permissions' => $request->input('permissions'),
'server' => $server->id,
'user' => $subuser->user_id
'user' => $subuser->user_id,
]);
Alert::success('Subuser permissions have successfully been updated.')->flash();
} catch (DisplayValidationException $ex) {
return redirect()->route('server.subusers.view', [
'uuid' => $uuid,
'id' => $id
'id' => $id,
])->withErrors(json_decode($ex->getMessage()));
} catch (DisplayException $ex) {
Alert::danger($ex->getMessage())->flash();
@ -132,9 +139,10 @@ class SubuserController extends Controller
Log::error($ex);
Alert::danger('An unknown error occured while attempting to update this subuser.')->flash();
}
return redirect()->route('server.subusers.view', [
'uuid' => $uuid,
'id' => $id
'id' => $id,
]);
}
@ -142,10 +150,16 @@ class SubuserController extends Controller
{
$server = Models\Server::getByUUID($uuid);
$this->authorize('create-subuser', $server);
$node = Models\Node::find($server->node);
Javascript::put([
'server' => collect($server->makeVisible('daemonSecret'))->only(['uuid', 'uuidShort', 'daemonSecret', 'username']),
'node' => collect($node)->only('fqdn', 'scheme', 'daemonListen'),
]);
return view('server.users.new', [
'server' => $server,
'node' => Models\Node::find($server->node)
'node' => $node,
]);
}
@ -157,12 +171,13 @@ class SubuserController extends Controller
try {
$repo = new SubuserRepository;
$id = $repo->create($server->id, $request->except([
'_token'
'_token',
]));
Alert::success('Successfully created new subuser.')->flash();
return redirect()->route('server.subusers.view', [
'uuid' => $uuid,
'id' => md5($id)
'id' => md5($id),
]);
} catch (DisplayValidationException $ex) {
return redirect()->route('server.subusers.new', $uuid)->withErrors(json_decode($ex->getMessage()))->withInput();
@ -172,6 +187,7 @@ class SubuserController extends Controller
Log::error($ex);
Alert::danger('An unknown error occured while attempting to add a new subuser.')->flash();
}
return redirect()->route('server.subusers.new', $uuid)->withInput();
}
@ -182,23 +198,23 @@ class SubuserController extends Controller
try {
$subuser = Models\Subuser::select('id')->where(DB::raw('md5(id)'), $id)->where('server_id', $server->id)->first();
if (!$subuser) {
if (! $subuser) {
throw new DisplayException('No subuser by that ID was found on the system.');
}
$repo = new SubuserRepository;
$repo->delete($subuser->id);
return response('', 204);
} catch (DisplayException $ex) {
response()->json([
'error' => $ex->getMessage()
'error' => $ex->getMessage(),
], 422);
} catch (\Exception $ex) {
Log::error($ex);
response()->json([
'error' => 'An unknown error occured while attempting to delete this subuser.'
'error' => 'An unknown error occured while attempting to delete this subuser.',
], 503);
}
}
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,19 +21,18 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Http\Controllers\Server;
use Alert;
use Log;
use Cron;
use Pterodactyl\Repositories;
use Alert;
use Javascript;
use Pterodactyl\Models;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Exceptions\DisplayValidationException;
use Pterodactyl\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Pterodactyl\Repositories;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Http\Controllers\Controller;
use Pterodactyl\Exceptions\DisplayValidationException;
class TaskController extends Controller
{
@ -46,15 +45,21 @@ class TaskController extends Controller
{
$server = Models\Server::getByUUID($uuid);
$this->authorize('list-tasks', $server);
$node = Models\Node::find($server->node);
Javascript::put([
'server' => collect($server->makeVisible('daemonSecret'))->only(['uuid', 'uuidShort', 'daemonSecret', 'username']),
'node' => collect($node)->only('fqdn', 'scheme', 'daemonListen'),
]);
return view('server.tasks.index', [
'server' => $server,
'node' => Models\Node::findOrFail($server->node),
'node' => $node,
'tasks' => Models\Task::where('server', $server->id)->get(),
'actions' => [
'command' => 'Send Command',
'power' => 'Set Power Status'
]
'command' => trans('server.tasks.actions.command'),
'power' => trans('server.tasks.actions.power'),
],
]);
}
@ -62,10 +67,16 @@ class TaskController extends Controller
{
$server = Models\Server::getByUUID($uuid);
$this->authorize('create-task', $server);
$node = Models\Node::find($server->node);
Javascript::put([
'server' => collect($server->makeVisible('daemonSecret'))->only(['uuid', 'uuidShort', 'daemonSecret', 'username']),
'node' => collect($node)->only('fqdn', 'scheme', 'daemonListen'),
]);
return view('server.tasks.new', [
'server' => $server,
'node' => Models\Node::findOrFail($server->node)
'node' => $node,
]);
}
@ -77,30 +88,20 @@ class TaskController extends Controller
try {
$repo = new Repositories\TaskRepository;
$repo->create($server->id, $request->except([
'_token'
'_token',
]));
return redirect()->route('server.tasks', $uuid);
} catch (DisplayValidationException $ex) {
return redirect()->route('server.tasks', $uuid)->withErrors(json_decode($ex->getMessage()))->withInput();
return redirect()->route('server.tasks.new', $uuid)->withErrors(json_decode($ex->getMessage()))->withInput();
} catch (DisplayException $ex) {
Alert::danger($ex->getMessage())->flash();
} catch (\Exception $ex) {
Log::error($ex);
Alert::danger('An unknown error occured while attempting to create this task.')->flash();
}
return redirect()->route('server.tasks', $uuid);
}
public function getView(Request $request, $uuid, $id)
{
$server = Models\Server::getByUUID($uuid);
$this->authorize('view-task', $server);
return view('server.tasks.view', [
'server' => $server,
'node' => Models\Node::findOrFail($server->node),
'task' => Models\Task::where('id', $id)->where('server', $server->id)->firstOrFail()
]);
return redirect()->route('server.tasks.new', $uuid);
}
public function deleteTask(Request $request, $uuid, $id)
@ -110,20 +111,22 @@ class TaskController extends Controller
$task = Models\Task::findOrFail($id);
if (!$task || $server->id !== $task->server) {
if (! $task || $server->id !== $task->server) {
return response()->json([
'error' => 'No task by that ID was found associated with this server.'
'error' => 'No task by that ID was found associated with this server.',
], 404);
}
try {
$repo = new Repositories\TaskRepository;
$repo->delete($id);
return response()->json([], 204);
} catch (\Exception $ex) {
Log::error($ex);
return response()->json([
'error' => 'A server error occured while attempting to delete this task.'
'error' => 'A server error occured while attempting to delete this task.',
], 503);
}
}
@ -135,22 +138,24 @@ class TaskController extends Controller
$task = Models\Task::findOrFail($id);
if (!$task || $server->id !== $task->server) {
if (! $task || $server->id !== $task->server) {
return response()->json([
'error' => 'No task by that ID was found associated with this server.'
'error' => 'No task by that ID was found associated with this server.',
], 404);
}
try {
$repo = new Repositories\TaskRepository;
$resp = $repo->toggle($id);
return response()->json([
'status' => $resp
'status' => $resp,
]);
} catch (\Exception $ex) {
Log::error($ex);
return response()->json([
'error' => 'A server error occured while attempting to toggle this task.'
'error' => 'A server error occured while attempting to toggle this task.',
], 503);
}
}

View file

@ -53,6 +53,7 @@ class Kernel extends HttpKernel
'guest' => \Pterodactyl\Http\Middleware\RedirectIfAuthenticated::class,
'server' => \Pterodactyl\Http\Middleware\CheckServer::class,
'admin' => \Pterodactyl\Http\Middleware\AdminAuthenticate::class,
'daemon' => \Pterodactyl\Http\Middleware\DaemonAuthenticate::class,
'csrf' => \Pterodactyl\Http\Middleware\VerifyCsrfToken::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,6 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Http\Middleware;
use Auth;
@ -28,24 +29,20 @@ use Crypt;
use Config;
use IPTools\IP;
use IPTools\Range;
use Dingo\Api\Routing\Route;
use Illuminate\Http\Request;
use Pterodactyl\Models\User;
use Pterodactyl\Models\APIKey;
use Pterodactyl\Models\APIPermission;
use Pterodactyl\Models\User;
use Pterodactyl\Services\APILogService;
use Illuminate\Http\Request;
use Dingo\Api\Routing\Route;
use Dingo\Api\Auth\Provider\Authorization;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; // 400
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException; // 401
use Symfony\Component\HttpKernel\Exception\HttpException; // 400
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; // 401
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; // 403
use Symfony\Component\HttpKernel\Exception\HttpException; //500
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException; //500
class APISecretToken extends Authorization
{
protected $algo = 'sha256';
protected $permissionAllowed = false;
@ -64,7 +61,7 @@ class APISecretToken extends Authorization
public function authenticate(Request $request, Route $route)
{
if (!$request->bearerToken() || empty($request->bearerToken())) {
if (! $request->bearerToken() || empty($request->bearerToken())) {
APILogService::log($request, 'The authentication header was missing or malformed.');
throw new UnauthorizedHttpException('The authentication header was missing or malformed.');
}
@ -72,22 +69,22 @@ class APISecretToken extends Authorization
list($public, $hashed) = explode('.', $request->bearerToken());
$key = APIKey::where('public', $public)->first();
if (!$key) {
if (! $key) {
APILogService::log($request, 'Invalid API Key.');
throw new AccessDeniedHttpException('Invalid API Key.');
}
// Check for Resource Permissions
if (!empty($request->route()->getName())) {
if(!is_null($key->allowed_ips)) {
if (! empty($request->route()->getName())) {
if (! is_null($key->allowed_ips)) {
$inRange = false;
foreach(json_decode($key->allowed_ips) as $ip) {
foreach (json_decode($key->allowed_ips) as $ip) {
if (Range::parse($ip)->contains(new IP($request->ip()))) {
$inRange = true;
break;
}
}
if (!$inRange) {
if (! $inRange) {
APILogService::log($request, 'This IP address <' . $request->ip() . '> does not have permission to use this API key.');
throw new AccessDeniedHttpException('This IP address <' . $request->ip() . '> does not have permission to use this API key.');
}
@ -98,11 +95,11 @@ class APISecretToken extends Authorization
// Suport Wildcards
if (starts_with($request->route()->getName(), 'api.user')) {
$permission->orWhere('permission', 'api.user.*');
} else if(starts_with($request->route()->getName(), 'api.admin')) {
} elseif (starts_with($request->route()->getName(), 'api.admin')) {
$permission->orWhere('permission', 'api.admin.*');
}
if (!$permission->first()) {
if (! $permission->first()) {
APILogService::log($request, 'You do not have permission to access this resource. This API Key requires the ' . $request->route()->getName() . ' permission node.');
throw new AccessDeniedHttpException('You do not have permission to access this resource. This API Key requires the ' . $request->route()->getName() . ' permission node.');
}
@ -116,21 +113,21 @@ class APISecretToken extends Authorization
}
$this->url = urldecode($request->fullUrl());
if($this->_generateHMAC($request->getContent(), $decrypted) !== base64_decode($hashed)) {
if ($this->_generateHMAC($request->getContent(), $decrypted) !== base64_decode($hashed)) {
APILogService::log($request, 'The hashed body was not valid. Potential modification of contents in route.');
throw new BadRequestHttpException('The hashed body was not valid. Potential modification of contents in route.');
}
// Log the Route Access
APILogService::log($request, null, true);
return Auth::loginUsingId($key->user);
return Auth::loginUsingId($key->user);
}
protected function _generateHMAC($body, $key)
{
$data = $this->url . $body;
return hash_hmac($this->algo, $data, $key, true);
}
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,8 +21,10 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Http\Middleware;
use Theme;
use Closure;
use Illuminate\Contracts\Auth\Guard;
@ -63,10 +65,13 @@ class AdminAuthenticate
}
}
if($this->auth->user()->root_admin !== 1) {
if ($this->auth->user()->root_admin !== 1) {
return abort(403);
}
// @TODO: eventually update admin themes
Theme::set('default');
return $next($request);
}
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,12 +21,12 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Http\Middleware;
use Closure;
use Auth;
use Closure;
use Pterodactyl\Models\Server;
use Debugbar;
class CheckServer
{
@ -39,13 +39,12 @@ class CheckServer
*/
public function handle($request, Closure $next)
{
if (!Auth::user()) {
if (! Auth::user()) {
return redirect()->guest('auth/login');
}
$server = Server::getByUUID($request->route()->server);
if (!$server) {
if (! $server) {
return response()->view('errors.404', [], 404);
}
@ -58,6 +57,5 @@ class CheckServer
}
return $next($request);
}
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,44 +21,51 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Listeners;
use Carbon;
namespace Pterodactyl\Http\Middleware;
use Pterodactyl\Events\ServerDeleted;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Closure;
use Pterodactyl\Models\Node;
use Illuminate\Contracts\Auth\Guard;
use Pterodactyl\Jobs\SuspendServer;
use Pterodactyl\Jobs\DeleteServer;
class DeleteServerListener
class DaemonAuthenticate
{
use DispatchesJobs;
/**
* The Guard implementation.
*
* @var Guard
*/
protected $auth;
/**
* Create the event listener.
* Create a new filter instance.
*
* @param Guard $auth
* @return void
*/
public function __construct()
public function __construct(Guard $auth)
{
//
$this->auth = $auth;
}
/**
* Handle the event.
* Handle an incoming request.
*
* @param DeleteServerEvent $event
* @return void
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle(ServerDeleted $event)
public function handle($request, Closure $next)
{
$this->dispatch((new SuspendServer($event->server))->onQueue(env('QUEUE_HIGH', 'high')));
$this->dispatch(
(new DeleteServer($event->server))
->delay(Carbon::now()->addMinutes(env('APP_DELETE_MINUTES', 10)))
->onQueue(env('QUEUE_STANDARD', 'standard'))
);
if (! $request->header('X-Access-Node')) {
return abort(403);
}
$node = Node::where('daemonSecret', $request->header('X-Access-Node'))->first();
if (! $node) {
return abort(404);
}
return $next($request);
}
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,18 +21,17 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Http\Middleware;
use Auth;
use Closure;
use Session;
use Settings;
use Illuminate\Support\Facades\App;
class LanguageMiddleware
{
public function __construct()
{
//
@ -49,12 +48,13 @@ class LanguageMiddleware
{
if (Session::has('applocale')) {
App::setLocale(Session::get('applocale'));
} else if(Auth::check() && isset(Auth::user()->language)) {
} elseif (Auth::check() && isset(Auth::user()->language)) {
Session::set('applocale', Auth::user()->language);
App::setLocale(Auth::user()->language);
} else {
App::setLocale(Settings::get('default_language', 'en'));
}
return $next($request);
}
}

View file

@ -13,6 +13,7 @@ class VerifyCsrfToken extends BaseVerifier
*/
protected $except = [
'remote/*',
'api/*'
'daemon/*',
'api/*',
];
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,162 +21,164 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Http\Routes;
use Pterodactyl\Models;
use Illuminate\Routing\Router;
class APIRoutes
{
public function map(Router $router) {
public function map(Router $router)
{
$api = app('Dingo\Api\Routing\Router');
$api->version('v1', ['prefix' => 'api/me', 'middleware' => 'api.auth'], function ($api) {
$api->get('/', [
'as' => 'api.user.me',
'uses' => 'Pterodactyl\Http\Controllers\API\User\InfoController@me'
'uses' => 'Pterodactyl\Http\Controllers\API\User\InfoController@me',
]);
$api->get('/server/{uuid}', [
'as' => 'api.user.server',
'uses' => 'Pterodactyl\Http\Controllers\API\User\ServerController@info'
'uses' => 'Pterodactyl\Http\Controllers\API\User\ServerController@info',
]);
$api->put('/server/{uuid}', [
'as' => 'api.user.server.power',
'uses' => 'Pterodactyl\Http\Controllers\API\User\ServerController@power'
'uses' => 'Pterodactyl\Http\Controllers\API\User\ServerController@power',
]);
});
$api->version('v1', ['prefix' => 'api', 'middleware' => 'api.auth'], function ($api) {
/**
/*
* User Routes
*/
$api->get('users', [
'as' => 'api.admin.users.list',
'uses' => 'Pterodactyl\Http\Controllers\API\UserController@list'
'uses' => 'Pterodactyl\Http\Controllers\API\UserController@lists',
]);
$api->post('users', [
'as' => 'api.admin.users.create',
'uses' => 'Pterodactyl\Http\Controllers\API\UserController@create'
'uses' => 'Pterodactyl\Http\Controllers\API\UserController@create',
]);
$api->get('users/{id}', [
'as' => 'api.admin.users.view',
'uses' => 'Pterodactyl\Http\Controllers\API\UserController@view'
'uses' => 'Pterodactyl\Http\Controllers\API\UserController@view',
]);
$api->patch('users/{id}', [
'as' => 'api.admin.users.update',
'uses' => 'Pterodactyl\Http\Controllers\API\UserController@update'
'uses' => 'Pterodactyl\Http\Controllers\API\UserController@update',
]);
$api->delete('users/{id}', [
'as' => 'api.admin.users.delete',
'uses' => 'Pterodactyl\Http\Controllers\API\UserController@delete'
'uses' => 'Pterodactyl\Http\Controllers\API\UserController@delete',
]);
/**
/*
* Server Routes
*/
$api->get('servers', [
'as' => 'api.admin.servers.list',
'uses' => 'Pterodactyl\Http\Controllers\API\ServerController@list'
'uses' => 'Pterodactyl\Http\Controllers\API\ServerController@lists',
]);
$api->post('servers', [
'as' => 'api.admin.servers.create',
'uses' => 'Pterodactyl\Http\Controllers\API\ServerController@create'
'uses' => 'Pterodactyl\Http\Controllers\API\ServerController@create',
]);
$api->get('servers/{id}', [
'as' => 'api.admin.servers.view',
'uses' => 'Pterodactyl\Http\Controllers\API\ServerController@view'
'uses' => 'Pterodactyl\Http\Controllers\API\ServerController@view',
]);
$api->patch('servers/{id}/config', [
'as' => 'api.admin.servers.config',
'uses' => 'Pterodactyl\Http\Controllers\API\ServerController@config'
'uses' => 'Pterodactyl\Http\Controllers\API\ServerController@config',
]);
$api->patch('servers/{id}/build', [
'as' => 'api.admin.servers.build',
'uses' => 'Pterodactyl\Http\Controllers\API\ServerController@build'
'uses' => 'Pterodactyl\Http\Controllers\API\ServerController@build',
]);
$api->post('servers/{id}/suspend', [
'as' => 'api.admin.servers.suspend',
'uses' => 'Pterodactyl\Http\Controllers\API\ServerController@suspend'
'uses' => 'Pterodactyl\Http\Controllers\API\ServerController@suspend',
]);
$api->post('servers/{id}/unsuspend', [
'as' => 'api.admin.servers.unsuspend',
'uses' => 'Pterodactyl\Http\Controllers\API\ServerController@unsuspend'
'uses' => 'Pterodactyl\Http\Controllers\API\ServerController@unsuspend',
]);
$api->delete('servers/{id}/{force?}', [
'as' => 'api.admin.servers.delete',
'uses' => 'Pterodactyl\Http\Controllers\API\ServerController@delete'
'uses' => 'Pterodactyl\Http\Controllers\API\ServerController@delete',
]);
/**
/*
* Node Routes
*/
$api->get('nodes', [
'as' => 'api.admin.nodes.list',
'uses' => 'Pterodactyl\Http\Controllers\API\NodeController@list'
'uses' => 'Pterodactyl\Http\Controllers\API\NodeController@lists',
]);
$api->post('nodes', [
'as' => 'api.admin.nodes.create',
'uses' => 'Pterodactyl\Http\Controllers\API\NodeController@create'
'uses' => 'Pterodactyl\Http\Controllers\API\NodeController@create',
]);
$api->get('nodes/allocations', [
'as' => 'api.admin.nodes.allocations',
'uses' => 'Pterodactyl\Http\Controllers\API\NodeController@allocations'
'uses' => 'Pterodactyl\Http\Controllers\API\NodeController@allocations',
]);
$api->get('nodes/allocations/{id}', [
'as' => 'api.admin.nodes.allocations',
'uses' => 'Pterodactyl\Http\Controllers\API\NodeController@allocationsView',
]);
$api->get('nodes/{id}', [
'as' => 'api.admin.nodes.view',
'uses' => 'Pterodactyl\Http\Controllers\API\NodeController@view'
'uses' => 'Pterodactyl\Http\Controllers\API\NodeController@view',
]);
$api->get('nodes/{id}/config', [
'as' => 'api.admin.nodes.view',
'uses' => 'Pterodactyl\Http\Controllers\API\NodeController@config'
'uses' => 'Pterodactyl\Http\Controllers\API\NodeController@config',
]);
$api->delete('nodes/{id}', [
'as' => 'api.admin.nodes.delete',
'uses' => 'Pterodactyl\Http\Controllers\API\NodeController@delete'
'uses' => 'Pterodactyl\Http\Controllers\API\NodeController@delete',
]);
/**
/*
* Location Routes
*/
$api->get('locations', [
'as' => 'api.admin.locations.list',
'uses' => 'Pterodactyl\Http\Controllers\API\LocationController@list'
'uses' => 'Pterodactyl\Http\Controllers\API\LocationController@lists',
]);
/**
/*
* Service Routes
*/
$api->get('services', [
'as' => 'api.admin.services.list',
'uses' => 'Pterodactyl\Http\Controllers\API\ServiceController@list'
'uses' => 'Pterodactyl\Http\Controllers\API\ServiceController@lists',
]);
$api->get('services/{id}', [
'as' => 'api.admin.services.view',
'uses' => 'Pterodactyl\Http\Controllers\API\ServiceController@view'
'uses' => 'Pterodactyl\Http\Controllers\API\ServiceController@view',
]);
});
}
}

View file

@ -1,8 +1,8 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* Some Modifications (c) 2015 Dylan Seidt <dylan.seidt@gmail.com>
* 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
@ -22,13 +22,15 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Http\Routes;
use Illuminate\Routing\Router;
class AdminRoutes {
public function map(Router $router) {
class AdminRoutes
{
public function map(Router $router)
{
// Admin Index
$router->get('admin', [
@ -36,9 +38,9 @@ class AdminRoutes {
'middleware' => [
'auth',
'admin',
'csrf'
'csrf',
],
'uses' => 'Admin\BaseController@getIndex'
'uses' => 'Admin\BaseController@getIndex',
]);
$router->group([
@ -46,15 +48,15 @@ class AdminRoutes {
'middleware' => [
'auth',
'admin',
'csrf'
]
'csrf',
],
], function () use ($router) {
$router->get('/', [
'as' => 'admin.settings',
'uses' => 'Admin\BaseController@getSettings'
'uses' => 'Admin\BaseController@getSettings',
]);
$router->post('/', [
'uses' => 'Admin\BaseController@postSettings'
'uses' => 'Admin\BaseController@postSettings',
]);
});
@ -63,48 +65,47 @@ class AdminRoutes {
'middleware' => [
'auth',
'admin',
'csrf'
]
'csrf',
],
], function () use ($router) {
// View All Accounts on System
$router->get('/', [
'as' => 'admin.users',
'uses' => 'Admin\UserController@getIndex'
'uses' => 'Admin\UserController@getIndex',
]);
$router->get('/accounts.json', [
'as' => 'admin.users.json',
'uses' => 'Admin\UserController@getJson'
'uses' => 'Admin\UserController@getJson',
]);
// View Specific Account
$router->get('/view/{id}', [
'as' => 'admin.users.view',
'uses' => 'Admin\UserController@getView'
'uses' => 'Admin\UserController@getView',
]);
// View Specific Account
$router->post('/view/{id}', [
'uses' => 'Admin\UserController@updateUser'
'uses' => 'Admin\UserController@updateUser',
]);
// Delete an Account Matching an ID
$router->delete('/view/{id}', [
'uses' => 'Admin\UserController@deleteUser'
'uses' => 'Admin\UserController@deleteUser',
]);
// Show Create Account Page
$router->get('/new', [
'as' => 'admin.users.new',
'uses' => 'Admin\UserController@getNew'
'uses' => 'Admin\UserController@getNew',
]);
// Handle Creating New Account
$router->post('/new', [
'uses' => 'Admin\UserController@postNew'
'uses' => 'Admin\UserController@postNew',
]);
});
// Server Routes
@ -113,108 +114,107 @@ class AdminRoutes {
'middleware' => [
'auth',
'admin',
'csrf'
]
'csrf',
],
], function () use ($router) {
// View All Servers
$router->get('/', [
'as' => 'admin.servers',
'uses' => 'Admin\ServersController@getIndex' ]);
'uses' => 'Admin\ServersController@getIndex', ]);
// View Create Server Page
$router->get('/new', [
'as' => 'admin.servers.new',
'uses' => 'Admin\ServersController@getNew'
'uses' => 'Admin\ServersController@getNew',
]);
// Handle POST Request for Creating Server
$router->post('/new', [
'uses' => 'Admin\ServersController@postNewServer'
'uses' => 'Admin\ServersController@postNewServer',
]);
// Assorted Page Helpers
$router->post('/new/get-nodes', [
'uses' => 'Admin\ServersController@postNewServerGetNodes'
'uses' => 'Admin\ServersController@postNewServerGetNodes',
]);
$router->post('/new/get-ips', [
'uses' => 'Admin\ServersController@postNewServerGetIps'
'uses' => 'Admin\ServersController@postNewServerGetIps',
]);
$router->post('/new/service-options', [
'uses' => 'Admin\ServersController@postNewServerServiceOptions'
'uses' => 'Admin\ServersController@postNewServerServiceOptions',
]);
$router->post('/new/service-variables', [
'uses' => 'Admin\ServersController@postNewServerServiceVariables'
$router->post('/new/option-details', [
'uses' => 'Admin\ServersController@postNewServerOptionDetails',
]);
// End Assorted Page Helpers
// View Specific Server
$router->get('/view/{id}', [
'as' => 'admin.servers.view',
'uses' => 'Admin\ServersController@getView'
'uses' => 'Admin\ServersController@getView',
]);
// Database Stuffs
$router->post('/view/{id}/database', [
'as' => 'admin.servers.database',
'uses' => 'Admin\ServersController@postDatabase'
'uses' => 'Admin\ServersController@postDatabase',
]);
// Change Server Details
$router->post('/view/{id}/details', [
'uses' => 'Admin\ServersController@postUpdateServerDetails'
'uses' => 'Admin\ServersController@postUpdateServerDetails',
]);
// Change Server Details
$router->post('/view/{id}/container', [
'as' => 'admin.servers.post.container',
'uses' => 'Admin\ServersController@postUpdateContainerDetails'
'uses' => 'Admin\ServersController@postUpdateContainerDetails',
]);
// Change Server Details
$router->post('/view/{id}/startup', [
'as' => 'admin.servers.post.startup',
'uses' => 'Admin\ServersController@postUpdateServerStartup'
'uses' => 'Admin\ServersController@postUpdateServerStartup',
]);
// Rebuild Server
$router->post('/view/{id}/rebuild', [
'uses' => 'Admin\ServersController@postUpdateServerToggleBuild'
'uses' => 'Admin\ServersController@postUpdateServerToggleBuild',
]);
// Change Build Details
$router->post('/view/{id}/build', [
'uses' => 'Admin\ServersController@postUpdateServerUpdateBuild'
'uses' => 'Admin\ServersController@postUpdateServerUpdateBuild',
]);
// Suspend Server
$router->post('/view/{id}/suspend', [
'uses' => 'Admin\ServersController@postSuspendServer'
'uses' => 'Admin\ServersController@postSuspendServer',
]);
// Unsuspend Server
$router->post('/view/{id}/unsuspend', [
'uses' => 'Admin\ServersController@postUnsuspendServer'
'uses' => 'Admin\ServersController@postUnsuspendServer',
]);
// Change Install Status
$router->post('/view/{id}/installed', [
'uses' => 'Admin\ServersController@postToggleInstall'
'uses' => 'Admin\ServersController@postToggleInstall',
]);
// Delete [force delete]
$router->delete('/view/{id}/{force?}', [
'uses' => 'Admin\ServersController@deleteServer'
'uses' => 'Admin\ServersController@deleteServer',
]);
$router->post('/view/{id}/queuedDeletion', [
'uses' => 'Admin\ServersController@postQueuedDeletionHandler',
'as' => 'admin.servers.post.queuedDeletion'
'as' => 'admin.servers.post.queuedDeletion',
]);
});
// Node Routes
@ -223,70 +223,74 @@ class AdminRoutes {
'middleware' => [
'auth',
'admin',
'csrf'
]
'csrf',
],
], function () use ($router) {
// View All Nodes
$router->get('/', [
'as' => 'admin.nodes',
'uses' => 'Admin\NodesController@getIndex'
'uses' => 'Admin\NodesController@getIndex',
]);
// Add New Node
$router->get('/new', [
'as' => 'admin.nodes.new',
'uses' => 'Admin\NodesController@getNew'
'uses' => 'Admin\NodesController@getNew',
]);
$router->post('/new', [
'uses' => 'Admin\NodesController@postNew'
'uses' => 'Admin\NodesController@postNew',
]);
// View Node
$router->get('/view/{id}', [
'as' => 'admin.nodes.view',
'uses' => 'Admin\NodesController@getView'
'uses' => 'Admin\NodesController@getView',
]);
$router->post('/view/{id}', [
'uses' => 'Admin\NodesController@postView'
'uses' => 'Admin\NodesController@postView',
]);
$router->delete('/view/{id}/deallocate/single/{allocation}', [
'uses' => 'Admin\NodesController@deallocateSingle'
'uses' => 'Admin\NodesController@deallocateSingle',
]);
$router->post('/view/{id}/deallocate/block', [
'uses' => 'Admin\NodesController@deallocateBlock'
'uses' => 'Admin\NodesController@deallocateBlock',
]);
$router->post('/view/{id}/alias', [
'as' => 'admin.nodes.alias',
'uses' => 'Admin\NodesController@setAlias'
'uses' => 'Admin\NodesController@setAlias',
]);
$router->get('/view/{id}/allocations.json', [
'as' => 'admin.nodes.view.allocations',
'uses' => 'Admin\NodesController@getAllocationsJson'
'uses' => 'Admin\NodesController@getAllocationsJson',
]);
$router->post('/view/{id}/allocations', [
'as' => 'admin.nodes.post.allocations',
'uses' => 'Admin\NodesController@postAllocations'
'uses' => 'Admin\NodesController@postAllocations',
]);
// View Deploy
$router->get('/view/{id}/deploy', [
'as' => 'admin.nodes.deply',
'uses' => 'Admin\NodesController@getScript'
'uses' => 'Admin\NodesController@getScript',
]);
$router->delete('/view/{id}', [
'as' => 'admin.nodes.delete',
'uses' => 'Admin\NodesController@deleteNode'
'uses' => 'Admin\NodesController@deleteNode',
]);
$router->get('/{id}/configurationtoken', [
'as' => 'admin.nodes.configuration-token',
'uses' => 'Admin\NodesController@getConfigurationToken',
]);
});
// Location Routes
@ -295,21 +299,21 @@ class AdminRoutes {
'middleware' => [
'auth',
'admin',
'csrf'
]
'csrf',
],
], function () use ($router) {
$router->get('/', [
'as' => 'admin.locations',
'uses' => 'Admin\LocationsController@getIndex'
'uses' => 'Admin\LocationsController@getIndex',
]);
$router->delete('/{id}', [
'uses' => 'Admin\LocationsController@deleteLocation'
'uses' => 'Admin\LocationsController@deleteLocation',
]);
$router->patch('/{id}', [
'uses' => 'Admin\LocationsController@patchLocation'
'uses' => 'Admin\LocationsController@patchLocation',
]);
$router->post('/', [
'uses' => 'Admin\LocationsController@postLocation'
'uses' => 'Admin\LocationsController@postLocation',
]);
});
@ -319,27 +323,27 @@ class AdminRoutes {
'middleware' => [
'auth',
'admin',
'csrf'
]
'csrf',
],
], function () use ($router) {
$router->get('/', [
'as' => 'admin.databases',
'uses' => 'Admin\DatabaseController@getIndex'
'uses' => 'Admin\DatabaseController@getIndex',
]);
$router->get('/new', [
'as' => 'admin.databases.new',
'uses' => 'Admin\DatabaseController@getNew'
'uses' => 'Admin\DatabaseController@getNew',
]);
$router->post('/new', [
'uses' => 'Admin\DatabaseController@postNew'
'uses' => 'Admin\DatabaseController@postNew',
]);
$router->delete('/delete/{id}', [
'as' => 'admin.databases.delete',
'uses' => 'Admin\DatabaseController@deleteDatabase'
'uses' => 'Admin\DatabaseController@deleteDatabase',
]);
$router->delete('/delete-server/{id}', [
'as' => 'admin.databases.delete-server',
'uses' => 'Admin\DatabaseController@deleteServer'
'uses' => 'Admin\DatabaseController@deleteServer',
]);
});
@ -349,78 +353,133 @@ class AdminRoutes {
'middleware' => [
'auth',
'admin',
'csrf'
]
'csrf',
],
], function () use ($router) {
$router->get('/', [
'as' => 'admin.services',
'uses' => 'Admin\ServiceController@getIndex'
'uses' => 'Admin\ServiceController@getIndex',
]);
$router->get('/new', [
'as' => 'admin.services.new',
'uses' => 'Admin\ServiceController@getNew'
'uses' => 'Admin\ServiceController@getNew',
]);
$router->post('/new', [
'uses' => 'Admin\ServiceController@postNew'
'uses' => 'Admin\ServiceController@postNew',
]);
$router->get('/service/{id}', [
'as' => 'admin.services.service',
'uses' => 'Admin\ServiceController@getService'
'uses' => 'Admin\ServiceController@getService',
]);
$router->post('/service/{id}', [
'uses' => 'Admin\ServiceController@postService'
'uses' => 'Admin\ServiceController@postService',
]);
$router->delete('/service/{id}', [
'uses' => 'Admin\ServiceController@deleteService'
'uses' => 'Admin\ServiceController@deleteService',
]);
$router->get('/service/{id}/configuration', [
'as' => 'admin.services.service.config',
'uses' => 'Admin\ServiceController@getConfiguration',
]);
$router->post('/service/{id}/configuration', [
'uses' => 'Admin\ServiceController@postConfiguration',
]);
$router->get('/service/{service}/option/new', [
'as' => 'admin.services.option.new',
'uses' => 'Admin\ServiceController@newOption'
'uses' => 'Admin\ServiceController@newOption',
]);
$router->post('/service/{service}/option/new', [
'uses' => 'Admin\ServiceController@postNewOption'
'uses' => 'Admin\ServiceController@postNewOption',
]);
$router->get('/service/{service}/option/{option}', [
'as' => 'admin.services.option',
'uses' => 'Admin\ServiceController@getOption'
'uses' => 'Admin\ServiceController@getOption',
]);
$router->post('/service/{service}/option/{option}', [
'uses' => 'Admin\ServiceController@postOption'
'uses' => 'Admin\ServiceController@postOption',
]);
$router->delete('/service/{service}/option/{id}', [
'uses' => 'Admin\ServiceController@deleteOption'
'uses' => 'Admin\ServiceController@deleteOption',
]);
$router->get('/service/{service}/option/{option}/variable/new', [
'as' => 'admin.services.option.variable.new',
'uses' => 'Admin\ServiceController@getNewVariable'
'uses' => 'Admin\ServiceController@getNewVariable',
]);
$router->post('/service/{service}/option/{option}/variable/new', [
'uses' => 'Admin\ServiceController@postNewVariable'
'uses' => 'Admin\ServiceController@postNewVariable',
]);
$router->post('/service/{service}/option/{option}/variable/{variable}', [
'as' => 'admin.services.option.variable',
'uses' => 'Admin\ServiceController@postOptionVariable'
'uses' => 'Admin\ServiceController@postOptionVariable',
]);
$router->get('/service/{service}/option/{option}/variable/{variable}/delete', [
'as' => 'admin.services.option.variable.delete',
'uses' => 'Admin\ServiceController@deleteVariable'
'uses' => 'Admin\ServiceController@deleteVariable',
]);
});
// Service Packs
$router->group([
'prefix' => 'admin/services/packs',
'middleware' => [
'auth',
'admin',
'csrf',
],
], function () use ($router) {
$router->get('/new/{option?}', [
'as' => 'admin.services.packs.new',
'uses' => 'Admin\PackController@new',
]);
$router->post('/new', [
'uses' => 'Admin\PackController@create',
]);
$router->get('/upload/{option?}', [
'as' => 'admin.services.packs.uploadForm',
'uses' => 'Admin\PackController@uploadForm',
]);
$router->post('/upload', [
'uses' => 'Admin\PackController@postUpload',
]);
$router->get('/', [
'as' => 'admin.services.packs',
'uses' => 'Admin\PackController@listAll',
]);
$router->get('/for/option/{option}', [
'as' => 'admin.services.packs.option',
'uses' => 'Admin\PackController@listByOption',
]);
$router->get('/for/service/{service}', [
'as' => 'admin.services.packs.service',
'uses' => 'Admin\PackController@listByService',
]);
$router->get('/edit/{pack}', [
'as' => 'admin.services.packs.edit',
'uses' => 'Admin\PackController@edit',
]);
$router->post('/edit/{pack}', [
'uses' => 'Admin\PackController@update',
]);
$router->get('/edit/{pack}/export/{archive?}', [
'as' => 'admin.services.packs.export',
'uses' => 'Admin\PackController@export',
]);
});
}
}

View file

@ -1,8 +1,8 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* Some Modifications (c) 2015 Dylan Seidt <dylan.seidt@gmail.com>
* 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
@ -22,71 +22,69 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Http\Routes;
use Illuminate\Routing\Router;
use Request;
use Pterodactyl\Models\User as User;
use Auth;
class AuthRoutes {
use Illuminate\Routing\Router;
public function map(Router $router) {
class AuthRoutes
{
public function map(Router $router)
{
$router->group([
'prefix' => 'auth',
'middleware' => [
'guest',
'csrf'
]
'csrf',
],
], function () use ($router) {
// Display Login Page
$router->get('login', [
'as' => 'auth.login',
'uses' => 'Auth\LoginController@showLoginForm'
'uses' => 'Auth\LoginController@showLoginForm',
]);
// Handle Login
$router->post('login', [
'uses' => 'Auth\LoginController@login'
'uses' => 'Auth\LoginController@login',
]);
// Determine if we need to ask for a TOTP Token
$router->post('login/totp', [
'uses' => 'Auth\LoginController@checkTotp'
'uses' => 'Auth\LoginController@checkTotp',
]);
// Show Password Reset Form
$router->get('password', [
'as' => 'auth.password',
'uses' => 'Auth\ForgotPasswordController@showLinkRequestForm'
'uses' => 'Auth\ForgotPasswordController@showLinkRequestForm',
]);
// Handle Password Reset
$router->post('password', [
'uses' => 'Auth\ForgotPasswordController@sendResetLinkEmail'
'uses' => 'Auth\ForgotPasswordController@sendResetLinkEmail',
]);
// Show Verification Checkpoint
$router->get('password/reset/{token}', [
'as' => 'auth.reset',
'uses' => 'Auth\ResetPasswordController@showResetForm'
'uses' => 'Auth\ResetPasswordController@showResetForm',
]);
// Handle Verification
$router->post('password/reset', [
'uses' => 'Auth\ResetPasswordController@reset'
'as' => 'auth.reset.post',
'uses' => 'Auth\ResetPasswordController@reset',
]);
});
// Not included above because we don't want the guest middleware
$router->get('auth/logout', [
'as' => 'auth.logout',
'middleware' => 'auth',
'uses' => 'Auth\LoginController@logout'
'uses' => 'Auth\LoginController@logout',
]);
}
}

View file

@ -1,8 +1,8 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* Some Modifications (c) 2015 Dylan Seidt <dylan.seidt@gmail.com>
* 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
@ -22,19 +22,21 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Http\Routes;
use Illuminate\Routing\Router;
class BaseRoutes {
public function map(Router $router) {
class BaseRoutes
{
public function map(Router $router)
{
// Index of Panel
$router->get('/', [
'as' => 'index',
'middleware' => 'auth',
'uses' => 'Base\IndexController@getIndex'
'uses' => 'Base\IndexController@getIndex',
]);
// Handle Index. Redirect /index to /
@ -46,7 +48,7 @@ class BaseRoutes {
$router->get('/password-gen/{length}', [
'as' => 'password-gen',
'middleware' => 'auth',
'uses' => 'Base\IndexController@getPassword'
'uses' => 'Base\IndexController@getPassword',
]);
// Account Routes
@ -54,18 +56,15 @@ class BaseRoutes {
'prefix' => 'account',
'middleware' => [
'auth',
'csrf'
]
'csrf',
],
], function () use ($router) {
$router->get('/', [
'as' => 'account',
'uses' => 'Base\AccountController@index'
'uses' => 'Base\AccountController@index',
]);
$router->post('/password', [
'uses' => 'Base\AccountController@password'
]);
$router->post('/email', [
'uses' => 'Base\AccountController@email'
$router->post('/', [
'uses' => 'Base\AccountController@update',
]);
});
@ -74,23 +73,23 @@ class BaseRoutes {
'prefix' => 'account/api',
'middleware' => [
'auth',
'csrf'
]
'csrf',
],
], function () use ($router) {
$router->get('/', [
'as' => 'account.api',
'uses' => 'Base\APIController@index'
'uses' => 'Base\APIController@index',
]);
$router->get('/new', [
'as' => 'account.api.new',
'uses' => 'Base\APIController@new'
'uses' => 'Base\APIController@create',
]);
$router->post('/new', [
'uses' => 'Base\APIController@save'
'uses' => 'Base\APIController@save',
]);
$router->delete('/revoke/{key}', [
'uses' => 'Base\APIController@revoke'
'uses' => 'Base\APIController@revoke',
]);
});
@ -99,28 +98,27 @@ class BaseRoutes {
'prefix' => 'account/security',
'middleware' => [
'auth',
'csrf'
]
'csrf',
],
], function () use ($router) {
$router->get('/', [
'as' => 'account.security',
'uses' => 'Base\SecurityController@index'
'uses' => 'Base\SecurityController@index',
]);
$router->get('/revoke/{id}', [
'as' => 'account.security.revoke',
'uses' => 'Base\SecurityController@revoke'
'uses' => 'Base\SecurityController@revoke',
]);
$router->put('/totp', [
'uses' => 'Base\SecurityController@generateTotp'
'as' => 'account.security.totp',
'uses' => 'Base\SecurityController@generateTotp',
]);
$router->post('/totp', [
'uses' => 'Base\SecurityController@setTotp'
'uses' => 'Base\SecurityController@setTotp',
]);
$router->delete('/totp', [
'uses' => 'Base\SecurityController@disableTotp'
'uses' => 'Base\SecurityController@disableTotp',
]);
});
}
}

View file

@ -0,0 +1,54 @@
<?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\Http\Routes;
use Illuminate\Routing\Router;
class DaemonRoutes
{
public function map(Router $router)
{
$router->group(['prefix' => 'daemon', 'middleware' => 'daemon'], function () use ($router) {
$router->get('services', [
'as' => 'daemon.services',
'uses' => 'Daemon\ServiceController@list',
]);
$router->get('services/pull/{service}/{file}', [
'as' => 'remote.install',
'uses' => 'Daemon\ServiceController@pull',
]);
$router->get('packs/pull/{uuid}', [
'as' => 'daemon.pack.pull',
'uses' => 'Daemon\PackController@pull',
]);
$router->get('packs/pull/{uuid}/hash', [
'as' => 'daemon.pack.hash',
'uses' => 'Daemon\PackController@hash',
]);
});
}
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,18 +21,18 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Http\Routes;
use Illuminate\Routing\Router;
class LanguageRoutes {
class LanguageRoutes
{
public function map(Router $router)
{
$router->get('language/{lang}', [
'as' => 'langauge.set',
'uses' => 'Base\LanguageController@setLanguage'
'uses' => 'Base\LanguageController@setLanguage',
]);
}
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,31 +21,31 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Http\Routes;
use Illuminate\Routing\Router;
use Request;
class RemoteRoutes {
public function map(Router $router) {
class RemoteRoutes
{
public function map(Router $router)
{
$router->group(['prefix' => 'remote'], function () use ($router) {
// Handles Remote Download Authentication Requests
$router->post('download', [
'as' => 'remote.download',
'uses' => 'Remote\RemoteController@postDownload'
'uses' => 'Remote\RemoteController@postDownload',
]);
$router->post('install', [
'as' => 'remote.install',
'uses' => 'Remote\RemoteController@postInstall'
'uses' => 'Remote\RemoteController@postInstall',
]);
$router->post('event', [
'as' => 'remote.event',
'uses' => 'Remote\RemoteController@event'
$router->get('configuration/{token}', [
'as' => 'remote.configuration',
'uses' => 'Remote\RemoteController@getConfiguration',
]);
});
}
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,161 +21,170 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Http\Routes;
use Illuminate\Routing\Router;
class ServerRoutes {
public function map(Router $router) {
class ServerRoutes
{
public function map(Router $router)
{
$router->group([
'prefix' => 'server/{server}',
'middleware' => [
'auth',
'server',
'csrf'
]
'csrf',
],
], function ($server) use ($router) {
// Index View for Server
$router->get('/', [
'as' => 'server.index',
'uses' => 'Server\ServerController@getIndex'
'uses' => 'Server\ServerController@getIndex',
]);
// Settings
$router->get('/settings', [
'as' => 'server.settings',
'uses' => 'Server\ServerController@getSettings'
'uses' => 'Server\ServerController@getSettings',
]);
$router->get('/settings/databases', [
'as' => 'server.settings.databases',
'uses' => 'Server\ServerController@getDatabases',
]);
$router->get('/settings/sftp', [
'as' => 'server.settings.sftp',
'uses' => 'Server\ServerController@getSFTP',
]);
$router->post('/settings/sftp', [
'as' => 'server.settings.sftp',
'uses' => 'Server\ServerController@postSettingsSFTP'
'uses' => 'Server\ServerController@postSettingsSFTP',
]);
$router->get('/settings/startup', [
'as' => 'server.settings.startup',
'uses' => 'Server\ServerController@getStartup',
]);
$router->post('/settings/startup', [
'as' => 'server.settings.startup',
'uses' => 'Server\ServerController@postSettingsStartup'
'uses' => 'Server\ServerController@postSettingsStartup',
]);
$router->get('/settings/allocation', [
'as' => 'server.settings.allocation',
'uses' => 'Server\ServerController@getAllocation',
]);
// File Manager Routes
$router->get('/files', [
'as' => 'server.files.index',
'uses' => 'Server\ServerController@getFiles'
'uses' => 'Server\ServerController@getFiles',
]);
$router->get('/files/edit/{file}', [
'as' => 'server.files.edit',
'uses' => 'Server\ServerController@getEditFile'
'uses' => 'Server\ServerController@getEditFile',
])->where('file', '.*');
$router->get('/files/download/{file}', [
'as' => 'server.files.download',
'uses' => 'Server\ServerController@getDownloadFile'
'uses' => 'Server\ServerController@getDownloadFile',
])->where('file', '.*');
$router->get('/files/add', [
'as' => 'server.files.add',
'uses' => 'Server\ServerController@getAddFile'
'uses' => 'Server\ServerController@getAddFile',
]);
$router->post('files/directory-list', [
'as' => 'server.files.directory-list',
'uses' => 'Server\AjaxController@postDirectoryList'
'uses' => 'Server\AjaxController@postDirectoryList',
]);
$router->post('files/save', [
'as' => 'server.files.save',
'uses' => 'Server\AjaxController@postSaveFile'
'uses' => 'Server\AjaxController@postSaveFile',
]);
// Sub-User Routes
$router->get('users', [
'as' => 'server.subusers',
'uses' => 'Server\SubuserController@getIndex'
'uses' => 'Server\SubuserController@getIndex',
]);
$router->get('users/new', [
'as' => 'server.subusers.new',
'uses' => 'Server\SubuserController@getNew'
'uses' => 'Server\SubuserController@getNew',
]);
$router->post('users/new', [
'uses' => 'Server\SubuserController@postNew'
'uses' => 'Server\SubuserController@postNew',
]);
$router->get('users/view/{id}', [
'as' => 'server.subusers.view',
'uses' => 'Server\SubuserController@getView'
'uses' => 'Server\SubuserController@getView',
]);
$router->post('users/view/{id}', [
'uses' => 'Server\SubuserController@postView'
'uses' => 'Server\SubuserController@postView',
]);
$router->delete('users/delete/{id}', [
'uses' => 'Server\SubuserController@deleteSubuser'
'uses' => 'Server\SubuserController@deleteSubuser',
]);
$router->get('tasks/', [
'as' => 'server.tasks',
'uses' => 'Server\TaskController@getIndex'
'uses' => 'Server\TaskController@getIndex',
]);
$router->get('tasks/view/{id}', [
'as' => 'server.tasks.view',
'uses' => 'Server\TaskController@getView'
'uses' => 'Server\TaskController@getView',
]);
$router->get('tasks/new', [
'as' => 'server.tasks.new',
'uses' => 'Server\TaskController@getNew'
'uses' => 'Server\TaskController@getNew',
]);
$router->post('tasks/new', [
'uses' => 'Server\TaskController@postNew'
'uses' => 'Server\TaskController@postNew',
]);
$router->delete('tasks/delete/{id}', [
'as' => 'server.tasks.delete',
'uses' => 'Server\TaskController@deleteTask'
'uses' => 'Server\TaskController@deleteTask',
]);
$router->post('tasks/toggle/{id}', [
'as' => 'server.tasks.toggle',
'uses' => 'Server\TaskController@toggleTask'
'uses' => 'Server\TaskController@toggleTask',
]);
// Assorted AJAX Routes
$router->group(['prefix' => 'ajax'], function ($server) use ($router) {
// Returns Server Status
$router->get('status', [
'uses' => 'Server\AjaxController@getStatus'
'as' => 'server.ajax.status',
'uses' => 'Server\AjaxController@getStatus',
]);
// Sets the Default Connection for the Server
$router->post('set-primary', [
'uses' => 'Server\AjaxController@postSetPrimary'
'uses' => 'Server\AjaxController@postSetPrimary',
]);
$router->post('settings/reset-database-password', [
'as' => 'server.ajax.reset-database-password',
'uses' => 'Server\AjaxController@postResetDatabasePassword'
'uses' => 'Server\AjaxController@postResetDatabasePassword',
]);
});
// Assorted AJAX Routes
$router->group(['prefix' => 'js'], function ($server) use ($router) {
// Returns Server Status
$router->get('{folder}/{file}', [
'as' => 'server.js',
'uses' => 'Server\ServerController@getJavascript'
])->where('file', '.*');
});
});
}
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,16 +21,12 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Jobs;
use DB;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Pterodactyl\Models;
use Pterodactyl\Repositories\ServerRepository;
class DeleteServer extends Job implements ShouldQueue
@ -46,7 +42,7 @@ class DeleteServer extends Job implements ShouldQueue
/**
* Create a new job instance.
*
* @param integer $server
* @param int $server
* @return void
*/
public function __construct($id)

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,19 +21,17 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Jobs;
use Pterodactyl\Jobs\Job;
use Cron;
use Carbon;
use Pterodactyl\Models;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use DB;
use Carbon;
use Cron;
use Pterodactyl\Models;
use Pterodactyl\Repositories\Daemon\CommandRepository;
use Pterodactyl\Repositories\Daemon\PowerRepository;
use Pterodactyl\Repositories\Daemon\CommandRepository;
class SendScheduledTask extends Job implements ShouldQueue
{
@ -76,7 +74,7 @@ class SendScheduledTask extends Job implements ShouldQueue
if ($this->task->action === 'command') {
$repo = new CommandRepository($this->server);
$response = $repo->send($this->task->data);
} else if ($this->task->action === 'power') {
} elseif ($this->task->action === 'power') {
$repo = new PowerRepository($this->server);
$response = $repo->do($this->task->data);
}
@ -84,14 +82,14 @@ class SendScheduledTask extends Job implements ShouldQueue
'task_id' => $this->task->id,
'run_time' => $time,
'run_status' => 0,
'response' => $response
'response' => $response,
]);
} catch (\Exception $ex) {
$log->fill([
'task_id' => $this->task->id,
'run_time' => $time,
'run_status' => 1,
'response' => $ex->getMessage()
'response' => $ex->getMessage(),
]);
} finally {
$cron = Cron::factory(sprintf('%s %s %s %s %s %s',
@ -105,7 +103,7 @@ class SendScheduledTask extends Job implements ShouldQueue
$this->task->fill([
'last_run' => $time,
'next_run' => $cron->getNextRunDate(),
'queued' => 0
'queued' => 0,
]);
$this->task->save();
$log->save();

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,14 +21,12 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Jobs;
use Debugbar;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Pterodactyl\Repositories\ServerRepository;
class SuspendServer extends Job implements ShouldQueue
@ -44,7 +42,7 @@ class SuspendServer extends Job implements ShouldQueue
/**
* Create a new job instance.
*
* @param integer $id
* @param int $id
* @return void
*/
public function __construct($id)

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,13 +21,13 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Models;
use Illuminate\Database\Eloquent\Model;
class APIKey extends Model
{
/**
* The table associated with the model.
*
@ -48,5 +48,4 @@ class APIKey extends Model
* @var array
*/
protected $guarded = ['id', 'created_at', 'updated_at'];
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,13 +21,13 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Models;
use Illuminate\Database\Eloquent\Model;
class APILog extends Model
{
/**
* The table associated with the model.
*
@ -49,13 +49,12 @@ class APILog extends Model
*/
protected $guarded = ['id', 'created_at', 'updated_at'];
/**
* Cast values to correct type.
*
* @var array
*/
/**
* Cast values to correct type.
*
* @var array
*/
protected $casts = [
'authorized' => 'boolean'
'authorized' => 'boolean',
];
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,13 +21,13 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Models;
use Illuminate\Database\Eloquent\Model;
class APIPermission extends Model
{
/**
* The table associated with the model.
*
@ -42,11 +42,11 @@ class APIPermission extends Model
*/
protected $guarded = ['id'];
/**
* Cast values to correct type.
*
* @var array
*/
/**
* Cast values to correct type.
*
* @var array
*/
protected $casts = [
'key_id' => 'integer',
];
@ -54,8 +54,7 @@ class APIPermission extends Model
/**
* Disable timestamps for this table.
*
* @var boolean
* @var bool
*/
public $timestamps = false;
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,13 +21,13 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Models;
use Illuminate\Database\Eloquent\Model;
class Allocation extends Model
{
/**
* The table associated with the model.
*
@ -42,15 +42,14 @@ class Allocation extends Model
*/
protected $guarded = ['id', 'created_at', 'updated_at'];
/**
* Cast values to correct type.
*
* @var array
*/
/**
* Cast values to correct type.
*
* @var array
*/
protected $casts = [
'node' => 'integer',
'port' => 'integer',
'assigned_to' => 'integer',
];
}

53
app/Models/Checksum.php Normal file
View file

@ -0,0 +1,53 @@
<?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\Models;
use Illuminate\Database\Eloquent\Model;
class Checksum extends Model
{
/**
* The table associated with the model.
*
* @var string
*/
protected $table = 'checksums';
/**
* Fields that are not mass assignable.
*
* @var array
*/
protected $guarded = ['id', 'created_at', 'updated_at'];
/**
* Cast values to correct type.
*
* @var array
*/
protected $casts = [
'service' => 'integer',
];
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,13 +21,13 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Models;
use Illuminate\Database\Eloquent\Model;
class Database extends Model
{
/**
* The table associated with the model.
*
@ -49,14 +49,13 @@ class Database extends Model
*/
protected $guarded = ['id', 'created_at', 'updated_at'];
/**
* Cast values to correct type.
*
* @var array
*/
/**
* Cast values to correct type.
*
* @var array
*/
protected $casts = [
'server' => 'integer',
'db_server' => 'integer',
];
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,13 +21,13 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Models;
use Illuminate\Database\Eloquent\Model;
class DatabaseServer extends Model
{
/**
* The table associated with the model.
*
@ -49,15 +49,14 @@ class DatabaseServer extends Model
*/
protected $guarded = ['id', 'created_at', 'updated_at'];
/**
* Cast values to correct type.
*
* @var array
*/
/**
* Cast values to correct type.
*
* @var array
*/
protected $casts = [
'id' => 'integer',
'server_id' => 'integer',
'db_server' => 'integer'
'db_server' => 'integer',
];
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,19 +21,17 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Models;
use Debugbar;
use Illuminate\Database\Eloquent\Model;
class Download extends Model
{
/**
* The table associated with the model.
*
* @var string
*/
protected $table = 'downloads';
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,13 +21,13 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Models;
use Illuminate\Database\Eloquent\Model;
class Location extends Model
{
/**
* The table associated with the model.
*
@ -41,5 +41,4 @@ class Location extends Model
* @var array
*/
protected $guarded = ['id', 'created_at', 'updated_at'];
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,13 +21,16 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Models;
use GuzzleHttp\Client;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Notifications\Notifiable;
class Node extends Model
{
use Notifiable;
/**
* The table associated with the model.
@ -43,11 +46,11 @@ class Node extends Model
*/
protected $hidden = ['daemonSecret'];
/**
* Cast values to correct type.
*
* @var array
*/
/**
* Cast values to correct type.
*
* @var array
*/
protected $casts = [
'public' => 'integer',
'location' => 'integer',
@ -88,9 +91,9 @@ class Node extends Model
return self::$nodes[$id];
}
self::$nodes[$id] = Node::where('id', $id)->first();
return self::$nodes[$id];
self::$nodes[$id] = self::where('id', $id)->first();
return self::$nodes[$id];
}
/**
@ -116,7 +119,62 @@ class Node extends Model
]);
return self::$guzzle[$node];
}
/**
* Returns the configuration in JSON format.
*
* @param bool $pretty Wether to pretty print the JSON or not
* @return string The configration in JSON format
*/
public function getConfigurationAsJson($pretty = false)
{
$config = [
'web' => [
'host' => '0.0.0.0',
'listen' => $this->daemonListen,
'ssl' => [
'enabled' => $this->scheme === 'https',
'certificate' => '/etc/letsencrypt/live/' . $this->fqdn . '/fullchain.pem',
'key' => '/etc/letsencrypt/live/' . $this->fqdn . '/privkey.pem',
],
],
'docker' => [
'socket' => '/var/run/docker.sock',
'autoupdate_images' => true,
],
'sftp' => [
'path' => $this->daemonBase,
'port' => $this->daemonSFTP,
'container' => 'ptdl-sftp',
],
'query' => [
'kill_on_fail' => true,
'fail_limit' => 5,
],
'logger' => [
'path' => 'logs/',
'src' => false,
'level' => 'info',
'period' => '1d',
'count' => 3,
],
'remote' => [
'base' => config('app.url'),
'download' => route('remote.download'),
'installed' => route('remote.install'),
],
'uploads' => [
'size_limit' => $this->upload_size,
],
'keys' => [$this->daemonSecret],
];
$json_options = JSON_UNESCAPED_SLASHES;
if ($pretty) {
$json_options |= JSON_PRETTY_PRINT;
}
return json_encode($config, $json_options);
}
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,20 +21,31 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
return [
/*
|--------------------------------------------------------------------------
| Password Reminder Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are the default lines which match reasons
| that are given by the password broker for a password update attempt
| has failed, such as for an invalid token or invalid new password.
|
*/
'password' => 'Senhas precisam ter ao menos 6 caracteres e combinar com a confirmação.',
'reset' => 'Sua senha foi resetada!',
'sent' => 'Nós te enviamos um email com o link para resetar sua senha!',
'token' => 'O token para resetar esta senha é inválido.',
'user' => "Nós não pudemos achar um usuário com este endereço de email.",
];
namespace Pterodactyl\Models;
use Illuminate\Database\Eloquent\Model;
class NodeConfigurationToken extends Model
{
/**
* The table associated with the model.
*
* @var string
*/
protected $table = 'node_configuration_tokens';
/**
* Fields that are not mass assignable.
*
* @var array
*/
protected $guarded = ['id', 'created_at', 'updated_at'];
/**
* The attributes that should be mutated to dates.
*
* @var array
*/
protected $dates = ['created_at', 'updated_at', 'expires_at'];
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,13 +21,13 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Models;
use Illuminate\Database\Eloquent\Model;
class Permission extends Model
{
/**
* The table associated with the model.
*
@ -42,11 +42,11 @@ class Permission extends Model
*/
protected $guarded = ['id', 'created_at', 'updated_at'];
/**
* Cast values to correct type.
*
* @var array
*/
/**
* Cast values to correct type.
*
* @var array
*/
protected $casts = [
'user_id' => 'integer',
'server_id' => 'integer',
@ -61,5 +61,4 @@ class Permission extends Model
{
return $query->where('server_id', $server->id);
}
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,19 +21,17 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Models;
use Auth;
use Pterodactyl\Models\Subuser;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Eloquent\SoftDeletes;
use Pterodactyl\Exceptions\DisplayException;
class Server extends Model
{
use SoftDeletes;
use Notifiable, SoftDeletes;
/**
* The table associated with the model.
@ -63,11 +61,11 @@ class Server extends Model
*/
protected $guarded = ['id', 'installed', 'created_at', 'updated_at', 'deleted_at'];
/**
* Cast values to correct type.
*
* @var array
*/
/**
* Cast values to correct type.
*
* @var array
*/
protected $casts = [
'node' => 'integer',
'suspended' => 'integer',
@ -95,7 +93,7 @@ class Server extends Model
protected static $user;
/**
* Constructor
* Constructor.
*/
public function __construct()
{
@ -112,7 +110,6 @@ class Server extends Model
*/
public static function getUserDaemonSecret(Server $server)
{
if (self::$user->id === $server->owner || self::$user->root_admin === 1) {
return $server->daemonSecret;
}
@ -124,7 +121,6 @@ class Server extends Model
}
return $subuser->daemonSecret;
}
/**
@ -135,7 +131,6 @@ class Server extends Model
*/
public static function getUserServers($paginate = null)
{
$query = self::select(
'servers.*',
'nodes.name as nodeName',
@ -160,7 +155,6 @@ class Server extends Model
}
return $query->get();
}
/**
@ -173,7 +167,6 @@ class Server extends Model
*/
public static function getByUUID($uuid)
{
if (array_key_exists($uuid, self::$serverUUIDInstance)) {
return self::$serverUUIDInstance[$uuid];
}
@ -189,33 +182,30 @@ class Server extends Model
$result = $query->first();
if(!is_null($result)) {
if (! is_null($result)) {
$result->daemonSecret = self::getUserDaemonSecret($result);
}
self::$serverUUIDInstance[$uuid] = $result;
return self::$serverUUIDInstance[$uuid];
return self::$serverUUIDInstance[$uuid];
}
/**
* Returns non-administrative headers for accessing a server on Scales
* Returns non-administrative headers for accessing a server on the daemon.
*
* @param string $uuid
* @return array
*/
public static function getGuzzleHeaders($uuid)
{
if (array_key_exists($uuid, self::$serverUUIDInstance)) {
return [
'X-Access-Server' => self::$serverUUIDInstance[$uuid]->uuid,
'X-Access-Token' => self::$serverUUIDInstance[$uuid]->daemonSecret
'X-Access-Token' => self::$serverUUIDInstance[$uuid]->daemonSecret,
];
}
return [];
}
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,13 +21,13 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Models;
use Illuminate\Database\Eloquent\Model;
class ServerVariables extends Model
{
/**
* The table associated with the model.
*
@ -42,14 +42,13 @@ class ServerVariables extends Model
*/
protected $guarded = ['id', 'created_at', 'updated_at'];
/**
* Cast values to correct type.
*
* @var array
*/
/**
* Cast values to correct type.
*
* @var array
*/
protected $casts = [
'server_id' => 'integer',
'variable_id' => 'integer',
];
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,13 +21,13 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Models;
use Illuminate\Database\Eloquent\Model;
class Service extends Model
{
/**
* The table associated with the model.
*
@ -41,5 +41,4 @@ class Service extends Model
* @var array
*/
protected $guarded = ['id', 'created_at', 'updated_at'];
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,13 +21,13 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Models;
use Illuminate\Database\Eloquent\Model;
class ServiceOptions extends Model
{
/**
* The table associated with the model.
*
@ -42,13 +42,22 @@ class ServiceOptions extends Model
*/
protected $guarded = ['id', 'created_at', 'updated_at'];
/**
* Cast values to correct type.
*
* @var array
*/
/**
* Cast values to correct type.
*
* @var array
*/
protected $casts = [
'parent_service' => 'integer',
];
/**
* Gets all variables associated with this service.
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function variables()
{
return $this->hasMany(ServiceVariables::class, 'option_id');
}
}

View file

@ -0,0 +1,59 @@
<?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\Models;
use Illuminate\Database\Eloquent\Model;
class ServicePack extends Model
{
/**
* The table associated with the model.
*
* @var string
*/
protected $table = 'service_packs';
/**
* Fields that are not mass assignable.
*
* @var array
*/
protected $guarded = ['id', 'created_at', 'updated_at'];
/**
* Cast values to correct type.
*
* @var array
*/
protected $casts = [
'option' => 'integer',
'build_memory' => 'integer',
'build_swap' => 'integer',
'build_cpu' => 'integer',
'build_io' => 'integer',
'selectable' => 'boolean',
'visible' => 'boolean',
];
}

View file

@ -1,7 +1,7 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com>
* 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
@ -21,13 +21,13 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
namespace Pterodactyl\Models;
use Illuminate\Database\Eloquent\Model;
class ServiceVariables extends Model
{
/**
* The table associated with the model.
*
@ -42,16 +42,15 @@ class ServiceVariables extends Model
*/
protected $guarded = ['id', 'created_at', 'updated_at'];
/**
* Cast values to correct type.
*
* @var array
*/
/**
* Cast values to correct type.
*
* @var array
*/
protected $casts = [
'option_id' => 'integer',
'user_viewable' => 'integer',
'user_editable' => 'integer',
'required' => 'integer',
];
}

Some files were not shown because too many files have changed in this diff Show more