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_ENV=production
APP_DEBUG=false APP_DEBUG=false
APP_KEY=SomeRandomString3232RandomString APP_KEY=SomeRandomString3232RandomString
APP_THEME=default APP_THEME=pterodactyl
APP_TIMEZONE=UTC APP_TIMEZONE=UTC
APP_CLEAR_TASKLOG=720 APP_CLEAR_TASKLOG=720
APP_DELETE_MINUTES=10 APP_DELETE_MINUTES=10
CONSOLE_PUSH_FREQ=250 APP_URL=http://yoursite.com/
CONSOLE_PUSH_COUNT=10
DB_HOST=localhost DB_HOST=localhost
DB_PORT=3306 DB_PORT=3306

View file

@ -1,61 +1,6 @@
<!-- The checkboxes below can be clicked once you submit this report if you'd like --> 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.
<!-- You can also use "- [x]" to mark it as checked. -->
## Product
Please check the corresponding boxes below for which products this is about.
- [ ] Panel If you're just making a suggestion, be descriptive, and link to any issues that might be releated as well.
- [ ] Daemon
- [ ] Dockerfile(s) [Please list if so: __ ]
## Type You can delete from this line up.
- [ ] 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
```

3
.gitignore vendored
View file

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

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. 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) ## v0.5.0 (Bodacious Boreopterus)
After nearly a month in the works, version `v0.5.0` is finally here! 🎉 After nearly a month in the works, version `v0.5.0` is finally here! 🎉

View file

@ -1,7 +1,7 @@
# The MIT License (MIT) # 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 Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal 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 ## 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 Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal 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) 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/) 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/) 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/) 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 - [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/) 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) 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 <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Console\Commands; namespace Pterodactyl\Console\Commands;
use DB; use DB;
use Illuminate\Console\Command; use Illuminate\Console\Command;
class ClearServices extends Command class ClearServices extends Command
@ -60,8 +60,7 @@ class ClearServices extends Command
*/ */
public function handle() 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.'); $this->error('Canceling.');
exit(); exit();
} }

View file

@ -1,7 +1,7 @@
<?php <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Console\Commands; namespace Pterodactyl\Console\Commands;
use DB;
use Carbon; use Carbon;
use Pterodactyl\Models; use Pterodactyl\Models;
use Illuminate\Console\Command; use Illuminate\Console\Command;
use Illuminate\Foundation\Bus\DispatchesJobs; use Illuminate\Foundation\Bus\DispatchesJobs;
use Pterodactyl\Jobs\SendScheduledTask;
class ClearTasks extends Command class ClearTasks extends Command
{ {
use DispatchesJobs; use DispatchesJobs;
/** /**

View file

@ -28,6 +28,6 @@ class Inspire extends Command
*/ */
public function handle() 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 <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Console\Commands; namespace Pterodactyl\Console\Commands;
use Hash;
use Illuminate\Console\Command; use Illuminate\Console\Command;
use Pterodactyl\Repositories\UserRepository; use Pterodactyl\Repositories\UserRepository;
class MakeUser extends Command class MakeUser extends Command
@ -36,6 +35,9 @@ class MakeUser extends Command
* @var string * @var string
*/ */
protected $signature = 'pterodactyl:user 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.} {--email= : Email address to use for this account.}
{--password= : Password to assign to the user.} {--password= : Password to assign to the user.}
{--admin= : Boolean flag for if user should be an admin.}'; {--admin= : Boolean flag for if user should be an admin.}';
@ -64,19 +66,23 @@ class MakeUser extends Command
*/ */
public function handle() public function handle()
{ {
$email = is_null($this->option('email')) ? $this->ask('Email') : $this->option('email'); $data['name_first'] = is_null($this->option('firstname')) ? $this->ask('First Name') : $this->option('firstname');
$password = is_null($this->option('password')) ? $this->secret('Password') : $this->option('password'); $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'); $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!'); 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 { try {
$user = new UserRepository; $user = new UserRepository;
$user->create($email, $password, $admin); $user->create($data);
return $this->info('User successfully created.'); return $this->info('User successfully created.');
} catch (\Exception $ex) { } catch (\Exception $ex) {
return $this->error($ex->getMessage()); return $this->error($ex->getMessage());

View file

@ -1,7 +1,7 @@
<?php <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Console\Commands; namespace Pterodactyl\Console\Commands;
use DB;
use Carbon; use Carbon;
use Pterodactyl\Models; use Pterodactyl\Models;
use Illuminate\Console\Command; use Illuminate\Console\Command;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Pterodactyl\Jobs\SendScheduledTask; use Pterodactyl\Jobs\SendScheduledTask;
use Illuminate\Foundation\Bus\DispatchesJobs;
class RunTasks extends Command class RunTasks extends Command
{ {
use DispatchesJobs; use DispatchesJobs;
/** /**

View file

@ -1,7 +1,7 @@
<?php <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Console\Commands; namespace Pterodactyl\Console\Commands;
use Version;
use Illuminate\Console\Command; use Illuminate\Console\Command;
class ShowVersion extends Command class ShowVersion extends Command
@ -58,6 +60,6 @@ class ShowVersion extends Command
*/ */
public function handle() 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 <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Console\Commands; namespace Pterodactyl\Console\Commands;
use Illuminate\Console\Command; use Illuminate\Console\Command;
@ -66,7 +67,7 @@ class UpdateEmailSettings extends Command
{ {
$variables = []; $variables = [];
$file = base_path() . '/.env'; $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.'); $this->error('Missing environment file! It appears that you have not installed this panel correctly.');
exit(); exit();
} }
@ -75,35 +76,35 @@ class UpdateEmailSettings extends Command
$this->table([ $this->table([
'Option', 'Option',
'Description' 'Description',
], [ ], [
[ [
'smtp', 'smtp',
'SMTP Server Email' 'SMTP Server Email',
], ],
[ [
'mail', 'mail',
'PHP\'s Internal Mail Server' 'PHP\'s Internal Mail Server',
], ],
[ [
'mailgun', 'mailgun',
'Mailgun Email Service' 'Mailgun Email Service',
], ],
[ [
'mandrill', 'mandrill',
'Mandrill Transactional Email Service' 'Mandrill Transactional Email Service',
], ],
[ [
'postmark', '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?', [ $variables['MAIL_DRIVER'] = is_null($this->option('driver')) ? $this->choice('Which email driver would you like to use?', [
'smtp', 'smtp',
'mail', 'mail',
'mailgun', 'mailgun',
'mandrill', 'mandrill',
'postmark' 'postmark',
]) : $this->option('driver'); ]) : $this->option('driver');
switch ($variables['MAIL_DRIVER']) { switch ($variables['MAIL_DRIVER']) {

View file

@ -1,7 +1,7 @@
<?php <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Console\Commands; namespace Pterodactyl\Console\Commands;
use Uuid; use Uuid;
@ -66,10 +67,9 @@ class UpdateEnvironment extends Command
*/ */
public function handle() public function handle()
{ {
$variables = []; $variables = [];
$file = base_path() . '/.env'; $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.'); $this->error('Missing environment file! It appears that you have not installed this panel correctly.');
exit(); exit();
} }
@ -77,12 +77,12 @@ class UpdateEnvironment extends Command
$envContents = file_get_contents($file); $envContents = file_get_contents($file);
$this->info('Simply leave blank and press enter to fields that you do not wish to update.'); $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.'); $this->info('No service author set, setting one now.');
$variables['SERVICE_AUTHOR'] = env('SERVICE_AUTHOR', (string) Uuid::generate(4)); $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.'); $this->info('Setting default queue settings.');
$variables['QUEUE_DRIVER'] = env('QUEUE_DRIVER', 'database'); $variables['QUEUE_DRIVER'] = env('QUEUE_DRIVER', 'database');
$variables['QUEUE_HIGH'] = env('QUEUE_HIGH', 'high'); $variables['QUEUE_HIGH'] = env('QUEUE_HIGH', 'high');
@ -91,25 +91,25 @@ class UpdateEnvironment extends Command
} }
if (is_null($this->option('dbhost'))) { 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 { } else {
$variables['DB_HOST'] = $this->option('dbhost'); $variables['DB_HOST'] = $this->option('dbhost');
} }
if (is_null($this->option('dbport'))) { 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 { } else {
$variables['DB_PORT'] = $this->option('dbport'); $variables['DB_PORT'] = $this->option('dbport');
} }
if (is_null($this->option('dbname'))) { 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 { } else {
$variables['DB_DATABASE'] = $this->option('dbname'); $variables['DB_DATABASE'] = $this->option('dbname');
} }
if (is_null($this->option('dbuser'))) { 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 { } else {
$variables['DB_USERNAME'] = $this->option('dbuser'); $variables['DB_USERNAME'] = $this->option('dbuser');
} }
@ -122,7 +122,7 @@ class UpdateEnvironment extends Command
} }
if (is_null($this->option('url'))) { 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 { } else {
$variables['APP_URL'] = $this->option('url'); $variables['APP_URL'] = $this->option('url');
} }

View file

@ -21,6 +21,9 @@ class Kernel extends ConsoleKernel
\Pterodactyl\Console\Commands\ClearTasks::class, \Pterodactyl\Console\Commands\ClearTasks::class,
\Pterodactyl\Console\Commands\ClearServices::class, \Pterodactyl\Console\Commands\ClearServices::class,
\Pterodactyl\Console\Commands\UpdateEmailSettings::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')->everyMinute()->withoutOverlapping();
$schedule->command('pterodactyl:tasks:clearlog')->twiceDaily(3, 15); $schedule->command('pterodactyl:tasks:clearlog')->twiceDaily(3, 15);
$schedule->command('pterodactyl:cleanservices')->twiceDaily(1, 13);
} }
} }

View file

@ -1,7 +1,7 @@
<?php <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Events;
namespace Pterodactyl\Events\Server;
use Pterodactyl\Models\Server;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
class ServerDeleted class Created
{ {
use SerializesModels; use SerializesModels;
@ -36,9 +38,8 @@ class ServerDeleted
* *
* @return void * @return void
*/ */
public function __construct($id) public function __construct(Server $server)
{ {
$this->server = $id; $this->server = $server;
} }
} }

View file

@ -1,8 +1,7 @@
<?php <?php
/** /**
* Pterodactyl - Panel * Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com> * Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
* Translated by Jakob Schrettenbrunner <dev@schrej.net>
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
return [
/* namespace Pterodactyl\Events\Server;
|--------------------------------------------------------------------------
| 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' => 'Dein Passwort muss länger als 6 Zeichen sein und mit der Wiederolung übereinstimmen.', use Pterodactyl\Models\Server;
'reset' => 'Dein Passwort wurde zurückgesetzt!', use Illuminate\Queue\SerializesModels;
'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.',
]; 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 <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Exceptions; namespace Pterodactyl\Exceptions;
class AccountNotFoundException extends \Exception class AccountNotFoundException extends \Exception
{ {
} }

View file

@ -1,7 +1,7 @@
<?php <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Exceptions; namespace Pterodactyl\Exceptions;
use Log; use Log;
class DisplayException extends \Exception class DisplayException extends \Exception
{ {
private $_logging = null; private $_logging = null;
public function __construct($message, $log = null) public function __construct($message, $log = null)
@ -44,5 +44,4 @@ class DisplayException extends \Exception
{ {
return $this->_logging; return $this->_logging;
} }
} }

View file

@ -1,7 +1,7 @@
<?php <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Exceptions; namespace Pterodactyl\Exceptions;
class DisplayValidationException extends \Exception class DisplayValidationException extends \Exception

View file

@ -3,12 +3,8 @@
namespace Pterodactyl\Exceptions; namespace Pterodactyl\Exceptions;
use Log; use Log;
use Exception; use Exception;
use DisplayException; use DisplayException;
use DisplayValidationException;
use AccountNotFoundException;
use Illuminate\Auth\AuthenticationException; use Illuminate\Auth\AuthenticationException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
@ -50,13 +46,12 @@ class Handler extends ExceptionHandler
*/ */
public function render($request, Exception $exception) public function render($request, Exception $exception)
{ {
if ($request->isXmlHttpRequest() || $request->ajax() || $request->is('remote/*')) { if ($request->expectsJson()) {
$response = response()->json([ $response = response()->json([
'error' => ($exception instanceof DisplayException) ? $exception->getMessage() : 'An unhandled error occured while attempting to process this request.' 'error' => ($exception instanceof DisplayException) ? $exception->getMessage() : 'An unhandled error occured while attempting to process this request.',
], 500); ], ($this->isHttpException($exception)) ? $exception->getStatusCode() : 500);
// parent::render() will log it, we are bypassing it in this case. parent::report($exception);
Log::error($exception);
} }
return (isset($response)) ? $response : parent::render($request, $exception); return (isset($response)) ? $response : parent::render($request, $exception);
@ -74,7 +69,7 @@ class Handler extends ExceptionHandler
if ($request->expectsJson()) { if ($request->expectsJson()) {
return response()->json(['error' => 'Unauthenticated.'], 401); return response()->json(['error' => 'Unauthenticated.'], 401);
} }
return redirect()->guest('/auth/login'); 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 <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Http\Controllers\API; namespace Pterodactyl\Http\Controllers\API;
use Dingo\Api\Routing\Helpers; use Dingo\Api\Routing\Helpers;

View file

@ -1,7 +1,7 @@
<?php <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Http\Controllers\API; namespace Pterodactyl\Http\Controllers\API;
use DB; use DB;
@ -32,14 +33,13 @@ use Pterodactyl\Models\Location;
*/ */
class LocationController extends BaseController class LocationController extends BaseController
{ {
public function __construct() public function __construct()
{ {
// //
} }
/** /**
* List All Locations * List All Locations.
* *
* Lists all locations currently on the system. * Lists all locations currently on the system.
* *
@ -47,18 +47,13 @@ class LocationController extends BaseController
* @Versions({"v1"}) * @Versions({"v1"})
* @Response(200) * @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') ->join('nodes', 'locations.id', '=', 'nodes.location')
->groupBy('locations.id') ->groupBy('locations.id')
->get(); ->get()->each(function ($location) {
$location->nodes = explode(',', $location->nodes);
foreach($locations as &$location) { })->all();
$location->nodes = explode(',', $location->nodes);
}
return $locations->toArray();
} }
} }

View file

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

View file

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

View file

@ -1,7 +1,7 @@
<?php <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Http\Controllers\API; namespace Pterodactyl\Http\Controllers\API;
use Illuminate\Http\Request;
use Pterodactyl\Models; use Pterodactyl\Models;
use Pterodactyl\Transformers\ServiceTransformer; use Illuminate\Http\Request;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/** /**
@ -35,13 +33,12 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
*/ */
class ServiceController extends BaseController class ServiceController extends BaseController
{ {
public function __construct() public function __construct()
{ {
// //
} }
public function list(Request $request) public function lists(Request $request)
{ {
return Models\Service::all()->toArray(); return Models\Service::all()->toArray();
} }
@ -49,20 +46,16 @@ class ServiceController extends BaseController
public function view(Request $request, $id) public function view(Request $request, $id)
{ {
$service = Models\Service::find($id); $service = Models\Service::find($id);
if (!$service) { if (! $service) {
throw new NotFoundHttpException('No service by that ID was found.'); 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 [ return [
'service' => $service, '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 <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Http\Controllers\API\User; namespace Pterodactyl\Http\Controllers\API\User;
use Auth;
use Dingo;
use Pterodactyl\Models; use Pterodactyl\Models;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Pterodactyl\Http\Controllers\API\BaseController; use Pterodactyl\Http\Controllers\API\BaseController;
class InfoController extends BaseController class InfoController extends BaseController
{ {
public function me(Request $request) public function me(Request $request)
{ {
$servers = Models\Server::getUserServers(); return Models\Server::getUserServers()->map(function ($server) {
$response = []; return [
foreach($servers as &$server) {
$response = array_merge($response, [[
'id' => $server->uuidShort, 'id' => $server->uuidShort,
'uuid' => $server->uuid, 'uuid' => $server->uuid,
'name' => $server->name, 'name' => $server->name,
'node' => $server->nodeName, 'node' => $server->nodeName,
'ip' => [ 'ip' => [
'set' => $server->ip, 'set' => $server->ip,
'alias' => $server->ip_alias 'alias' => $server->ip_alias,
], ],
'port' => $server->port, 'port' => $server->port,
'service' => $server->a_serviceName, 'service' => $server->a_serviceName,
'option' => $server->a_serviceOptionName 'option' => $server->a_serviceOptionName,
]]); ];
} })->all();
return $response;
} }
} }

View file

@ -1,7 +1,7 @@
<?php <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Http\Controllers\API\User; namespace Pterodactyl\Http\Controllers\API\User;
use Auth;
use Log; use Log;
use Auth;
use Pterodactyl\Models; use Pterodactyl\Models;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Pterodactyl\Http\Controllers\API\BaseController; use Pterodactyl\Http\Controllers\API\BaseController;
class ServerController extends BaseController class ServerController extends BaseController
{ {
public function info(Request $request, $uuid) public function info(Request $request, $uuid)
{ {
$server = Models\Server::getByUUID($uuid); $server = Models\Server::getByUUID($uuid);
@ -43,28 +42,29 @@ class ServerController extends BaseController
$response = $client->request('GET', '/server', [ $response = $client->request('GET', '/server', [
'headers' => [ 'headers' => [
'X-Access-Token' => $server->daemonSecret, 'X-Access-Token' => $server->daemonSecret,
'X-Access-Server' => $server->uuid 'X-Access-Server' => $server->uuid,
] ],
]); ]);
$json = json_decode($response->getBody()); $json = json_decode($response->getBody());
$daemon = [ $daemon = [
'status' => $json->status, 'status' => $json->status,
'stats' => $json->proc, 'stats' => $json->proc,
'query' => $json->query 'query' => $json->query,
]; ];
} catch (\Exception $ex) { } catch (\Exception $ex) {
$daemon = [ $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); Log::error($ex);
} }
$allocations = Models\Allocation::select('id', 'ip', 'port', 'ip_alias as alias')->where('assigned_to', $server->id)->get(); $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); $allocation->default = ($allocation->id === $server->allocation);
unset($allocation->id); unset($allocation->id);
} }
return [ return [
'uuidShort' => $server->uuidShort, 'uuidShort' => $server->uuidShort,
'uuid' => $server->uuid, 'uuid' => $server->uuid,
@ -76,23 +76,22 @@ class ServerController extends BaseController
'disk' => $server->disk, 'disk' => $server->disk,
'io' => $server->io, 'io' => $server->io,
'cpu' => $server->cpu, 'cpu' => $server->cpu,
'oom_disabled' => (bool) $server->oom_disabled 'oom_disabled' => (bool) $server->oom_disabled,
], ],
'allocations' => $allocations, 'allocations' => $allocations,
'sftp' => [ 'sftp' => [
'username' => (Auth::user()->can('view-sftp', $server)) ? $server->username : null 'username' => (Auth::user()->can('view-sftp', $server)) ? $server->username : null,
], ],
'daemon' => [ 'daemon' => [
'token' => ($request->secure()) ? $server->daemonSecret : false, 'token' => ($request->secure()) ? $server->daemonSecret : false,
'response' => $daemon 'response' => $daemon,
] ],
]; ];
} }
public function power(Request $request, $uuid) public function power(Request $request, $uuid)
{ {
$server = Models\Server::getByUUID($uuid); $server = Models\Server::getByUUID($uuid);
$node = Models\Node::getByID($server->node);
$client = Models\Node::guzzleRequest($server->node); $client = Models\Node::guzzleRequest($server->node);
Auth::user()->can('power-' . $request->input('action'), $server); Auth::user()->can('power-' . $request->input('action'), $server);
@ -100,12 +99,12 @@ class ServerController extends BaseController
$res = $client->request('PUT', '/server/power', [ $res = $client->request('PUT', '/server/power', [
'headers' => [ 'headers' => [
'X-Access-Server' => $server->uuid, 'X-Access-Server' => $server->uuid,
'X-Access-Token' => $server->daemonSecret 'X-Access-Token' => $server->daemonSecret,
], ],
'exceptions' => false, 'exceptions' => false,
'json' => [ 'json' => [
'action' => $request->input('action') 'action' => $request->input('action'),
] ],
]); ]);
if ($res->getStatusCode() !== 204) { if ($res->getStatusCode() !== 204) {

View file

@ -1,7 +1,7 @@
<?php <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Http\Controllers\API; namespace Pterodactyl\Http\Controllers\API;
use Illuminate\Http\Request;
use Dingo\Api\Exception\ResourceException;
use Pterodactyl\Models; use Pterodactyl\Models;
use Pterodactyl\Transformers\UserTransformer; use Illuminate\Http\Request;
use Pterodactyl\Repositories\UserRepository; use Dingo\Api\Exception\ResourceException;
use Pterodactyl\Exceptions\DisplayValidationException;
use Pterodactyl\Exceptions\DisplayException; use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Repositories\UserRepository;
use Pterodactyl\Exceptions\DisplayValidationException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException; use Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException;
@ -42,14 +39,12 @@ use Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException;
*/ */
class UserController extends BaseController class UserController extends BaseController
{ {
public function __construct() public function __construct()
{ {
} }
/** /**
* List All Users * List All Users.
* *
* Lists all users currently on the system. * Lists all users currently on the system.
* *
@ -60,13 +55,13 @@ class UserController extends BaseController
* }) * })
* @Response(200) * @Response(200)
*/ */
public function list(Request $request) public function lists(Request $request)
{ {
return Models\User::all()->toArray(); return Models\User::all()->toArray();
} }
/** /**
* List Specific User * List Specific User.
* *
* Lists specific fields about a user or all fields pertaining to that 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) 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'))) { if (! is_null($request->input('fields'))) {
foreach(explode(',', $request->input('fields')) as $field) { foreach (explode(',', $request->input('fields')) as $field) {
if (!empty($field)) { if (! empty($field)) {
$query->addSelect($field); $query->addSelect($field);
} }
} }
} }
try { try {
if (!$query->first()) { if (! $query->first()) {
throw new NotFoundHttpException('No user by that ID was found.'); throw new NotFoundHttpException('No user by that ID was found.');
} }
$user = $query->first(); $user = $query->first();
$userArray = $user->toArray(); $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; return $userArray;
} catch (NotFoundHttpException $ex) { } catch (NotFoundHttpException $ex) {
@ -105,11 +100,10 @@ class UserController extends BaseController
} catch (\Exception $ex) { } catch (\Exception $ex) {
throw new BadRequestHttpException('There was an issue with the fields passed in the request.'); throw new BadRequestHttpException('There was an issue with the fields passed in the request.');
} }
} }
/** /**
* Create a New User * Create a New User.
* *
* @Post("/users") * @Post("/users")
* @Versions({"v1"}) * @Versions({"v1"})
@ -128,8 +122,12 @@ class UserController extends BaseController
{ {
try { try {
$user = new UserRepository; $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')); $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) { } catch (DisplayValidationException $ex) {
throw new ResourceException('A validation error occured.', json_decode($ex->getMessage(), true)); throw new ResourceException('A validation error occured.', json_decode($ex->getMessage(), true));
} catch (DisplayException $ex) { } 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. * 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 { try {
$user = new UserRepository; $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); return Models\User::findOrFail($id);
} catch (DisplayValidationException $ex) { } catch (DisplayValidationException $ex) {
throw new ResourceException('A validation error occured.', json_decode($ex->getMessage(), true)); 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}") * @Delete("/users/{id}")
* @Versions({"v1"}) * @Versions({"v1"})
@ -191,6 +192,7 @@ class UserController extends BaseController
try { try {
$user = new UserRepository; $user = new UserRepository;
$user->delete($id); $user->delete($id);
return $this->response->noContent(); return $this->response->noContent();
} catch (DisplayException $ex) { } catch (DisplayException $ex) {
throw new ResourceException($ex->getMessage()); 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.'); throw new ServiceUnavailableHttpException('Unable to delete this user due to an error.');
} }
} }
} }

View file

@ -1,7 +1,7 @@
<?php <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Http\Controllers\Admin; namespace Pterodactyl\Http\Controllers\Admin;
use Alert; use Alert;
use Settings; use Settings;
use Validator; use Validator;
use Pterodactyl\Http\Controllers\Controller;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Pterodactyl\Http\Controllers\Controller;
class BaseController extends Controller class BaseController extends Controller
{ {
/** /**
* Controller Constructor * Controller Constructor.
*/ */
public function __construct() public function __construct()
{ {
@ -57,7 +56,7 @@ class BaseController extends Controller
'company' => 'required|between:1,256', 'company' => 'required|between:1,256',
'default_language' => 'required|alpha_dash|min:2|max:5', 'default_language' => 'required|alpha_dash|min:2|max:5',
'email_from' => 'required|email', 'email_from' => 'required|email',
'email_sender_name' => 'required|between:1,256' 'email_sender_name' => 'required|between:1,256',
]); ]);
if ($validator->fails()) { if ($validator->fails()) {
@ -70,8 +69,7 @@ class BaseController extends Controller
Settings::set('email_sender_name', $request->input('email_sender_name')); Settings::set('email_sender_name', $request->input('email_sender_name'));
Alert::success('Settings have been successfully updated.')->flash(); Alert::success('Settings have been successfully updated.')->flash();
return redirect()->route('admin.settings'); return redirect()->route('admin.settings');
} }
} }

View file

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

View file

@ -1,7 +1,7 @@
<?php <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Http\Controllers\Admin; namespace Pterodactyl\Http\Controllers\Admin;
use DB; use DB;
use Alert; use Alert;
use Pterodactyl\Models; 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 Illuminate\Http\Request;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Http\Controllers\Controller;
use Pterodactyl\Repositories\LocationRepository;
use Pterodactyl\Exceptions\DisplayValidationException;
class LocationsController extends Controller class LocationsController extends Controller
{ {
public function __construct() public function __construct()
{ {
// //
@ -50,7 +47,7 @@ class LocationsController extends Controller
'locations.*', 'locations.*',
DB::raw('(SELECT COUNT(*) FROM nodes WHERE nodes.location = locations.id) as a_nodeCount'), 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') 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') 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(); )->where('id', $id)->first();
if (!$model) { if (! $model) {
return response()->json([ return response()->json([
'error' => 'No location with that ID exists on the system.' 'error' => 'No location with that ID exists on the system.',
], 404); ], 404);
} }
if ($model->a_nodeCount > 0 || $model->a_serverCount > 0) { if ($model->a_nodeCount > 0 || $model->a_serverCount > 0) {
return response()->json([ 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); ], 422);
} }
$model->delete(); $model->delete();
return response('', 204); return response('', 204);
} }
@ -83,10 +81,11 @@ class LocationsController extends Controller
try { try {
$location = new LocationRepository; $location = new LocationRepository;
$location->edit($id, $request->all()); $location->edit($id, $request->all());
return response('', 204); return response('', 204);
} catch (DisplayValidationException $ex) { } catch (DisplayValidationException $ex) {
return response()->json([ 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); ], 422);
} catch (\Exception $ex) { } catch (\Exception $ex) {
// This gets caught and processed into JSON anyways. // This gets caught and processed into JSON anyways.
@ -99,9 +98,10 @@ class LocationsController extends Controller
try { try {
$location = new LocationRepository; $location = new LocationRepository;
$id = $location->create($request->except([ $id = $location->create($request->except([
'_token' '_token',
])); ]));
Alert::success('New location successfully added.')->flash(); Alert::success('New location successfully added.')->flash();
return redirect()->route('admin.locations'); return redirect()->route('admin.locations');
} catch (DisplayValidationException $ex) { } catch (DisplayValidationException $ex) {
return redirect()->route('admin.locations')->withErrors(json_decode($ex->getMessage()))->withInput(); return redirect()->route('admin.locations')->withErrors(json_decode($ex->getMessage()))->withInput();
@ -111,7 +111,7 @@ class LocationsController extends Controller
Log::error($ex); Log::error($ex);
Alert::danger('An unhandled exception occured while attempting to add this location. Please try again.')->flash(); Alert::danger('An unhandled exception occured while attempting to add this location. Please try again.')->flash();
} }
return redirect()->route('admin.locations')->withInput(); return redirect()->route('admin.locations')->withInput();
} }
} }

View file

@ -1,7 +1,7 @@
<?php <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Http\Controllers\Admin; namespace Pterodactyl\Http\Controllers\Admin;
use Alert;
use Debugbar;
use Log;
use DB; use DB;
use Log;
use Alert;
use Carbon;
use Validator; use Validator;
use Pterodactyl\Models; 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 Illuminate\Http\Request;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Http\Controllers\Controller;
use Pterodactyl\Repositories\NodeRepository;
use Pterodactyl\Exceptions\DisplayValidationException;
class NodesController extends Controller class NodesController extends Controller
{ {
/** /**
* Controller Constructor * Controller Constructor.
*/ */
public function __construct() public function __construct()
{ {
@ -50,7 +48,7 @@ class NodesController extends Controller
public function getScript(Request $request, $id) 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) public function getIndex(Request $request)
@ -66,13 +64,14 @@ class NodesController extends Controller
public function getNew(Request $request) 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(); Alert::warning('You must add a location before you can add a new node.')->flash();
return redirect()->route('admin.locations'); return redirect()->route('admin.locations');
} }
return view('admin.nodes.new', [ return view('admin.nodes.new', [
'locations' => Models\Location::all() 'locations' => Models\Location::all(),
]); ]);
} }
@ -81,12 +80,14 @@ class NodesController extends Controller
try { try {
$node = new NodeRepository; $node = new NodeRepository;
$new = $node->create($request->except([ $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::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', [ return redirect()->route('admin.nodes.view', [
'id' => $new, 'id' => $new,
'tab' => 'tab_allocation' 'tab' => 'tab_allocation',
]); ]);
} catch (DisplayValidationException $e) { } catch (DisplayValidationException $e) {
return redirect()->route('admin.nodes.new')->withErrors(json_decode($e->getMessage()))->withInput(); return redirect()->route('admin.nodes.new')->withErrors(json_decode($e->getMessage()))->withInput();
@ -96,6 +97,7 @@ class NodesController extends Controller
Log::error($e); Log::error($e);
Alert::danger('An unhandled exception occured while attempting to add this node. Please try again.')->flash(); Alert::danger('An unhandled exception occured while attempting to add this node. Please try again.')->flash();
} }
return redirect()->route('admin.nodes.new')->withInput(); return redirect()->route('admin.nodes.new')->withInput();
} }
@ -129,12 +131,13 @@ class NodesController extends Controller
try { try {
$node = new NodeRepository; $node = new NodeRepository;
$node->update($id, $request->except([ $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(); 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', [ return redirect()->route('admin.nodes.view', [
'id' => $id, 'id' => $id,
'tab' => 'tab_settings' 'tab' => 'tab_settings',
]); ]);
} catch (DisplayValidationException $e) { } catch (DisplayValidationException $e) {
return redirect()->route('admin.nodes.view', $id)->withErrors(json_decode($e->getMessage()))->withInput(); return redirect()->route('admin.nodes.view', $id)->withErrors(json_decode($e->getMessage()))->withInput();
@ -144,9 +147,10 @@ class NodesController extends Controller
Log::error($e); Log::error($e);
Alert::danger('An unhandled exception occured while attempting to edit this node. Please try again.')->flash(); Alert::danger('An unhandled exception occured while attempting to edit this node. Please try again.')->flash();
} }
return redirect()->route('admin.nodes.view', [ return redirect()->route('admin.nodes.view', [
'id' => $id, 'id' => $id,
'tab' => 'tab_settings' 'tab' => 'tab_settings',
])->withInput(); ])->withInput();
} }
@ -155,9 +159,10 @@ class NodesController extends Controller
$query = Models\Allocation::where('node', $node)->whereNull('assigned_to')->where('id', $allocation)->delete(); $query = Models\Allocation::where('node', $node)->whereNull('assigned_to')->where('id', $allocation)->delete();
if ((int) $query === 0) { if ((int) $query === 0) {
return response()->json([ 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); ], 400);
} }
return response('', 204); 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(); $query = Models\Allocation::where('node', $node)->whereNull('assigned_to')->where('ip', $request->input('ip'))->delete();
if ((int) $query === 0) { if ((int) $query === 0) {
Alert::danger('There was an error while attempting to delete allocations on that IP.')->flash(); Alert::danger('There was an error while attempting to delete allocations on that IP.')->flash();
return redirect()->route('admin.nodes.view', [ return redirect()->route('admin.nodes.view', [
'id' => $node, 'id' => $node,
'tab' => 'tab_allocations' 'tab' => 'tab_allocations',
]); ]);
} }
Alert::success('Deleted all unallocated ports for <code>' . $request->input('ip') . '</code>.')->flash(); Alert::success('Deleted all unallocated ports for <code>' . $request->input('ip') . '</code>.')->flash();
return redirect()->route('admin.nodes.view', [ return redirect()->route('admin.nodes.view', [
'id' => $node, 'id' => $node,
'tab' => 'tab_allocation' 'tab' => 'tab_allocation',
]); ]);
} }
public function setAlias(Request $request, $node) public function setAlias(Request $request, $node)
{ {
if (!$request->input('allocation')) { if (! $request->input('allocation')) {
return response('Missing required parameters.', 422); return response('Missing required parameters.', 422);
} }
@ -198,36 +205,36 @@ class NodesController extends Controller
public function getAllocationsJson(Request $request, $id) public function getAllocationsJson(Request $request, $id)
{ {
$allocations = Models\Allocation::select('ip')->where('node', $id)->groupBy('ip')->get(); $allocations = Models\Allocation::select('ip')->where('node', $id)->groupBy('ip')->get();
return response()->json($allocations); return response()->json($allocations);
} }
public function postAllocations(Request $request, $id) public function postAllocations(Request $request, $id)
{ {
$validator = Validator::make($request->all(), [ $validator = Validator::make($request->all(), [
'allocate_ip.*' => 'required|string', 'allocate_ip.*' => 'required|string',
'allocate_port.*' => 'required' 'allocate_port.*' => 'required',
]); ]);
if ($validator->fails()) { if ($validator->fails()) {
return redirect()->route('admin.nodes.view', [ return redirect()->route('admin.nodes.view', [
'id' => $id, 'id' => $id,
'tab' => 'tab_allocation' 'tab' => 'tab_allocation',
])->withErrors($validator->errors())->withInput(); ])->withErrors($validator->errors())->withInput();
} }
$processedData = []; $processedData = [];
foreach($request->input('allocate_ip') as $ip) { foreach ($request->input('allocate_ip') as $ip) {
if (!array_key_exists($ip, $processedData)) { if (! array_key_exists($ip, $processedData)) {
$processedData[$ip] = []; $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'))) { if (array_key_exists($portid, $request->input('allocate_ip'))) {
$json = json_decode($ports); $json = json_decode($ports);
if (json_last_error() === 0 && !empty($json)) { if (json_last_error() === 0 && ! empty($json)) {
foreach($json as &$parsed) { foreach ($json as &$parsed) {
array_push($processedData[$request->input('allocate_ip')[$portid]], $parsed->value); array_push($processedData[$request->input('allocate_ip')[$portid]], $parsed->value);
} }
} }
@ -246,27 +253,49 @@ class NodesController extends Controller
} finally { } finally {
return redirect()->route('admin.nodes.view', [ return redirect()->route('admin.nodes.view', [
'id' => $id, 'id' => $id,
'tab' => 'tab_allocation' 'tab' => 'tab_allocation',
]); ]);
} }
} }
public function deleteNode(Request $request, $id) public function deleteNode(Request $request, $id)
{ {
$node = Models\Node::findOrFail($id); try {
$servers = Models\Server::where('node', $id)->count(); $repo = new NodeRepository;
if ($servers > 0) { $repo->delete($id);
Alert::danger('You cannot delete a node with servers currently attached to it.')->flash(); Alert::success('Successfully deleted the requested node from the panel.')->flash();
return redirect()->route('admin.nodes.view', [
'id' => $id, return redirect()->route('admin.nodes');
'tab' => 'tab_delete' } 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(); return redirect()->route('admin.nodes.view', [
Alert::success('Node successfully deleted.')->flash(); 'id' => $id,
return redirect()->route('admin.nodes'); '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 <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Http\Controllers\Admin; namespace Pterodactyl\Http\Controllers\Admin;
use Alert;
use Debugbar;
use DB; use DB;
use Log; use Log;
use Alert;
use Pterodactyl\Models; use Pterodactyl\Models;
use Illuminate\Http\Request;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Http\Controllers\Controller;
use Pterodactyl\Repositories\ServerRepository; use Pterodactyl\Repositories\ServerRepository;
use Pterodactyl\Repositories\DatabaseRepository; use Pterodactyl\Repositories\DatabaseRepository;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Exceptions\DisplayValidationException; use Pterodactyl\Exceptions\DisplayValidationException;
use Pterodactyl\Http\Controllers\Controller;
use Illuminate\Http\Request;
class ServersController extends Controller class ServersController extends Controller
{ {
/** /**
* Controller Constructor * Controller Constructor.
*/ */
public function __construct() public function __construct()
{ {
@ -62,20 +58,29 @@ class ServersController extends Controller
->join('users', 'servers.owner', '=', 'users.id') ->join('users', 'servers.owner', '=', 'users.id')
->join('allocations', 'servers.allocation', '=', 'allocations.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); preg_match_all('/[^\s"\']+|"([^"]*)"|\'([^\']*)\'/', urldecode($request->input('filter')), $matches);
foreach($matches[0] as $match) { foreach ($matches[0] as $match) {
$match = str_replace('"', '', $match); $match = str_replace('"', '', $match);
if (strpos($match, ':')) { if (strpos($match, ':')) {
list($field, $term) = explode(':', $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 . '%'); $query->orWhere($field, 'LIKE', '%' . $term . '%');
} else { } else {
$query->where('servers.name', 'LIKE', '%' . $match . '%'); $query->where('servers.name', 'LIKE', '%' . $match . '%');
$query->orWhere('servers.username', 'LIKE', '%' . $match . '%'); $query->orWhere([
$query->orWhere('users.email', 'LIKE', '%' . $match . '%'); ['servers.username', 'LIKE', '%' . $match . '%'],
$query->orWhere('allocations.port', 'LIKE', '%' . $match . '%'); ['users.email', 'LIKE', '%' . $match . '%'],
$query->orWhere('allocations.ip', 'LIKE', '%' . $match . '%'); ['allocations.port', 'LIKE', '%' . $match . '%'],
['allocations.ip', 'LIKE', '%' . $match . '%'],
]);
} }
} }
} }
@ -98,7 +103,7 @@ class ServersController extends Controller
} }
return view('admin.servers.index', [ return view('admin.servers.index', [
'servers' => $servers 'servers' => $servers,
]); ]);
} }
@ -106,7 +111,7 @@ class ServersController extends Controller
{ {
return view('admin.servers.new', [ return view('admin.servers.new', [
'locations' => Models\Location::all(), '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( $server = Models\Server::withTrashed()->select(
'servers.*', 'servers.*',
'nodes.name as a_nodeName',
'users.email as a_ownerEmail', 'users.email as a_ownerEmail',
'locations.long as a_locationName',
'services.name as a_serviceName', 'services.name as a_serviceName',
DB::raw('IFNULL(service_options.executable, services.executable) as a_serviceExecutable'), DB::raw('IFNULL(service_options.executable, services.executable) as a_serviceExecutable'),
'service_options.docker_image', 'service_options.docker_image',
@ -126,19 +129,24 @@ class ServersController extends Controller
'allocations.ip_alias' 'allocations.ip_alias'
)->join('nodes', 'servers.node', '=', 'nodes.id') )->join('nodes', 'servers.node', '=', 'nodes.id')
->join('users', 'servers.owner', '=', 'users.id') ->join('users', 'servers.owner', '=', 'users.id')
->join('locations', 'nodes.location', '=', 'locations.id')
->join('services', 'servers.service', '=', 'services.id') ->join('services', 'servers.service', '=', 'services.id')
->join('service_options', 'servers.option', '=', 'service_options.id') ->join('service_options', 'servers.option', '=', 'service_options.id')
->join('allocations', 'servers.allocation', '=', 'allocations.id') ->join('allocations', 'servers.allocation', '=', 'allocations.id')
->where('servers.id', $id) ->where('servers.id', $id)
->first(); ->first();
if (!$server) { if (! $server) {
return abort(404); return abort(404);
} }
return view('admin.servers.view', [ return view('admin.servers.view', [
'server' => $server, '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(), '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(), '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') '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) ->where('server_id', $server->id)
->join('database_servers', 'database_servers.id', '=', 'databases.db_server') ->join('database_servers', 'database_servers.id', '=', 'databases.db_server')
->get(), ->get(),
'db_servers' => Models\DatabaseServer::all() 'db_servers' => Models\DatabaseServer::all(),
]); ]);
} }
public function postNewServer(Request $request) public function postNewServer(Request $request)
{ {
try { try {
$server = new ServerRepository; $server = new ServerRepository;
$response = $server->create($request->all()); $response = $server->create($request->all());
return redirect()->route('admin.servers.view', [ 'id' => $response ]);
return redirect()->route('admin.servers.view', ['id' => $response]);
} catch (DisplayValidationException $ex) { } catch (DisplayValidationException $ex) {
return redirect()->route('admin.servers.new')->withErrors(json_decode($ex->getMessage()))->withInput(); return redirect()->route('admin.servers.new')->withErrors(json_decode($ex->getMessage()))->withInput();
} catch (DisplayException $ex) { } catch (DisplayException $ex) {
Alert::danger($ex->getMessage())->flash(); Alert::danger($ex->getMessage())->flash();
return redirect()->route('admin.servers.new')->withInput(); return redirect()->route('admin.servers.new')->withInput();
} catch (\Exception $ex) { } catch (\Exception $ex) {
Log::error($ex); Log::error($ex);
Alert::danger('An unhandled exception occured while attemping to add this server. Please try again.')->flash(); Alert::danger('An unhandled exception occured while attemping to add this server. Please try again.')->flash();
return redirect()->route('admin.servers.new')->withInput(); return redirect()->route('admin.servers.new')->withInput();
} }
} }
/** /**
@ -182,15 +191,13 @@ class ServersController extends Controller
*/ */
public function postNewServerGetNodes(Request $request) public function postNewServerGetNodes(Request $request)
{ {
if (! $request->input('location')) {
if(!$request->input('location')) {
return response()->json([ return response()->json([
'error' => 'Missing location in request.' 'error' => 'Missing location in request.',
], 500); ], 500);
} }
return response()->json(Models\Node::select('id', 'name', 'public')->where('location', $request->input('location'))->get()); 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) public function postNewServerGetIps(Request $request)
{ {
if (! $request->input('node')) {
if(!$request->input('node')) {
return response()->json([ return response()->json([
'error' => 'Missing node in request.' 'error' => 'Missing node in request.',
], 500); ], 500);
} }
$ips = Models\Allocation::where('node', $request->input('node'))->whereNull('assigned_to')->get(); $ips = Models\Allocation::where('node', $request->input('node'))->whereNull('assigned_to')->get();
$listing = []; $listing = [];
foreach($ips as &$ip) { foreach ($ips as &$ip) {
if (array_key_exists($ip->ip, $listing)) { if (array_key_exists($ip->ip, $listing)) {
$listing[$ip->ip] = array_merge($listing[$ip->ip], [$ip->port]); $listing[$ip->ip] = array_merge($listing[$ip->ip], [$ip->port]);
} else { } else {
$listing[$ip->ip] = [$ip->port]; $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) public function postNewServerServiceOptions(Request $request)
{ {
if (! $request->input('service')) {
if(!$request->input('service')) {
return response()->json([ return response()->json([
'error' => 'Missing service in request.' 'error' => 'Missing service in request.',
], 500); ], 500);
} }
$service = Models\Service::select('executable', 'startup')->where('id', $request->input('service'))->first(); $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 * @param \Illuminate\Http\Request $request
* @return \Illuminate\Contracts\View\View * @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([ return response()->json([
'error' => 'Missing option in request.' 'error' => 'Missing option in request.',
], 500); ], 500);
} }
@ -265,30 +269,28 @@ class ServersController extends Controller
->first(); ->first();
return response()->json([ 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(), 'variables' => Models\ServiceVariables::where('option_id', $request->input('option'))->get(),
'exec' => $option->executable, 'exec' => $option->executable,
'startup' => $option->startup 'startup' => $option->startup,
]); ]);
} }
public function postUpdateServerDetails(Request $request, $id) public function postUpdateServerDetails(Request $request, $id)
{ {
try { try {
$server = new ServerRepository; $server = new ServerRepository;
$server->updateDetails($id, [ $server->updateDetails($id, [
'owner' => $request->input('owner'), 'owner' => $request->input('owner'),
'name' => $request->input('name'), '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(); Alert::success('Server details were successfully updated.')->flash();
} catch (DisplayValidationException $ex) { } catch (DisplayValidationException $ex) {
return redirect()->route('admin.servers.view', [ return redirect()->route('admin.servers.view', [
'id' => $id, 'id' => $id,
'tab' => 'tab_details' 'tab' => 'tab_details',
])->withErrors(json_decode($ex->getMessage()))->withInput(); ])->withErrors(json_decode($ex->getMessage()))->withInput();
} catch (DisplayException $ex) { } catch (DisplayException $ex) {
Alert::danger($ex->getMessage())->flash(); Alert::danger($ex->getMessage())->flash();
@ -299,21 +301,22 @@ class ServersController extends Controller
return redirect()->route('admin.servers.view', [ return redirect()->route('admin.servers.view', [
'id' => $id, 'id' => $id,
'tab' => 'tab_details' 'tab' => 'tab_details',
])->withInput(); ])->withInput();
} }
public function postUpdateContainerDetails(Request $request, $id) { public function postUpdateContainerDetails(Request $request, $id)
{
try { try {
$server = new ServerRepository; $server = new ServerRepository;
$server->updateContainer($id, [ $server->updateContainer($id, [
'image' => $request->input('docker_image') 'image' => $request->input('docker_image'),
]); ]);
Alert::success('Successfully updated this server\'s docker image.')->flash(); Alert::success('Successfully updated this server\'s docker image.')->flash();
} catch (DisplayValidationException $ex) { } catch (DisplayValidationException $ex) {
return redirect()->route('admin.servers.view', [ return redirect()->route('admin.servers.view', [
'id' => $id, 'id' => $id,
'tab' => 'tab_details' 'tab' => 'tab_details',
])->withErrors(json_decode($ex->getMessage()))->withInput(); ])->withErrors(json_decode($ex->getMessage()))->withInput();
} catch (DisplayException $ex) { } catch (DisplayException $ex) {
Alert::danger($ex->getMessage())->flash(); Alert::danger($ex->getMessage())->flash();
@ -324,11 +327,12 @@ class ServersController extends Controller
return redirect()->route('admin.servers.view', [ return redirect()->route('admin.servers.view', [
'id' => $id, '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); $server = Models\Server::findOrFail($id);
$node = Models\Node::findOrFail($server->node); $node = Models\Node::findOrFail($server->node);
$client = Models\Node::guzzleRequest($server->node); $client = Models\Node::guzzleRequest($server->node);
@ -337,8 +341,8 @@ class ServersController extends Controller
$res = $client->request('POST', '/server/rebuild', [ $res = $client->request('POST', '/server/rebuild', [
'headers' => [ 'headers' => [
'X-Access-Server' => $server->uuid, '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(); Alert::success('A rebuild has been queued successfully. It will run the next time this server is booted.')->flash();
} catch (\GuzzleHttp\Exception\TransferException $ex) { } catch (\GuzzleHttp\Exception\TransferException $ex) {
@ -348,14 +352,13 @@ class ServersController extends Controller
return redirect()->route('admin.servers.view', [ return redirect()->route('admin.servers.view', [
'id' => $id, 'id' => $id,
'tab' => 'tab_manage' 'tab' => 'tab_manage',
]); ]);
} }
public function postUpdateServerUpdateBuild(Request $request, $id) public function postUpdateServerUpdateBuild(Request $request, $id)
{ {
try { try {
$server = new ServerRepository; $server = new ServerRepository;
$server->changeBuild($id, [ $server->changeBuild($id, [
'default' => $request->input('default'), 'default' => $request->input('default'),
@ -370,13 +373,14 @@ class ServersController extends Controller
} catch (DisplayValidationException $ex) { } catch (DisplayValidationException $ex) {
return redirect()->route('admin.servers.view', [ return redirect()->route('admin.servers.view', [
'id' => $id, 'id' => $id,
'tab' => 'tab_build' 'tab' => 'tab_build',
])->withErrors(json_decode($ex->getMessage()))->withInput(); ])->withErrors(json_decode($ex->getMessage()))->withInput();
} catch (DisplayException $ex) { } catch (DisplayException $ex) {
Alert::danger($ex->getMessage())->flash(); Alert::danger($ex->getMessage())->flash();
return redirect()->route('admin.servers.view', [ return redirect()->route('admin.servers.view', [
'id' => $id, 'id' => $id,
'tab' => 'tab_build' 'tab' => 'tab_build',
]); ]);
} catch (\Exception $ex) { } catch (\Exception $ex) {
Log::error($ex); Log::error($ex);
@ -385,7 +389,7 @@ class ServersController extends Controller
return redirect()->route('admin.servers.view', [ return redirect()->route('admin.servers.view', [
'id' => $id, 'id' => $id,
'tab' => 'tab_build' 'tab' => 'tab_build',
]); ]);
} }
@ -395,16 +399,18 @@ class ServersController extends Controller
$server = new ServerRepository; $server = new ServerRepository;
$server->deleteServer($id, $force); $server->deleteServer($id, $force);
Alert::success('Server has been marked for deletion on the system.')->flash(); Alert::success('Server has been marked for deletion on the system.')->flash();
return redirect()->route('admin.servers'); return redirect()->route('admin.servers');
} catch (DisplayException $ex) { } catch (DisplayException $ex) {
Alert::danger($ex->getMessage())->flash(); Alert::danger($ex->getMessage())->flash();
} catch(\Exception $ex) { } catch (\Exception $ex) {
Log::error($ex); Log::error($ex);
Alert::danger('An unhandled exception occured while attemping to delete this server. Please try again.')->flash(); Alert::danger('An unhandled exception occured while attemping to delete this server. Please try again.')->flash();
} }
return redirect()->route('admin.servers.view', [ return redirect()->route('admin.servers.view', [
'id' => $id, 'id' => $id,
'tab' => 'tab_delete' 'tab' => 'tab_delete',
]); ]);
} }
@ -416,13 +422,13 @@ class ServersController extends Controller
Alert::success('Server status was successfully toggled.')->flash(); Alert::success('Server status was successfully toggled.')->flash();
} catch (DisplayException $ex) { } catch (DisplayException $ex) {
Alert::danger($ex->getMessage())->flash(); Alert::danger($ex->getMessage())->flash();
} catch(\Exception $ex) { } catch (\Exception $ex) {
Log::error($ex); Log::error($ex);
Alert::danger('An unhandled exception occured while attemping to toggle this servers status.')->flash(); Alert::danger('An unhandled exception occured while attemping to toggle this servers status.')->flash();
} finally { } finally {
return redirect()->route('admin.servers.view', [ return redirect()->route('admin.servers.view', [
'id' => $id, 'id' => $id,
'tab' => 'tab_manage' 'tab' => 'tab_manage',
]); ]);
} }
} }
@ -432,18 +438,18 @@ class ServersController extends Controller
try { try {
$server = new ServerRepository; $server = new ServerRepository;
$server->updateStartup($id, $request->except([ $server->updateStartup($id, $request->except([
'_token' '_token',
]), true); ]), true);
Alert::success('Server startup variables were successfully updated.')->flash(); Alert::success('Server startup variables were successfully updated.')->flash();
} catch (\Pterodactyl\Exceptions\DisplayException $e) { } catch (\Pterodactyl\Exceptions\DisplayException $e) {
Alert::danger($e->getMessage())->flash(); Alert::danger($e->getMessage())->flash();
} catch(\Exception $e) { } catch (\Exception $e) {
Log::error($e); Log::error($e);
Alert::danger('An unhandled exception occured while attemping to update startup variables for this server. Please try again.')->flash(); Alert::danger('An unhandled exception occured while attemping to update startup variables for this server. Please try again.')->flash();
} finally { } finally {
return redirect()->route('admin.servers.view', [ return redirect()->route('admin.servers.view', [
'id' => $id, 'id' => $id,
'tab' => 'tab_startup' 'tab' => 'tab_startup',
])->withInput(); ])->withInput();
} }
} }
@ -453,13 +459,13 @@ class ServersController extends Controller
try { try {
$repo = new DatabaseRepository; $repo = new DatabaseRepository;
$repo->create($id, $request->except([ $repo->create($id, $request->except([
'_token' '_token',
])); ]));
Alert::success('Added new database to this server.')->flash(); Alert::success('Added new database to this server.')->flash();
} catch (DisplayValidationException $ex) { } catch (DisplayValidationException $ex) {
return redirect()->route('admin.servers.view', [ return redirect()->route('admin.servers.view', [
'id' => $id, 'id' => $id,
'tab' => 'tab_database' 'tab' => 'tab_database',
])->withInput()->withErrors(json_decode($ex->getMessage()))->withInput(); ])->withInput()->withErrors(json_decode($ex->getMessage()))->withInput();
} catch (\Exception $ex) { } catch (\Exception $ex) {
Log::error($ex); Log::error($ex);
@ -468,7 +474,7 @@ class ServersController extends Controller
return redirect()->route('admin.servers.view', [ return redirect()->route('admin.servers.view', [
'id' => $id, 'id' => $id,
'tab' => 'tab_database' 'tab' => 'tab_database',
])->withInput(); ])->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.'); 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) { } catch (DisplayException $e) {
Alert::danger($e->getMessage())->flash(); Alert::danger($e->getMessage())->flash();
} catch(\Exception $e) { } catch (\Exception $e) {
Log::error($e); Log::error($e);
Alert::danger('An unhandled exception occured while attemping to suspend this server. Please try again.')->flash(); Alert::danger('An unhandled exception occured while attemping to suspend this server. Please try again.')->flash();
} finally { } finally {
return redirect()->route('admin.servers.view', [ return redirect()->route('admin.servers.view', [
'id' => $id, '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.'); Alert::success('Server has been unsuspended on the system. Access has been re-enabled.');
} catch (DisplayException $e) { } catch (DisplayException $e) {
Alert::danger($e->getMessage())->flash(); Alert::danger($e->getMessage())->flash();
} catch(\Exception $e) { } catch (\Exception $e) {
Log::error($e); Log::error($e);
Alert::danger('An unhandled exception occured while attemping to unsuspend this server. Please try again.')->flash(); Alert::danger('An unhandled exception occured while attemping to unsuspend this server. Please try again.')->flash();
} finally { } finally {
return redirect()->route('admin.servers.view', [ return redirect()->route('admin.servers.view', [
'id' => $id, 'id' => $id,
'tab' => 'tab_manage' 'tab' => 'tab_manage',
]); ]);
} }
} }
@ -514,27 +520,31 @@ class ServersController extends Controller
{ {
try { try {
$repo = new ServerRepository; $repo = new ServerRepository;
if (!is_null($request->input('cancel'))) { if (! is_null($request->input('cancel'))) {
$repo->cancelDeletion($id); $repo->cancelDeletion($id);
Alert::success('Server deletion has been cancelled. This server will remain suspended until you unsuspend it.')->flash(); Alert::success('Server deletion has been cancelled. This server will remain suspended until you unsuspend it.')->flash();
return redirect()->route('admin.servers.view', $id); return redirect()->route('admin.servers.view', $id);
} else if(!is_null($request->input('delete'))) { } elseif (! is_null($request->input('delete'))) {
$repo->deleteNow($id); $repo->deleteNow($id);
Alert::success('Server was successfully deleted from the system.')->flash(); Alert::success('Server was successfully deleted from the system.')->flash();
return redirect()->route('admin.servers'); return redirect()->route('admin.servers');
} else if(!is_null($request->input('force_delete'))) { } elseif (! is_null($request->input('force_delete'))) {
$repo->deleteNow($id, true); $repo->deleteNow($id, true);
Alert::success('Server was successfully force deleted from the system.')->flash(); Alert::success('Server was successfully force deleted from the system.')->flash();
return redirect()->route('admin.servers'); return redirect()->route('admin.servers');
} }
} catch (DisplayException $ex) { } catch (DisplayException $ex) {
Alert::danger($ex->getMessage())->flash(); Alert::danger($ex->getMessage())->flash();
return redirect()->route('admin.servers.view', $id); return redirect()->route('admin.servers.view', $id);
} catch (\Exception $ex) { } catch (\Exception $ex) {
Log::error($ex); Log::error($ex);
Alert::danger('An unhandled error occured while attempting to perform this action.')->flash(); Alert::danger('An unhandled error occured while attempting to perform this action.')->flash();
return redirect()->route('admin.servers.view', $id); return redirect()->route('admin.servers.view', $id);
} }
} }
} }

View file

@ -1,7 +1,7 @@
<?php <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Http\Controllers\Admin; namespace Pterodactyl\Http\Controllers\Admin;
use Alert;
use DB; use DB;
use Log; use Log;
use Validator; use Alert;
use Storage;
use Pterodactyl\Models; 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 Illuminate\Http\Request;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Http\Controllers\Controller;
use Pterodactyl\Repositories\ServiceRepository;
use Pterodactyl\Exceptions\DisplayValidationException;
class ServiceController extends Controller class ServiceController extends Controller
{ {
public function __construct() public function __construct()
{ {
// //
@ -50,7 +48,7 @@ class ServiceController extends Controller
'services' => Models\Service::select( 'services' => Models\Service::select(
'services.*', 'services.*',
DB::raw('(SELECT COUNT(*) FROM servers WHERE servers.service = services.id) as c_servers') 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 { try {
$repo = new ServiceRepository\Service; $repo = new ServiceRepository\Service;
$id = $repo->create($request->except([ $id = $repo->create($request->except([
'_token' '_token',
])); ]));
Alert::success('Successfully created new service!')->flash(); Alert::success('Successfully created new service!')->flash();
return redirect()->route('admin.services.service', $id); return redirect()->route('admin.services.service', $id);
} catch (DisplayValidationException $ex) { } catch (DisplayValidationException $ex) {
return redirect()->route('admin.services.new')->withErrors(json_decode($ex->getMessage()))->withInput(); return redirect()->route('admin.services.new')->withErrors(json_decode($ex->getMessage()))->withInput();
@ -76,6 +75,7 @@ class ServiceController extends Controller
Log::error($ex); Log::error($ex);
Alert::danger('An error occured while attempting to add a new service.')->flash(); Alert::danger('An error occured while attempting to add a new service.')->flash();
} }
return redirect()->route('admin.services.new')->withInput(); return redirect()->route('admin.services.new')->withInput();
} }
@ -86,7 +86,7 @@ class ServiceController extends Controller
'options' => Models\ServiceOptions::select( 'options' => Models\ServiceOptions::select(
'service_options.*', 'service_options.*',
DB::raw('(SELECT COUNT(*) FROM servers WHERE servers.option = service_options.id) as c_servers') 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 { try {
$repo = new ServiceRepository\Service; $repo = new ServiceRepository\Service;
$repo->update($service, $request->except([ $repo->update($service, $request->except([
'_token' '_token',
])); ]));
Alert::success('Successfully updated this service.')->flash(); Alert::success('Successfully updated this service.')->flash();
} catch (DisplayValidationException $ex) { } catch (DisplayValidationException $ex) {
@ -106,6 +106,7 @@ class ServiceController extends Controller
Log::error($ex); Log::error($ex);
Alert::danger('An error occurred while attempting to update this service.')->flash(); Alert::danger('An error occurred while attempting to update this service.')->flash();
} }
return redirect()->route('admin.services.service', $service)->withInput(); return redirect()->route('admin.services.service', $service)->withInput();
} }
@ -115,6 +116,7 @@ class ServiceController extends Controller
$repo = new ServiceRepository\Service; $repo = new ServiceRepository\Service;
$repo->delete($service); $repo->delete($service);
Alert::success('Successfully deleted that service.')->flash(); Alert::success('Successfully deleted that service.')->flash();
return redirect()->route('admin.services'); return redirect()->route('admin.services');
} catch (DisplayException $ex) { } catch (DisplayException $ex) {
Alert::danger($ex->getMessage())->flash(); Alert::danger($ex->getMessage())->flash();
@ -122,12 +124,14 @@ class ServiceController extends Controller
Log::error($ex); Log::error($ex);
Alert::danger('An error was encountered while attempting to delete that service.')->flash(); Alert::danger('An error was encountered while attempting to delete that service.')->flash();
} }
return redirect()->route('admin.services.service', $service); return redirect()->route('admin.services.service', $service);
} }
public function getOption(Request $request, $service, $option) public function getOption(Request $request, $service, $option)
{ {
$opt = Models\ServiceOptions::findOrFail($option); $opt = Models\ServiceOptions::findOrFail($option);
return view('admin.services.options.view', [ return view('admin.services.options.view', [
'service' => Models\Service::findOrFail($opt->parent_service), 'service' => Models\Service::findOrFail($opt->parent_service),
'option' => $opt, 'option' => $opt,
@ -135,7 +139,7 @@ class ServiceController extends Controller
'servers' => Models\Server::select('servers.*', 'users.email as a_ownerEmail') 'servers' => Models\Server::select('servers.*', 'users.email as a_ownerEmail')
->join('users', 'users.id', '=', 'servers.owner') ->join('users', 'users.id', '=', 'servers.owner')
->where('option', $option) ->where('option', $option)
->paginate(10) ->paginate(10),
]); ]);
} }
@ -144,7 +148,7 @@ class ServiceController extends Controller
try { try {
$repo = new ServiceRepository\Option; $repo = new ServiceRepository\Option;
$repo->update($option, $request->except([ $repo->update($option, $request->except([
'_token' '_token',
])); ]));
Alert::success('Option settings successfully updated.')->flash(); Alert::success('Option settings successfully updated.')->flash();
} catch (DisplayValidationException $ex) { } catch (DisplayValidationException $ex) {
@ -153,6 +157,7 @@ class ServiceController extends Controller
Log::error($ex); Log::error($ex);
Alert::danger('An error occured while attempting to modify this option.')->flash(); Alert::danger('An error occured while attempting to modify this option.')->flash();
} }
return redirect()->route('admin.services.option', [$service, $option])->withInput(); return redirect()->route('admin.services.option', [$service, $option])->withInput();
} }
@ -164,6 +169,7 @@ class ServiceController extends Controller
$repo->delete($option); $repo->delete($option);
Alert::success('Successfully deleted that option.')->flash(); Alert::success('Successfully deleted that option.')->flash();
return redirect()->route('admin.services.service', $service->parent_service); return redirect()->route('admin.services.service', $service->parent_service);
} catch (DisplayException $ex) { } catch (DisplayException $ex) {
Alert::danger($ex->getMessage())->flash(); Alert::danger($ex->getMessage())->flash();
@ -171,6 +177,7 @@ class ServiceController extends Controller
Log::error($ex); Log::error($ex);
Alert::danger('An error was encountered while attempting to delete this option.')->flash(); Alert::danger('An error was encountered while attempting to delete this option.')->flash();
} }
return redirect()->route('admin.services.option', [$service, $option]); return redirect()->route('admin.services.option', [$service, $option]);
} }
@ -184,18 +191,19 @@ class ServiceController extends Controller
$data = [ $data = [
'user_viewable' => '0', 'user_viewable' => '0',
'user_editable' => '0', 'user_editable' => '0',
'required' => '0' 'required' => '0',
]; ];
foreach($request->except(['_token']) as $id => $val) { foreach ($request->except(['_token']) as $id => $val) {
$data[str_replace($variable.'_', '', $id)] = $val; $data[str_replace($variable . '_', '', $id)] = $val;
} }
$repo->update($variable, $data); $repo->update($variable, $data);
Alert::success('Successfully updated variable.')->flash(); Alert::success('Successfully updated variable.')->flash();
} catch (DisplayValidationException $ex) { } catch (DisplayValidationException $ex) {
$data = []; $data = [];
foreach(json_decode($ex->getMessage(), true) as $id => $val) { foreach (json_decode($ex->getMessage(), true) as $id => $val) {
$data[$variable.'_'.$id] = $val; $data[$variable . '_' . $id] = $val;
} }
return redirect()->route('admin.services.option', [$service, $option])->withErrors((object) $data)->withInput(); return redirect()->route('admin.services.option', [$service, $option])->withErrors((object) $data)->withInput();
} catch (DisplayException $ex) { } catch (DisplayException $ex) {
Alert::danger($ex->getMessage())->flash(); Alert::danger($ex->getMessage())->flash();
@ -203,6 +211,7 @@ class ServiceController extends Controller
Log::error($ex); Log::error($ex);
Alert::danger('An error occurred while attempting to update this service.')->flash(); Alert::danger('An error occurred while attempting to update this service.')->flash();
} }
return redirect()->route('admin.services.option', [$service, $option])->withInput(); return redirect()->route('admin.services.option', [$service, $option])->withInput();
} }
@ -210,7 +219,7 @@ class ServiceController extends Controller
{ {
return view('admin.services.options.variable', [ return view('admin.services.options.variable', [
'service' => Models\Service::findOrFail($service), '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 { try {
$repo = new ServiceRepository\Variable; $repo = new ServiceRepository\Variable;
$repo->create($option, $request->except([ $repo->create($option, $request->except([
'_token' '_token',
])); ]));
Alert::success('Successfully added new variable to this option.')->flash(); 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) { } catch (DisplayValidationException $ex) {
return redirect()->route('admin.services.option.variable.new', [$service, $option])->withErrors(json_decode($ex->getMessage()))->withInput(); return redirect()->route('admin.services.option.variable.new', [$service, $option])->withErrors(json_decode($ex->getMessage()))->withInput();
} catch (DisplayException $ex) { } catch (DisplayException $ex) {
@ -231,6 +241,7 @@ class ServiceController extends Controller
Log::error($ex); Log::error($ex);
Alert::danger('An error occurred while attempting to add this variable.')->flash(); Alert::danger('An error occurred while attempting to add this variable.')->flash();
} }
return redirect()->route('admin.services.option.variable.new', [$service, $option])->withInput(); return redirect()->route('admin.services.option.variable.new', [$service, $option])->withInput();
} }
@ -246,9 +257,10 @@ class ServiceController extends Controller
try { try {
$repo = new ServiceRepository\Option; $repo = new ServiceRepository\Option;
$id = $repo->create($service, $request->except([ $id = $repo->create($service, $request->except([
'_token' '_token',
])); ]));
Alert::success('Successfully created new service option.')->flash(); Alert::success('Successfully created new service option.')->flash();
return redirect()->route('admin.services.option', [$service, $id]); return redirect()->route('admin.services.option', [$service, $id]);
} catch (DisplayValidationException $ex) { } catch (DisplayValidationException $ex) {
return redirect()->route('admin.services.option.new', $service)->withErrors(json_decode($ex->getMessage()))->withInput(); 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); Log::error($ex);
Alert::danger('An error occured while attempting to add this service option.')->flash(); Alert::danger('An error occured while attempting to add this service option.')->flash();
} }
return redirect()->route('admin.services.option.new', $service)->withInput(); return redirect()->route('admin.services.option.new', $service)->withInput();
} }
@ -271,7 +284,42 @@ class ServiceController extends Controller
Log::error($ex); Log::error($ex);
Alert::danger('An error occured while attempting to delete that variable.')->flash(); Alert::danger('An error occured while attempting to delete that variable.')->flash();
} }
return redirect()->route('admin.services.option', [$service, $option]); 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 <?php
/** /**
* Pterodactyl - Panel * Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com> * Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>
* Some Modifications (c) 2015 Dylan Seidt <dylan.seidt@gmail.com> * Some Modifications (c) 2015 Dylan Seidt <dylan.seidt@gmail.com>.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Http\Controllers\Admin; namespace Pterodactyl\Http\Controllers\Admin;
use Alert;
use Settings;
use Mail;
use Log; use Log;
use Pterodactyl\Models\User; use Alert;
use Pterodactyl\Repositories\UserRepository;
use Pterodactyl\Models\Server;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Exceptions\DisplayValidationException;
use Pterodactyl\Http\Controllers\Controller;
use Illuminate\Http\Request; 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 class UserController extends Controller
{ {
/** /**
* Controller Constructor * Controller Constructor.
*/ */
public function __construct() public function __construct()
{ {
@ -51,8 +47,33 @@ class UserController extends Controller
public function getIndex(Request $request) 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', [ return view('admin.users.index', [
'users' => User::paginate(20) 'users' => $users,
]); ]);
} }
@ -79,13 +100,15 @@ class UserController extends Controller
$repo = new UserRepository; $repo = new UserRepository;
$repo->delete($id); $repo->delete($id);
Alert::success('Successfully deleted user from system.')->flash(); Alert::success('Successfully deleted user from system.')->flash();
return redirect()->route('admin.users'); return redirect()->route('admin.users');
} catch(DisplayException $ex) { } catch (DisplayException $ex) {
Alert::danger($ex->getMessage())->flash(); Alert::danger($ex->getMessage())->flash();
} catch (\Exception $ex) { } catch (\Exception $ex) {
Log::error($ex); Log::error($ex);
Alert::danger('An exception was encountered while attempting to delete this user.')->flash(); Alert::danger('An exception was encountered while attempting to delete this user.')->flash();
} }
return redirect()->route('admin.users.view', $id); return redirect()->route('admin.users.view', $id);
} }
@ -93,33 +116,39 @@ class UserController extends Controller
{ {
try { try {
$user = new UserRepository; $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(); Alert::success('Account has been successfully created.')->flash();
return redirect()->route('admin.users.view', $userid); return redirect()->route('admin.users.view', $userid);
} catch (DisplayValidationException $ex) { } catch (DisplayValidationException $ex) {
return redirect()->route('admin.users.new')->withErrors(json_decode($ex->getMessage()))->withInput(); return redirect()->route('admin.users.new')->withErrors(json_decode($ex->getMessage()))->withInput();
} catch (\Exception $ex) { } catch (\Exception $ex) {
Log::error($ex); Log::error($ex);
Alert::danger('An error occured while attempting to add a new user.')->flash(); Alert::danger('An error occured while attempting to add a new user.')->flash();
return redirect()->route('admin.users.new'); return redirect()->route('admin.users.new');
} }
} }
public function updateUser(Request $request, $user) 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 { try {
$repo = new UserRepository; $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(); Alert::success('User account was successfully updated.')->flash();
} catch (DisplayValidationException $ex) { } catch (DisplayValidationException $ex) {
return redirect()->route('admin.users.view', $user)->withErrors(json_decode($ex->getMessage())); return redirect()->route('admin.users.view', $user)->withErrors(json_decode($ex->getMessage()));
@ -127,15 +156,16 @@ class UserController extends Controller
Log::error($e); Log::error($e);
Alert::danger('An error occured while attempting to update this user.')->flash(); Alert::danger('An error occured while attempting to update this user.')->flash();
} }
return redirect()->route('admin.users.view', $user); return redirect()->route('admin.users.view', $user);
} }
public function getJson(Request $request) public function getJson(Request $request)
{ {
foreach(User::select('email')->get() as $user) { foreach (User::select('email')->get() as $user) {
$resp[] = $user->email; $resp[] = $user->email;
} }
return $resp; return $resp;
} }
} }

View file

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

View file

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

View file

@ -1,8 +1,8 @@
<?php <?php
/** /**
* Pterodactyl - Panel * Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com> * Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>
* Some Modifications (c) 2015 Dylan Seidt <dylan.seidt@gmail.com> * Some Modifications (c) 2015 Dylan Seidt <dylan.seidt@gmail.com>.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Http\Controllers\Base; namespace Pterodactyl\Http\Controllers\Base;
use Alert;
use Log; use Log;
use Alert;
use Pterodactyl\Models; use Pterodactyl\Models;
use Illuminate\Http\Request;
use Pterodactyl\Repositories\APIRepository; use Pterodactyl\Repositories\APIRepository;
use Pterodactyl\Exceptions\DisplayValidationException;
use Pterodactyl\Exceptions\DisplayException; use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Http\Controllers\Controller; use Pterodactyl\Http\Controllers\Controller;
use Pterodactyl\Exceptions\DisplayValidationException;
use Illuminate\Http\Request;
class APIController extends Controller class APIController extends Controller
{ {
public function index(Request $request) public function index(Request $request)
{ {
$keys = Models\APIKey::where('user', $request->user()->id)->get(); $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(); $key->permissions = Models\APIPermission::where('key_id', $key->id)->get();
} }
return view('base.api.index', [ return view('base.api.index', [
'keys' => $keys 'keys' => $keys,
]); ]);
} }
public function new(Request $request) public function create(Request $request)
{ {
return view('base.api.new'); return view('base.api.new');
} }
@ -59,8 +57,9 @@ class APIController extends Controller
{ {
try { try {
$repo = new APIRepository($request->user()); $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(); 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'); return redirect()->route('account.api');
} catch (DisplayValidationException $ex) { } catch (DisplayValidationException $ex) {
return redirect()->route('account.api.new')->withErrors(json_decode($ex->getMessage()))->withInput(); return redirect()->route('account.api.new')->withErrors(json_decode($ex->getMessage()))->withInput();
@ -70,6 +69,7 @@ class APIController extends Controller
Log::error($ex); Log::error($ex);
Alert::danger('An unhandled exception occured while attempting to add this API key.')->flash(); Alert::danger('An unhandled exception occured while attempting to add this API key.')->flash();
} }
return redirect()->route('account.api.new')->withInput(); return redirect()->route('account.api.new')->withInput();
} }
@ -78,10 +78,11 @@ class APIController extends Controller
try { try {
$repo = new APIRepository($request->user()); $repo = new APIRepository($request->user());
$repo->revoke($key); $repo->revoke($key);
return response('', 204); return response('', 204);
} catch (\Exception $ex) { } catch (\Exception $ex) {
return response()->json([ return response()->json([
'error' => 'An error occured while attempting to remove this key.' 'error' => 'An error occured while attempting to remove this key.',
], 503); ], 503);
} }
} }

View file

@ -1,8 +1,8 @@
<?php <?php
/** /**
* Pterodactyl - Panel * Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com> * Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>
* Some Modifications (c) 2015 Dylan Seidt <dylan.seidt@gmail.com> * Some Modifications (c) 2015 Dylan Seidt <dylan.seidt@gmail.com>.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Http\Controllers\Base; namespace Pterodactyl\Http\Controllers\Base;
use Log;
use Alert; use Alert;
use Pterodactyl\Models\User;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Http\Controllers\Controller;
use Illuminate\Http\Request; 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 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 * @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, [ // Request to update account Password
'new_email' => 'required|email', if ($request->input('do_action') === 'password') {
'password' => 'required' $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)) { // Request to update account Email
Alert::danger('The password provided was not valid for this account.')->flash(); } elseif ($request->input('do_action') === 'email') {
return redirect()->route('account'); $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'); if (
$user->save(); 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'); return redirect()->route('account');
} }
try { try {
$user->setPassword($request->input('new_password')); $repo = new UserRepository;
Alert::success('Your password has successfully been updated.')->flash(); $repo->update($request->user()->id, $data);
} catch (DisplayException $e) { Alert::success('Your account details were successfully updated.')->flash();
Alert::danger($e->getMessage())->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'); return redirect()->route('account');
} }
} }

View file

@ -1,8 +1,8 @@
<?php <?php
/** /**
* Pterodactyl - Panel * Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com> * Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>
* Some Modifications (c) 2015 Dylan Seidt <dylan.seidt@gmail.com> * Some Modifications (c) 2015 Dylan Seidt <dylan.seidt@gmail.com>.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Http\Controllers\Base; namespace Pterodactyl\Http\Controllers\Base;
use Illuminate\Http\Request;
use Pterodactyl\Models\Server; use Pterodactyl\Models\Server;
use Pterodactyl\Http\Controllers\Controller; use Pterodactyl\Http\Controllers\Controller;
use Illuminate\Http\Request;
class IndexController extends Controller class IndexController extends Controller
{ {
/** /**
* Controller Constructor * Controller Constructor.
*/ */
public function __construct() public function __construct()
{ {
@ -62,7 +61,15 @@ class IndexController extends Controller
public function getPassword(Request $request, $length = 16) public function getPassword(Request $request, $length = 16)
{ {
$length = ($length < 8) ? 8 : $length; $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 <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Http\Controllers\Base; namespace Pterodactyl\Http\Controllers\Base;
use Auth; use Auth;
use Session; use Session;
use Pterodactyl\Models\User;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Pterodactyl\Models\User;
use Pterodactyl\Http\Controllers\Controller; use Pterodactyl\Http\Controllers\Controller;
class LanguageController extends Controller class LanguageController extends Controller
{ {
protected $languages = [ protected $languages = [
'de' => 'Danish', 'de' => 'German',
'en' => 'English', 'en' => 'English',
'es' => 'Spanish', 'et' => 'Estonian',
'fr' => 'French', 'nb' => 'Norwegian',
'it' => 'Italian', 'nl' => 'Dutch',
'pl' => 'Polish',
'pt' => 'Portuguese', 'pt' => 'Portuguese',
'ro' => 'Romanian',
'ru' => 'Russian', 'ru' => 'Russian',
'se' => 'Swedish',
'zh' => 'Chinese',
]; ];
/** /**
* Controller Constructor * Controller Constructor.
*/ */
public function __construct() public function __construct()
{ {
@ -64,7 +61,7 @@ class LanguageController extends Controller
} }
Session::set('applocale', $language); Session::set('applocale', $language);
} }
return redirect()->back(); return redirect()->back();
} }
} }

View file

@ -1,8 +1,8 @@
<?php <?php
/** /**
* Pterodactyl - Panel * Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com> * Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>
* Some Modifications (c) 2015 Dylan Seidt <dylan.seidt@gmail.com> * Some Modifications (c) 2015 Dylan Seidt <dylan.seidt@gmail.com>.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Http\Controllers\Base; namespace Pterodactyl\Http\Controllers\Base;
use Google2FA;
use Alert; use Alert;
use Google2FA;
use Illuminate\Http\Request;
use Pterodactyl\Models\Session; use Pterodactyl\Models\Session;
use Pterodactyl\Http\Controllers\Controller; use Pterodactyl\Http\Controllers\Controller;
use Illuminate\Http\Request;
class SecurityController extends Controller class SecurityController extends Controller
{ {
/** /**
* Returns Security Management Page. * Returns Security Management Page.
* *
@ -44,7 +42,7 @@ class SecurityController extends Controller
public function index(Request $request) public function index(Request $request)
{ {
return view('base.security', [ 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) public function generateTotp(Request $request)
{ {
$user = $request->user(); $user = $request->user();
$user->totp_secret = Google2FA::generateSecretKey(); $user->totp_secret = Google2FA::generateSecretKey();
@ -69,9 +66,8 @@ class SecurityController extends Controller
$user->email, $user->email,
$user->totp_secret $user->totp_secret
), ),
'secret' => $user->totp_secret 'secret' => $user->totp_secret,
]); ]);
} }
/** /**
@ -82,18 +78,18 @@ class SecurityController extends Controller
*/ */
public function setTotp(Request $request) public function setTotp(Request $request)
{ {
if (! $request->has('token')) {
if (!$request->has('token')) { return response()->json([
return response(null, 500); 'error' => 'Request is missing token parameter.',
], 500);
} }
$user = $request->user(); $user = $request->user();
if($user->toggleTotp($request->input('token'))) { if ($user->toggleTotp($request->input('token'))) {
return response('true'); return response('true');
} }
return response('false'); return response('false');
} }
/** /**
@ -104,27 +100,27 @@ class SecurityController extends Controller
*/ */
public function disableTotp(Request $request) public function disableTotp(Request $request)
{ {
if (! $request->has('token')) {
if (!$request->has('token')) {
Alert::danger('Missing required `token` field in request.')->flash(); Alert::danger('Missing required `token` field in request.')->flash();
return redirect()->route('account.totp');
return redirect()->route('account.security');
} }
$user = $request->user(); $user = $request->user();
if($user->toggleTotp($request->input('token'))) { if ($user->toggleTotp($request->input('token'))) {
return redirect()->route('account.security'); return redirect()->route('account.security');
} }
Alert::danger('The TOTP token provided was invalid.')->flash(); 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) public function revoke(Request $request, $id)
{ {
$session = Session::where('id', $id)->where('user_id', $request->user()->id)->firstOrFail(); $session = Session::where('id', $id)->where('user_id', $request->user()->id)->firstOrFail();
$session->delete(); $session->delete();
return redirect()->route('account.security'); 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 <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Http\Controllers\Remote; namespace Pterodactyl\Http\Controllers\Remote;
use Carbon\Carbon;
use Pterodactyl\Models; use Pterodactyl\Models;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Services\NotificationService;
use Pterodactyl\Http\Controllers\Controller;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Pterodactyl\Http\Controllers\Controller;
use Pterodactyl\Services\NotificationService;
class RemoteController extends Controller class RemoteController extends Controller
{ {
/** /**
* Controller Constructor * Controller Constructor.
*/ */
public function __construct() public function __construct()
{ {
// No middleware for this route. // 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(); $download = Models\Download::where('token', $request->input('token', '00'))->first();
if (!$download) { if (! $download) {
return response()->json([ return response()->json([
'error' => 'An invalid request token was recieved with this request.' 'error' => 'An invalid request token was recieved with this request.',
], 403); ], 403);
} }
$download->delete(); $download->delete();
return response()->json([ return response()->json([
'path' => $download->path, 'path' => $download->path,
'server' => $download->server 'server' => $download->server,
]); ]);
} }
public function postInstall(Request $request) public function postInstall(Request $request)
{ {
$server = Models\Server::where('uuid', $request->input('server'))->first(); $server = Models\Server::where('uuid', $request->input('server'))->first();
if (!$server) { if (! $server) {
return response()->json([ 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); ], 422);
} }
@ -71,7 +72,7 @@ class RemoteController extends Controller
if (base64_decode($hmac) !== hash_hmac('sha256', $server->uuid, $node->daemonSecret, true)) { if (base64_decode($hmac) !== hash_hmac('sha256', $server->uuid, $node->daemonSecret, true)) {
return response()->json([ return response()->json([
'error' => 'Signed HMAC was invalid.' 'error' => 'Signed HMAC was invalid.',
], 403); ], 403);
} }
@ -79,16 +80,16 @@ class RemoteController extends Controller
$server->save(); $server->save();
return response()->json([ return response()->json([
'message' => 'Recieved!' 'message' => 'Recieved!',
], 200); ], 200);
} }
public function event(Request $request) public function event(Request $request)
{ {
$server = Models\Server::where('uuid', $request->input('server'))->first(); $server = Models\Server::where('uuid', $request->input('server'))->first();
if (!$server) { if (! $server) {
return response()->json([ 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); ], 422);
} }
@ -97,7 +98,7 @@ class RemoteController extends Controller
$hmac = $request->input('signed'); $hmac = $request->input('signed');
if (base64_decode($hmac) !== hash_hmac('sha256', $server->uuid, $node->daemonSecret, true)) { if (base64_decode($hmac) !== hash_hmac('sha256', $server->uuid, $node->daemonSecret, true)) {
return response()->json([ return response()->json([
'error' => 'Signed HMAC was invalid.' 'error' => 'Signed HMAC was invalid.',
], 403); ], 403);
} }
@ -108,4 +109,28 @@ class RemoteController extends Controller
return response('', 201); 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 <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Http\Controllers\Server; namespace Pterodactyl\Http\Controllers\Server;
use Log; use Log;
use Pterodactyl\Models; use Pterodactyl\Models;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Exceptions\DisplayValidationException;
use Pterodactyl\Repositories;
use Pterodactyl\Http\Controllers\Controller;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Pterodactyl\Repositories;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException; use GuzzleHttp\Exception\RequestException;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Http\Controllers\Controller;
use Pterodactyl\Exceptions\DisplayValidationException;
class AjaxController extends Controller class AjaxController extends Controller
{ {
/** /**
* @var array * @var array
*/ */
@ -55,7 +51,7 @@ class AjaxController extends Controller
protected $directory; protected $directory;
/** /**
* Controller Constructor * Controller Constructor.
*/ */
public function __construct() public function __construct()
{ {
@ -73,7 +69,7 @@ class AjaxController extends Controller
{ {
$server = Models\Server::getByUUID($uuid); $server = Models\Server::getByUUID($uuid);
if (!$server) { if (! $server) {
return response()->json([], 404); return response()->json([], 404);
} }
@ -81,14 +77,15 @@ class AjaxController extends Controller
try { try {
$res = $client->request('GET', '/server', [ $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())); return response()->json(json_decode($res->getBody()));
} }
} catch (RequestException $e) { } catch (RequestException $e) {
// //
} }
return response()->json([]); return response()->json([]);
} }
@ -101,13 +98,12 @@ class AjaxController extends Controller
*/ */
public function postDirectoryList(Request $request, $uuid) public function postDirectoryList(Request $request, $uuid)
{ {
$server = Models\Server::getByUUID($uuid); $server = Models\Server::getByUUID($uuid);
$this->directory = '/' . trim(urldecode($request->input('directory', '/')), '/'); $this->directory = '/' . trim(urldecode($request->input('directory', '/')), '/');
$this->authorize('list-files', $server); $this->authorize('list-files', $server);
$prevDir = [ $prevDir = [
'header' => ($this->directory !== '/') ? $this->directory : '' 'header' => ($this->directory !== '/') ? $this->directory : '',
]; ];
if ($this->directory !== '/') { if ($this->directory !== '/') {
$prevDir['first'] = true; $prevDir['first'] = true;
@ -116,7 +112,7 @@ class AjaxController extends Controller
// Determine if we should show back links in the file browser. // Determine if we should show back links in the file browser.
// This code is strange, and could probably be rewritten much better. // This code is strange, and could probably be rewritten much better.
$goBack = explode('/', trim($this->directory, '/')); $goBack = explode('/', trim($this->directory, '/'));
if (!empty(array_filter($goBack)) && count($goBack) >= 2) { if (! empty(array_filter($goBack)) && count($goBack) >= 2) {
$prevDir['show'] = true; $prevDir['show'] = true;
array_pop($goBack); array_pop($goBack);
$prevDir['link'] = '/' . implode('/', $goBack); $prevDir['link'] = '/' . implode('/', $goBack);
@ -131,6 +127,7 @@ class AjaxController extends Controller
return response($ex->getMessage(), 500); return response($ex->getMessage(), 500);
} catch (\Exception $ex) { } catch (\Exception $ex) {
Log::error($ex); Log::error($ex);
return response('An error occured while attempting to load the requested directory, please try again.', 500); 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, 'files' => $directoryContents->files,
'folders' => $directoryContents->folders, 'folders' => $directoryContents->folders,
'editableMime' => Repositories\HelperRepository::editableFiles(), 'editableMime' => Repositories\HelperRepository::editableFiles(),
'directory' => $prevDir 'directory' => $prevDir,
]); ]);
} }
/** /**
@ -153,7 +149,6 @@ class AjaxController extends Controller
*/ */
public function postSaveFile(Request $request, $uuid) public function postSaveFile(Request $request, $uuid)
{ {
$server = Models\Server::getByUUID($uuid); $server = Models\Server::getByUUID($uuid);
$this->authorize('save-files', $server); $this->authorize('save-files', $server);
@ -161,39 +156,39 @@ class AjaxController extends Controller
try { try {
$controller->saveFileContents($request->input('file'), $request->input('contents')); $controller->saveFileContents($request->input('file'), $request->input('contents'));
return response(null, 204); return response(null, 204);
} catch (DisplayException $ex) { } catch (DisplayException $ex) {
return response($ex->getMessage(), 500); return response($ex->getMessage(), 500);
} catch (\Exception $ex) { } catch (\Exception $ex) {
Log::error($ex); Log::error($ex);
return response('An error occured while attempting to save this file, please try again.', 500); return response('An error occured while attempting to save this file, please try again.', 500);
} }
} }
/** /**
* [postSetPrimary description] * [postSetPrimary description].
* @param Request $request * @param Request $request
* @param string $uuid * @param string $uuid
* @return \Illuminate\Http\Response * @return \Illuminate\Http\Response
*/ */
public function postSetPrimary(Request $request, $uuid) public function postSetPrimary(Request $request, $uuid)
{ {
$server = Models\Server::getByUUID($uuid); $server = Models\Server::getByUUID($uuid);
$this->authorize('set-connection', $server); $this->authorize('set-connection', $server);
if ((int) $request->input('allocation') === $server->allocation) { if ((int) $request->input('allocation') === $server->allocation) {
return response()->json([ return response()->json([
'error' => 'You are already using this as your default connection.' 'error' => 'You are already using this as your default connection.',
], 409); ], 409);
} }
try { try {
$allocation = Models\Allocation::where('id', $request->input('allocation'))->where('assigned_to', $server->id)->first(); $allocation = Models\Allocation::where('id', $request->input('allocation'))->where('assigned_to', $server->id)->first();
if (!$allocation) { if (! $allocation) {
return response()->json([ 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); ], 422);
} }
@ -201,6 +196,7 @@ class AjaxController extends Controller
$repo->changeBuild($server->id, [ $repo->changeBuild($server->id, [
'default' => $allocation->ip . ':' . $allocation->port, '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.'); 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) { } catch (DisplayValidationException $ex) {
return response()->json([ return response()->json([
@ -212,8 +208,9 @@ class AjaxController extends Controller
], 503); ], 503);
} catch (\Exception $ex) { } catch (\Exception $ex) {
Log::error($ex); Log::error($ex);
return response()->json([ 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); ], 503);
} }
} }
@ -225,21 +222,21 @@ class AjaxController extends Controller
$this->authorize('reset-db-password', $server); $this->authorize('reset-db-password', $server);
try { try {
$repo = new Repositories\DatabaseRepository; $repo = new Repositories\DatabaseRepository;
$password = str_random(16); $password = str_random(16);
$repo->modifyPassword($request->input('database'), $password); $repo->modifyPassword($request->input('database'), $password);
return response($password); return response($password);
} catch (\Pterodactyl\Exceptions\DisplayException $ex) { } catch (\Pterodactyl\Exceptions\DisplayException $ex) {
return response()->json([ return response()->json([
'error' => $ex->getMessage(), 'error' => $ex->getMessage(),
], 503); ], 503);
} catch(\Exception $ex) { } catch (\Exception $ex) {
Log::error($ex); Log::error($ex);
return response()->json([ 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); ], 503);
} }
} }
} }

View file

@ -1,7 +1,7 @@
<?php <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Http\Controllers\Server; namespace Pterodactyl\Http\Controllers\Server;
use Auth;
use DB; use DB;
use Log;
use Uuid; use Uuid;
use Alert; use Alert;
use Log; use Javascript;
use Pterodactyl\Models; 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 Illuminate\Http\Request;
use Pterodactyl\Exceptions\DisplayException;
use InvalidArgumentException; use Pterodactyl\Http\Controllers\Controller;
use Pterodactyl\Repositories\ServerRepository;
use Pterodactyl\Repositories\Daemon\FileRepository;
use Pterodactyl\Exceptions\DisplayValidationException;
class ServerController extends Controller class ServerController extends Controller
{ {
/** /**
* Controller Constructor * Controller Constructor.
* *
* @return void * @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. * Renders server index page for specified server.
* *
@ -80,10 +58,20 @@ class ServerController extends Controller
public function getIndex(Request $request) public function getIndex(Request $request)
{ {
$server = Models\Server::getByUUID($request->route()->server); $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', [ return view('server.index', [
'server' => $server, 'server' => $server,
'allocations' => Models\Allocation::where('assigned_to', $server->id)->orderBy('ip', 'asc')->orderBy('port', 'asc')->get(), 'node' => $node,
'node' => Models\Node::find($server->node)
]); ]);
} }
@ -93,15 +81,34 @@ class ServerController extends Controller
* @param Request $request * @param Request $request
* @return \Illuminate\Contracts\View\View * @return \Illuminate\Contracts\View\View
*/ */
public function getFiles(Request $request) public function getFiles(Request $request, $uuid)
{ {
$server = Models\Server::getByUUID($uuid);
$server = Models\Server::getByUUID($request->route()->server);
$this->authorize('list-files', $server); $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', [ return view('server.files.index', [
'server' => $server, 'server' => $server,
'node' => Models\Node::find($server->node) 'node' => $node,
]); ]);
} }
@ -111,16 +118,21 @@ class ServerController extends Controller
* @param Request $request * @param Request $request
* @return \Illuminate\Contracts\View\View * @return \Illuminate\Contracts\View\View
*/ */
public function getAddFile(Request $request) public function getAddFile(Request $request, $uuid)
{ {
$server = Models\Server::getByUUID($uuid);
$server = Models\Server::getByUUID($request->route()->server);
$this->authorize('add-files', $server); $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', [ return view('server.files.add', [
'server' => $server, 'server' => $server,
'node' => Models\Node::find($server->node), 'node' => $node,
'directory' => (in_array($request->get('dir'), [null, '/', ''])) ? '' : trim($request->get('dir'), '/') . '/' '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) public function getEditFile(Request $request, $uuid, $file)
{ {
$server = Models\Server::getByUUID($uuid); $server = Models\Server::getByUUID($uuid);
$this->authorize('edit-files', $server); $this->authorize('edit-files', $server);
$node = Models\Node::find($server->node);
$fileInfo = (object) pathinfo($file); $fileInfo = (object) pathinfo($file);
$controller = new FileRepository($uuid); $controller = new FileRepository($uuid);
@ -145,22 +157,29 @@ class ServerController extends Controller
$fileContent = $controller->returnFileContents($file); $fileContent = $controller->returnFileContents($file);
} catch (DisplayException $ex) { } catch (DisplayException $ex) {
Alert::danger($ex->getMessage())->flash(); Alert::danger($ex->getMessage())->flash();
return redirect()->route('server.files.index', $uuid); return redirect()->route('server.files.index', $uuid);
} catch (\Exception $ex) { } catch (\Exception $ex) {
Log::error($ex); Log::error($ex);
Alert::danger('An error occured while attempting to load the requested file for editing, please try again.')->flash(); 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); 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', [ return view('server.files.edit', [
'server' => $server, 'server' => $server,
'node' => Models\Node::find($server->node), 'node' => $node,
'file' => $file, 'file' => $file,
'stat' => $fileContent['stat'], 'stat' => $fileContent['stat'],
'contents' => $fileContent['file']->content, '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) public function getDownloadFile(Request $request, $uuid, $file)
{ {
$server = Models\Server::getByUUID($uuid); $server = Models\Server::getByUUID($uuid);
$node = Models\Node::find($server->node); $node = Models\Node::find($server->node);
@ -187,21 +205,39 @@ class ServerController extends Controller
$download->save(); $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);
} }
/** public function getAllocation(Request $request, $uuid)
* Renders server settings page.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Contracts\View\View
*/
public function getSettings(Request $request, $uuid)
{ {
$server = Models\Server::getByUUID($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); $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( $variables = Models\ServiceVariables::select(
'service_variables.*', 'service_variables.*',
DB::raw('COALESCE(server_variables.variable_value, service_variables.default_value) as a_serverValue') 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); $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 : '**'; $replace = ($variable->user_viewable === 1) ? $variable->a_serverValue : '**';
$processed = str_replace('{{' . $variable->env_variable . '}}', $replace, $processed); $processed = str_replace('{{' . $variable->env_variable . '}}', $replace, $processed);
} }
return view('server.settings', [ return view('server.settings.startup', [
'server' => $server, '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), 'node' => Models\Node::find($server->node),
'variables' => $variables->where('user_viewable', 1), 'variables' => $variables->where('user_viewable', 1),
'service' => $service, '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) public function postSettingsSFTP(Request $request, $uuid)
{ {
$server = Models\Server::getByUUID($uuid); $server = Models\Server::getByUUID($uuid);
@ -252,14 +322,15 @@ class ServerController extends Controller
$repo->updateSFTPPassword($server->id, $request->input('sftp_pass')); $repo->updateSFTPPassword($server->id, $request->input('sftp_pass'));
Alert::success('Successfully updated this servers SFTP password.')->flash(); Alert::success('Successfully updated this servers SFTP password.')->flash();
} catch (DisplayValidationException $ex) { } 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) { } catch (DisplayException $ex) {
Alert::danger($ex->getMessage())->flash(); Alert::danger($ex->getMessage())->flash();
} catch (\Exception $ex) { } catch (\Exception $ex) {
Log::error($ex); Log::error($ex);
Alert::danger('An unknown error occured while attempting to update this server\'s SFTP settings.')->flash(); 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) public function postSettingsStartup(Request $request, $uuid)
@ -270,19 +341,19 @@ class ServerController extends Controller
try { try {
$repo = new ServerRepository; $repo = new ServerRepository;
$repo->updateStartup($server->id, $request->except([ $repo->updateStartup($server->id, $request->except([
'_token' '_token',
])); ]));
Alert::success('Server startup variables were successfully updated.')->flash(); Alert::success('Server startup variables were successfully updated.')->flash();
} catch (DisplayException $ex) { } catch (DisplayException $ex) {
Alert::danger($ex->getMessage())->flash(); Alert::danger($ex->getMessage())->flash();
} catch(\Exception $ex) { } catch (\Exception $ex) {
Log::error($ex); Log::error($ex);
Alert::danger('An unhandled exception occured while attemping to update startup variables for this server. Please try again.')->flash(); Alert::danger('An unhandled exception occured while attemping to update startup variables for this server. Please try again.')->flash();
} }
return redirect()->route('server.settings', [ return redirect()->route('server.settings', [
'uuid' => $uuid, 'uuid' => $uuid,
'tab' => 'tab_startup' 'tab' => 'tab_startup',
]); ]);
} }
} }

View file

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

View file

@ -1,7 +1,7 @@
<?php <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Http\Controllers\Server; namespace Pterodactyl\Http\Controllers\Server;
use Alert;
use Log; use Log;
use Cron; use Alert;
use Javascript;
use Pterodactyl\Repositories;
use Pterodactyl\Models; use Pterodactyl\Models;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Exceptions\DisplayValidationException;
use Pterodactyl\Http\Controllers\Controller;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Pterodactyl\Repositories;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Http\Controllers\Controller;
use Pterodactyl\Exceptions\DisplayValidationException;
class TaskController extends Controller class TaskController extends Controller
{ {
@ -46,15 +45,21 @@ class TaskController extends Controller
{ {
$server = Models\Server::getByUUID($uuid); $server = Models\Server::getByUUID($uuid);
$this->authorize('list-tasks', $server); $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', [ return view('server.tasks.index', [
'server' => $server, 'server' => $server,
'node' => Models\Node::findOrFail($server->node), 'node' => $node,
'tasks' => Models\Task::where('server', $server->id)->get(), 'tasks' => Models\Task::where('server', $server->id)->get(),
'actions' => [ 'actions' => [
'command' => 'Send Command', 'command' => trans('server.tasks.actions.command'),
'power' => 'Set Power Status' 'power' => trans('server.tasks.actions.power'),
] ],
]); ]);
} }
@ -62,10 +67,16 @@ class TaskController extends Controller
{ {
$server = Models\Server::getByUUID($uuid); $server = Models\Server::getByUUID($uuid);
$this->authorize('create-task', $server); $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', [ return view('server.tasks.new', [
'server' => $server, 'server' => $server,
'node' => Models\Node::findOrFail($server->node) 'node' => $node,
]); ]);
} }
@ -77,30 +88,20 @@ class TaskController extends Controller
try { try {
$repo = new Repositories\TaskRepository; $repo = new Repositories\TaskRepository;
$repo->create($server->id, $request->except([ $repo->create($server->id, $request->except([
'_token' '_token',
])); ]));
return redirect()->route('server.tasks', $uuid);
} catch (DisplayValidationException $ex) { } 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) { } catch (DisplayException $ex) {
Alert::danger($ex->getMessage())->flash(); Alert::danger($ex->getMessage())->flash();
} catch (\Exception $ex) { } catch (\Exception $ex) {
Log::error($ex); Log::error($ex);
Alert::danger('An unknown error occured while attempting to create this task.')->flash(); Alert::danger('An unknown error occured while attempting to create this task.')->flash();
} }
return redirect()->route('server.tasks', $uuid);
} return redirect()->route('server.tasks.new', $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()
]);
} }
public function deleteTask(Request $request, $uuid, $id) public function deleteTask(Request $request, $uuid, $id)
@ -110,20 +111,22 @@ class TaskController extends Controller
$task = Models\Task::findOrFail($id); $task = Models\Task::findOrFail($id);
if (!$task || $server->id !== $task->server) { if (! $task || $server->id !== $task->server) {
return response()->json([ 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); ], 404);
} }
try { try {
$repo = new Repositories\TaskRepository; $repo = new Repositories\TaskRepository;
$repo->delete($id); $repo->delete($id);
return response()->json([], 204); return response()->json([], 204);
} catch (\Exception $ex) { } catch (\Exception $ex) {
Log::error($ex); Log::error($ex);
return response()->json([ 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); ], 503);
} }
} }
@ -135,22 +138,24 @@ class TaskController extends Controller
$task = Models\Task::findOrFail($id); $task = Models\Task::findOrFail($id);
if (!$task || $server->id !== $task->server) { if (! $task || $server->id !== $task->server) {
return response()->json([ 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); ], 404);
} }
try { try {
$repo = new Repositories\TaskRepository; $repo = new Repositories\TaskRepository;
$resp = $repo->toggle($id); $resp = $repo->toggle($id);
return response()->json([ return response()->json([
'status' => $resp 'status' => $resp,
]); ]);
} catch (\Exception $ex) { } catch (\Exception $ex) {
Log::error($ex); Log::error($ex);
return response()->json([ 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); ], 503);
} }
} }

View file

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

View file

@ -1,7 +1,7 @@
<?php <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Http\Middleware; namespace Pterodactyl\Http\Middleware;
use Auth; use Auth;
@ -28,24 +29,20 @@ use Crypt;
use Config; use Config;
use IPTools\IP; use IPTools\IP;
use IPTools\Range; use IPTools\Range;
use Dingo\Api\Routing\Route;
use Illuminate\Http\Request;
use Pterodactyl\Models\User;
use Pterodactyl\Models\APIKey; use Pterodactyl\Models\APIKey;
use Pterodactyl\Models\APIPermission; use Pterodactyl\Models\APIPermission;
use Pterodactyl\Models\User;
use Pterodactyl\Services\APILogService; use Pterodactyl\Services\APILogService;
use Illuminate\Http\Request;
use Dingo\Api\Routing\Route;
use Dingo\Api\Auth\Provider\Authorization; use Dingo\Api\Auth\Provider\Authorization;
use Symfony\Component\HttpKernel\Exception\HttpException; // 400
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; // 400 use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; // 401
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException; // 401
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; // 403 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 class APISecretToken extends Authorization
{ {
protected $algo = 'sha256'; protected $algo = 'sha256';
protected $permissionAllowed = false; protected $permissionAllowed = false;
@ -64,7 +61,7 @@ class APISecretToken extends Authorization
public function authenticate(Request $request, Route $route) 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.'); APILogService::log($request, 'The authentication header was missing or malformed.');
throw new UnauthorizedHttpException('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()); list($public, $hashed) = explode('.', $request->bearerToken());
$key = APIKey::where('public', $public)->first(); $key = APIKey::where('public', $public)->first();
if (!$key) { if (! $key) {
APILogService::log($request, 'Invalid API Key.'); APILogService::log($request, 'Invalid API Key.');
throw new AccessDeniedHttpException('Invalid API Key.'); throw new AccessDeniedHttpException('Invalid API Key.');
} }
// Check for Resource Permissions // Check for Resource Permissions
if (!empty($request->route()->getName())) { if (! empty($request->route()->getName())) {
if(!is_null($key->allowed_ips)) { if (! is_null($key->allowed_ips)) {
$inRange = false; $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()))) { if (Range::parse($ip)->contains(new IP($request->ip()))) {
$inRange = true; $inRange = true;
break; break;
} }
} }
if (!$inRange) { if (! $inRange) {
APILogService::log($request, 'This IP address <' . $request->ip() . '> does not have permission to use this API key.'); 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.'); 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 // Suport Wildcards
if (starts_with($request->route()->getName(), 'api.user')) { if (starts_with($request->route()->getName(), 'api.user')) {
$permission->orWhere('permission', '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.*'); $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.'); 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.'); 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()); $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.'); 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.'); throw new BadRequestHttpException('The hashed body was not valid. Potential modification of contents in route.');
} }
// Log the Route Access // Log the Route Access
APILogService::log($request, null, true); APILogService::log($request, null, true);
return Auth::loginUsingId($key->user);
return Auth::loginUsingId($key->user);
} }
protected function _generateHMAC($body, $key) protected function _generateHMAC($body, $key)
{ {
$data = $this->url . $body; $data = $this->url . $body;
return hash_hmac($this->algo, $data, $key, true); return hash_hmac($this->algo, $data, $key, true);
} }
} }

View file

@ -1,7 +1,7 @@
<?php <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Http\Middleware; namespace Pterodactyl\Http\Middleware;
use Theme;
use Closure; use Closure;
use Illuminate\Contracts\Auth\Guard; 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); return abort(403);
} }
// @TODO: eventually update admin themes
Theme::set('default');
return $next($request); return $next($request);
} }
} }

View file

@ -1,7 +1,7 @@
<?php <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Http\Middleware; namespace Pterodactyl\Http\Middleware;
use Closure;
use Auth; use Auth;
use Closure;
use Pterodactyl\Models\Server; use Pterodactyl\Models\Server;
use Debugbar;
class CheckServer class CheckServer
{ {
@ -39,13 +39,12 @@ class CheckServer
*/ */
public function handle($request, Closure $next) public function handle($request, Closure $next)
{ {
if (! Auth::user()) {
if (!Auth::user()) {
return redirect()->guest('auth/login'); return redirect()->guest('auth/login');
} }
$server = Server::getByUUID($request->route()->server); $server = Server::getByUUID($request->route()->server);
if (!$server) { if (! $server) {
return response()->view('errors.404', [], 404); return response()->view('errors.404', [], 404);
} }
@ -58,6 +57,5 @@ class CheckServer
} }
return $next($request); return $next($request);
} }
} }

View file

@ -1,7 +1,7 @@
<?php <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Listeners;
use Carbon; namespace Pterodactyl\Http\Middleware;
use Pterodactyl\Events\ServerDeleted; use Closure;
use Illuminate\Foundation\Bus\DispatchesJobs; use Pterodactyl\Models\Node;
use Illuminate\Contracts\Auth\Guard;
use Pterodactyl\Jobs\SuspendServer; class DaemonAuthenticate
use Pterodactyl\Jobs\DeleteServer;
class DeleteServerListener
{ {
/**
use DispatchesJobs; * The Guard implementation.
*
* @var Guard
*/
protected $auth;
/** /**
* Create the event listener. * Create a new filter instance.
* *
* @param Guard $auth
* @return void * @return void
*/ */
public function __construct() public function __construct(Guard $auth)
{ {
// $this->auth = $auth;
} }
/** /**
* Handle the event. * Handle an incoming request.
* *
* @param DeleteServerEvent $event * @param \Illuminate\Http\Request $request
* @return void * @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'))); if (! $request->header('X-Access-Node')) {
$this->dispatch( return abort(403);
(new DeleteServer($event->server)) }
->delay(Carbon::now()->addMinutes(env('APP_DELETE_MINUTES', 10)))
->onQueue(env('QUEUE_STANDARD', 'standard')) $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 <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Http\Middleware; namespace Pterodactyl\Http\Middleware;
use Auth; use Auth;
use Closure; use Closure;
use Session; use Session;
use Settings; use Settings;
use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\App;
class LanguageMiddleware class LanguageMiddleware
{ {
public function __construct() public function __construct()
{ {
// //
@ -49,12 +48,13 @@ class LanguageMiddleware
{ {
if (Session::has('applocale')) { if (Session::has('applocale')) {
App::setLocale(Session::get('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); Session::set('applocale', Auth::user()->language);
App::setLocale(Auth::user()->language); App::setLocale(Auth::user()->language);
} else { } else {
App::setLocale(Settings::get('default_language', 'en')); App::setLocale(Settings::get('default_language', 'en'));
} }
return $next($request); return $next($request);
} }
} }

View file

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

View file

@ -1,7 +1,7 @@
<?php <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Http\Routes; namespace Pterodactyl\Http\Routes;
use Pterodactyl\Models;
use Illuminate\Routing\Router; use Illuminate\Routing\Router;
class APIRoutes class APIRoutes
{ {
public function map(Router $router)
public function map(Router $router) { {
$api = app('Dingo\Api\Routing\Router'); $api = app('Dingo\Api\Routing\Router');
$api->version('v1', ['prefix' => 'api/me', 'middleware' => 'api.auth'], function ($api) { $api->version('v1', ['prefix' => 'api/me', 'middleware' => 'api.auth'], function ($api) {
$api->get('/', [ $api->get('/', [
'as' => 'api.user.me', 'as' => 'api.user.me',
'uses' => 'Pterodactyl\Http\Controllers\API\User\InfoController@me' 'uses' => 'Pterodactyl\Http\Controllers\API\User\InfoController@me',
]); ]);
$api->get('/server/{uuid}', [ $api->get('/server/{uuid}', [
'as' => 'api.user.server', 'as' => 'api.user.server',
'uses' => 'Pterodactyl\Http\Controllers\API\User\ServerController@info' 'uses' => 'Pterodactyl\Http\Controllers\API\User\ServerController@info',
]); ]);
$api->put('/server/{uuid}', [ $api->put('/server/{uuid}', [
'as' => 'api.user.server.power', '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) { $api->version('v1', ['prefix' => 'api', 'middleware' => 'api.auth'], function ($api) {
/** /*
* User Routes * User Routes
*/ */
$api->get('users', [ $api->get('users', [
'as' => 'api.admin.users.list', 'as' => 'api.admin.users.list',
'uses' => 'Pterodactyl\Http\Controllers\API\UserController@list' 'uses' => 'Pterodactyl\Http\Controllers\API\UserController@lists',
]); ]);
$api->post('users', [ $api->post('users', [
'as' => 'api.admin.users.create', 'as' => 'api.admin.users.create',
'uses' => 'Pterodactyl\Http\Controllers\API\UserController@create' 'uses' => 'Pterodactyl\Http\Controllers\API\UserController@create',
]); ]);
$api->get('users/{id}', [ $api->get('users/{id}', [
'as' => 'api.admin.users.view', 'as' => 'api.admin.users.view',
'uses' => 'Pterodactyl\Http\Controllers\API\UserController@view' 'uses' => 'Pterodactyl\Http\Controllers\API\UserController@view',
]); ]);
$api->patch('users/{id}', [ $api->patch('users/{id}', [
'as' => 'api.admin.users.update', 'as' => 'api.admin.users.update',
'uses' => 'Pterodactyl\Http\Controllers\API\UserController@update' 'uses' => 'Pterodactyl\Http\Controllers\API\UserController@update',
]); ]);
$api->delete('users/{id}', [ $api->delete('users/{id}', [
'as' => 'api.admin.users.delete', 'as' => 'api.admin.users.delete',
'uses' => 'Pterodactyl\Http\Controllers\API\UserController@delete' 'uses' => 'Pterodactyl\Http\Controllers\API\UserController@delete',
]); ]);
/** /*
* Server Routes * Server Routes
*/ */
$api->get('servers', [ $api->get('servers', [
'as' => 'api.admin.servers.list', 'as' => 'api.admin.servers.list',
'uses' => 'Pterodactyl\Http\Controllers\API\ServerController@list' 'uses' => 'Pterodactyl\Http\Controllers\API\ServerController@lists',
]); ]);
$api->post('servers', [ $api->post('servers', [
'as' => 'api.admin.servers.create', 'as' => 'api.admin.servers.create',
'uses' => 'Pterodactyl\Http\Controllers\API\ServerController@create' 'uses' => 'Pterodactyl\Http\Controllers\API\ServerController@create',
]); ]);
$api->get('servers/{id}', [ $api->get('servers/{id}', [
'as' => 'api.admin.servers.view', 'as' => 'api.admin.servers.view',
'uses' => 'Pterodactyl\Http\Controllers\API\ServerController@view' 'uses' => 'Pterodactyl\Http\Controllers\API\ServerController@view',
]); ]);
$api->patch('servers/{id}/config', [ $api->patch('servers/{id}/config', [
'as' => 'api.admin.servers.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', [ $api->patch('servers/{id}/build', [
'as' => 'api.admin.servers.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', [ $api->post('servers/{id}/suspend', [
'as' => 'api.admin.servers.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', [ $api->post('servers/{id}/unsuspend', [
'as' => 'api.admin.servers.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?}', [ $api->delete('servers/{id}/{force?}', [
'as' => 'api.admin.servers.delete', 'as' => 'api.admin.servers.delete',
'uses' => 'Pterodactyl\Http\Controllers\API\ServerController@delete' 'uses' => 'Pterodactyl\Http\Controllers\API\ServerController@delete',
]); ]);
/** /*
* Node Routes * Node Routes
*/ */
$api->get('nodes', [ $api->get('nodes', [
'as' => 'api.admin.nodes.list', 'as' => 'api.admin.nodes.list',
'uses' => 'Pterodactyl\Http\Controllers\API\NodeController@list' 'uses' => 'Pterodactyl\Http\Controllers\API\NodeController@lists',
]); ]);
$api->post('nodes', [ $api->post('nodes', [
'as' => 'api.admin.nodes.create', 'as' => 'api.admin.nodes.create',
'uses' => 'Pterodactyl\Http\Controllers\API\NodeController@create' 'uses' => 'Pterodactyl\Http\Controllers\API\NodeController@create',
]); ]);
$api->get('nodes/allocations', [ $api->get('nodes/allocations', [
'as' => 'api.admin.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}', [ $api->get('nodes/{id}', [
'as' => 'api.admin.nodes.view', 'as' => 'api.admin.nodes.view',
'uses' => 'Pterodactyl\Http\Controllers\API\NodeController@view' 'uses' => 'Pterodactyl\Http\Controllers\API\NodeController@view',
]); ]);
$api->get('nodes/{id}/config', [ $api->get('nodes/{id}/config', [
'as' => 'api.admin.nodes.view', 'as' => 'api.admin.nodes.view',
'uses' => 'Pterodactyl\Http\Controllers\API\NodeController@config' 'uses' => 'Pterodactyl\Http\Controllers\API\NodeController@config',
]); ]);
$api->delete('nodes/{id}', [ $api->delete('nodes/{id}', [
'as' => 'api.admin.nodes.delete', 'as' => 'api.admin.nodes.delete',
'uses' => 'Pterodactyl\Http\Controllers\API\NodeController@delete' 'uses' => 'Pterodactyl\Http\Controllers\API\NodeController@delete',
]); ]);
/** /*
* Location Routes * Location Routes
*/ */
$api->get('locations', [ $api->get('locations', [
'as' => 'api.admin.locations.list', 'as' => 'api.admin.locations.list',
'uses' => 'Pterodactyl\Http\Controllers\API\LocationController@list' 'uses' => 'Pterodactyl\Http\Controllers\API\LocationController@lists',
]); ]);
/** /*
* Service Routes * Service Routes
*/ */
$api->get('services', [ $api->get('services', [
'as' => 'api.admin.services.list', 'as' => 'api.admin.services.list',
'uses' => 'Pterodactyl\Http\Controllers\API\ServiceController@list' 'uses' => 'Pterodactyl\Http\Controllers\API\ServiceController@lists',
]); ]);
$api->get('services/{id}', [ $api->get('services/{id}', [
'as' => 'api.admin.services.view', '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 <?php
/** /**
* Pterodactyl - Panel * Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com> * Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>
* Some Modifications (c) 2015 Dylan Seidt <dylan.seidt@gmail.com> * Some Modifications (c) 2015 Dylan Seidt <dylan.seidt@gmail.com>.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Http\Routes; namespace Pterodactyl\Http\Routes;
use Illuminate\Routing\Router; use Illuminate\Routing\Router;
class AdminRoutes { class AdminRoutes
{
public function map(Router $router) { public function map(Router $router)
{
// Admin Index // Admin Index
$router->get('admin', [ $router->get('admin', [
@ -36,9 +38,9 @@ class AdminRoutes {
'middleware' => [ 'middleware' => [
'auth', 'auth',
'admin', 'admin',
'csrf' 'csrf',
], ],
'uses' => 'Admin\BaseController@getIndex' 'uses' => 'Admin\BaseController@getIndex',
]); ]);
$router->group([ $router->group([
@ -46,15 +48,15 @@ class AdminRoutes {
'middleware' => [ 'middleware' => [
'auth', 'auth',
'admin', 'admin',
'csrf' 'csrf',
] ],
], function () use ($router) { ], function () use ($router) {
$router->get('/', [ $router->get('/', [
'as' => 'admin.settings', 'as' => 'admin.settings',
'uses' => 'Admin\BaseController@getSettings' 'uses' => 'Admin\BaseController@getSettings',
]); ]);
$router->post('/', [ $router->post('/', [
'uses' => 'Admin\BaseController@postSettings' 'uses' => 'Admin\BaseController@postSettings',
]); ]);
}); });
@ -63,48 +65,47 @@ class AdminRoutes {
'middleware' => [ 'middleware' => [
'auth', 'auth',
'admin', 'admin',
'csrf' 'csrf',
] ],
], function () use ($router) { ], function () use ($router) {
// View All Accounts on System // View All Accounts on System
$router->get('/', [ $router->get('/', [
'as' => 'admin.users', 'as' => 'admin.users',
'uses' => 'Admin\UserController@getIndex' 'uses' => 'Admin\UserController@getIndex',
]); ]);
$router->get('/accounts.json', [ $router->get('/accounts.json', [
'as' => 'admin.users.json', 'as' => 'admin.users.json',
'uses' => 'Admin\UserController@getJson' 'uses' => 'Admin\UserController@getJson',
]); ]);
// View Specific Account // View Specific Account
$router->get('/view/{id}', [ $router->get('/view/{id}', [
'as' => 'admin.users.view', 'as' => 'admin.users.view',
'uses' => 'Admin\UserController@getView' 'uses' => 'Admin\UserController@getView',
]); ]);
// View Specific Account // View Specific Account
$router->post('/view/{id}', [ $router->post('/view/{id}', [
'uses' => 'Admin\UserController@updateUser' 'uses' => 'Admin\UserController@updateUser',
]); ]);
// Delete an Account Matching an ID // Delete an Account Matching an ID
$router->delete('/view/{id}', [ $router->delete('/view/{id}', [
'uses' => 'Admin\UserController@deleteUser' 'uses' => 'Admin\UserController@deleteUser',
]); ]);
// Show Create Account Page // Show Create Account Page
$router->get('/new', [ $router->get('/new', [
'as' => 'admin.users.new', 'as' => 'admin.users.new',
'uses' => 'Admin\UserController@getNew' 'uses' => 'Admin\UserController@getNew',
]); ]);
// Handle Creating New Account // Handle Creating New Account
$router->post('/new', [ $router->post('/new', [
'uses' => 'Admin\UserController@postNew' 'uses' => 'Admin\UserController@postNew',
]); ]);
}); });
// Server Routes // Server Routes
@ -113,108 +114,107 @@ class AdminRoutes {
'middleware' => [ 'middleware' => [
'auth', 'auth',
'admin', 'admin',
'csrf' 'csrf',
] ],
], function () use ($router) { ], function () use ($router) {
// View All Servers // View All Servers
$router->get('/', [ $router->get('/', [
'as' => 'admin.servers', 'as' => 'admin.servers',
'uses' => 'Admin\ServersController@getIndex' ]); 'uses' => 'Admin\ServersController@getIndex', ]);
// View Create Server Page // View Create Server Page
$router->get('/new', [ $router->get('/new', [
'as' => 'admin.servers.new', 'as' => 'admin.servers.new',
'uses' => 'Admin\ServersController@getNew' 'uses' => 'Admin\ServersController@getNew',
]); ]);
// Handle POST Request for Creating Server // Handle POST Request for Creating Server
$router->post('/new', [ $router->post('/new', [
'uses' => 'Admin\ServersController@postNewServer' 'uses' => 'Admin\ServersController@postNewServer',
]); ]);
// Assorted Page Helpers // Assorted Page Helpers
$router->post('/new/get-nodes', [ $router->post('/new/get-nodes', [
'uses' => 'Admin\ServersController@postNewServerGetNodes' 'uses' => 'Admin\ServersController@postNewServerGetNodes',
]); ]);
$router->post('/new/get-ips', [ $router->post('/new/get-ips', [
'uses' => 'Admin\ServersController@postNewServerGetIps' 'uses' => 'Admin\ServersController@postNewServerGetIps',
]); ]);
$router->post('/new/service-options', [ $router->post('/new/service-options', [
'uses' => 'Admin\ServersController@postNewServerServiceOptions' 'uses' => 'Admin\ServersController@postNewServerServiceOptions',
]); ]);
$router->post('/new/service-variables', [ $router->post('/new/option-details', [
'uses' => 'Admin\ServersController@postNewServerServiceVariables' 'uses' => 'Admin\ServersController@postNewServerOptionDetails',
]); ]);
// End Assorted Page Helpers // End Assorted Page Helpers
// View Specific Server // View Specific Server
$router->get('/view/{id}', [ $router->get('/view/{id}', [
'as' => 'admin.servers.view', 'as' => 'admin.servers.view',
'uses' => 'Admin\ServersController@getView' 'uses' => 'Admin\ServersController@getView',
]); ]);
// Database Stuffs // Database Stuffs
$router->post('/view/{id}/database', [ $router->post('/view/{id}/database', [
'as' => 'admin.servers.database', 'as' => 'admin.servers.database',
'uses' => 'Admin\ServersController@postDatabase' 'uses' => 'Admin\ServersController@postDatabase',
]); ]);
// Change Server Details // Change Server Details
$router->post('/view/{id}/details', [ $router->post('/view/{id}/details', [
'uses' => 'Admin\ServersController@postUpdateServerDetails' 'uses' => 'Admin\ServersController@postUpdateServerDetails',
]); ]);
// Change Server Details // Change Server Details
$router->post('/view/{id}/container', [ $router->post('/view/{id}/container', [
'as' => 'admin.servers.post.container', 'as' => 'admin.servers.post.container',
'uses' => 'Admin\ServersController@postUpdateContainerDetails' 'uses' => 'Admin\ServersController@postUpdateContainerDetails',
]); ]);
// Change Server Details // Change Server Details
$router->post('/view/{id}/startup', [ $router->post('/view/{id}/startup', [
'as' => 'admin.servers.post.startup', 'as' => 'admin.servers.post.startup',
'uses' => 'Admin\ServersController@postUpdateServerStartup' 'uses' => 'Admin\ServersController@postUpdateServerStartup',
]); ]);
// Rebuild Server // Rebuild Server
$router->post('/view/{id}/rebuild', [ $router->post('/view/{id}/rebuild', [
'uses' => 'Admin\ServersController@postUpdateServerToggleBuild' 'uses' => 'Admin\ServersController@postUpdateServerToggleBuild',
]); ]);
// Change Build Details // Change Build Details
$router->post('/view/{id}/build', [ $router->post('/view/{id}/build', [
'uses' => 'Admin\ServersController@postUpdateServerUpdateBuild' 'uses' => 'Admin\ServersController@postUpdateServerUpdateBuild',
]); ]);
// Suspend Server // Suspend Server
$router->post('/view/{id}/suspend', [ $router->post('/view/{id}/suspend', [
'uses' => 'Admin\ServersController@postSuspendServer' 'uses' => 'Admin\ServersController@postSuspendServer',
]); ]);
// Unsuspend Server // Unsuspend Server
$router->post('/view/{id}/unsuspend', [ $router->post('/view/{id}/unsuspend', [
'uses' => 'Admin\ServersController@postUnsuspendServer' 'uses' => 'Admin\ServersController@postUnsuspendServer',
]); ]);
// Change Install Status // Change Install Status
$router->post('/view/{id}/installed', [ $router->post('/view/{id}/installed', [
'uses' => 'Admin\ServersController@postToggleInstall' 'uses' => 'Admin\ServersController@postToggleInstall',
]); ]);
// Delete [force delete] // Delete [force delete]
$router->delete('/view/{id}/{force?}', [ $router->delete('/view/{id}/{force?}', [
'uses' => 'Admin\ServersController@deleteServer' 'uses' => 'Admin\ServersController@deleteServer',
]); ]);
$router->post('/view/{id}/queuedDeletion', [ $router->post('/view/{id}/queuedDeletion', [
'uses' => 'Admin\ServersController@postQueuedDeletionHandler', 'uses' => 'Admin\ServersController@postQueuedDeletionHandler',
'as' => 'admin.servers.post.queuedDeletion' 'as' => 'admin.servers.post.queuedDeletion',
]); ]);
}); });
// Node Routes // Node Routes
@ -223,70 +223,74 @@ class AdminRoutes {
'middleware' => [ 'middleware' => [
'auth', 'auth',
'admin', 'admin',
'csrf' 'csrf',
] ],
], function () use ($router) { ], function () use ($router) {
// View All Nodes // View All Nodes
$router->get('/', [ $router->get('/', [
'as' => 'admin.nodes', 'as' => 'admin.nodes',
'uses' => 'Admin\NodesController@getIndex' 'uses' => 'Admin\NodesController@getIndex',
]); ]);
// Add New Node // Add New Node
$router->get('/new', [ $router->get('/new', [
'as' => 'admin.nodes.new', 'as' => 'admin.nodes.new',
'uses' => 'Admin\NodesController@getNew' 'uses' => 'Admin\NodesController@getNew',
]); ]);
$router->post('/new', [ $router->post('/new', [
'uses' => 'Admin\NodesController@postNew' 'uses' => 'Admin\NodesController@postNew',
]); ]);
// View Node // View Node
$router->get('/view/{id}', [ $router->get('/view/{id}', [
'as' => 'admin.nodes.view', 'as' => 'admin.nodes.view',
'uses' => 'Admin\NodesController@getView' 'uses' => 'Admin\NodesController@getView',
]); ]);
$router->post('/view/{id}', [ $router->post('/view/{id}', [
'uses' => 'Admin\NodesController@postView' 'uses' => 'Admin\NodesController@postView',
]); ]);
$router->delete('/view/{id}/deallocate/single/{allocation}', [ $router->delete('/view/{id}/deallocate/single/{allocation}', [
'uses' => 'Admin\NodesController@deallocateSingle' 'uses' => 'Admin\NodesController@deallocateSingle',
]); ]);
$router->post('/view/{id}/deallocate/block', [ $router->post('/view/{id}/deallocate/block', [
'uses' => 'Admin\NodesController@deallocateBlock' 'uses' => 'Admin\NodesController@deallocateBlock',
]); ]);
$router->post('/view/{id}/alias', [ $router->post('/view/{id}/alias', [
'as' => 'admin.nodes.alias', 'as' => 'admin.nodes.alias',
'uses' => 'Admin\NodesController@setAlias' 'uses' => 'Admin\NodesController@setAlias',
]); ]);
$router->get('/view/{id}/allocations.json', [ $router->get('/view/{id}/allocations.json', [
'as' => 'admin.nodes.view.allocations', 'as' => 'admin.nodes.view.allocations',
'uses' => 'Admin\NodesController@getAllocationsJson' 'uses' => 'Admin\NodesController@getAllocationsJson',
]); ]);
$router->post('/view/{id}/allocations', [ $router->post('/view/{id}/allocations', [
'as' => 'admin.nodes.post.allocations', 'as' => 'admin.nodes.post.allocations',
'uses' => 'Admin\NodesController@postAllocations' 'uses' => 'Admin\NodesController@postAllocations',
]); ]);
// View Deploy // View Deploy
$router->get('/view/{id}/deploy', [ $router->get('/view/{id}/deploy', [
'as' => 'admin.nodes.deply', 'as' => 'admin.nodes.deply',
'uses' => 'Admin\NodesController@getScript' 'uses' => 'Admin\NodesController@getScript',
]); ]);
$router->delete('/view/{id}', [ $router->delete('/view/{id}', [
'as' => 'admin.nodes.delete', '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 // Location Routes
@ -295,21 +299,21 @@ class AdminRoutes {
'middleware' => [ 'middleware' => [
'auth', 'auth',
'admin', 'admin',
'csrf' 'csrf',
] ],
], function () use ($router) { ], function () use ($router) {
$router->get('/', [ $router->get('/', [
'as' => 'admin.locations', 'as' => 'admin.locations',
'uses' => 'Admin\LocationsController@getIndex' 'uses' => 'Admin\LocationsController@getIndex',
]); ]);
$router->delete('/{id}', [ $router->delete('/{id}', [
'uses' => 'Admin\LocationsController@deleteLocation' 'uses' => 'Admin\LocationsController@deleteLocation',
]); ]);
$router->patch('/{id}', [ $router->patch('/{id}', [
'uses' => 'Admin\LocationsController@patchLocation' 'uses' => 'Admin\LocationsController@patchLocation',
]); ]);
$router->post('/', [ $router->post('/', [
'uses' => 'Admin\LocationsController@postLocation' 'uses' => 'Admin\LocationsController@postLocation',
]); ]);
}); });
@ -319,27 +323,27 @@ class AdminRoutes {
'middleware' => [ 'middleware' => [
'auth', 'auth',
'admin', 'admin',
'csrf' 'csrf',
] ],
], function () use ($router) { ], function () use ($router) {
$router->get('/', [ $router->get('/', [
'as' => 'admin.databases', 'as' => 'admin.databases',
'uses' => 'Admin\DatabaseController@getIndex' 'uses' => 'Admin\DatabaseController@getIndex',
]); ]);
$router->get('/new', [ $router->get('/new', [
'as' => 'admin.databases.new', 'as' => 'admin.databases.new',
'uses' => 'Admin\DatabaseController@getNew' 'uses' => 'Admin\DatabaseController@getNew',
]); ]);
$router->post('/new', [ $router->post('/new', [
'uses' => 'Admin\DatabaseController@postNew' 'uses' => 'Admin\DatabaseController@postNew',
]); ]);
$router->delete('/delete/{id}', [ $router->delete('/delete/{id}', [
'as' => 'admin.databases.delete', 'as' => 'admin.databases.delete',
'uses' => 'Admin\DatabaseController@deleteDatabase' 'uses' => 'Admin\DatabaseController@deleteDatabase',
]); ]);
$router->delete('/delete-server/{id}', [ $router->delete('/delete-server/{id}', [
'as' => 'admin.databases.delete-server', 'as' => 'admin.databases.delete-server',
'uses' => 'Admin\DatabaseController@deleteServer' 'uses' => 'Admin\DatabaseController@deleteServer',
]); ]);
}); });
@ -349,78 +353,133 @@ class AdminRoutes {
'middleware' => [ 'middleware' => [
'auth', 'auth',
'admin', 'admin',
'csrf' 'csrf',
] ],
], function () use ($router) { ], function () use ($router) {
$router->get('/', [ $router->get('/', [
'as' => 'admin.services', 'as' => 'admin.services',
'uses' => 'Admin\ServiceController@getIndex' 'uses' => 'Admin\ServiceController@getIndex',
]); ]);
$router->get('/new', [ $router->get('/new', [
'as' => 'admin.services.new', 'as' => 'admin.services.new',
'uses' => 'Admin\ServiceController@getNew' 'uses' => 'Admin\ServiceController@getNew',
]); ]);
$router->post('/new', [ $router->post('/new', [
'uses' => 'Admin\ServiceController@postNew' 'uses' => 'Admin\ServiceController@postNew',
]); ]);
$router->get('/service/{id}', [ $router->get('/service/{id}', [
'as' => 'admin.services.service', 'as' => 'admin.services.service',
'uses' => 'Admin\ServiceController@getService' 'uses' => 'Admin\ServiceController@getService',
]); ]);
$router->post('/service/{id}', [ $router->post('/service/{id}', [
'uses' => 'Admin\ServiceController@postService' 'uses' => 'Admin\ServiceController@postService',
]); ]);
$router->delete('/service/{id}', [ $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', [ $router->get('/service/{service}/option/new', [
'as' => 'admin.services.option.new', 'as' => 'admin.services.option.new',
'uses' => 'Admin\ServiceController@newOption' 'uses' => 'Admin\ServiceController@newOption',
]); ]);
$router->post('/service/{service}/option/new', [ $router->post('/service/{service}/option/new', [
'uses' => 'Admin\ServiceController@postNewOption' 'uses' => 'Admin\ServiceController@postNewOption',
]); ]);
$router->get('/service/{service}/option/{option}', [ $router->get('/service/{service}/option/{option}', [
'as' => 'admin.services.option', 'as' => 'admin.services.option',
'uses' => 'Admin\ServiceController@getOption' 'uses' => 'Admin\ServiceController@getOption',
]); ]);
$router->post('/service/{service}/option/{option}', [ $router->post('/service/{service}/option/{option}', [
'uses' => 'Admin\ServiceController@postOption' 'uses' => 'Admin\ServiceController@postOption',
]); ]);
$router->delete('/service/{service}/option/{id}', [ $router->delete('/service/{service}/option/{id}', [
'uses' => 'Admin\ServiceController@deleteOption' 'uses' => 'Admin\ServiceController@deleteOption',
]); ]);
$router->get('/service/{service}/option/{option}/variable/new', [ $router->get('/service/{service}/option/{option}/variable/new', [
'as' => 'admin.services.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', [ $router->post('/service/{service}/option/{option}/variable/new', [
'uses' => 'Admin\ServiceController@postNewVariable' 'uses' => 'Admin\ServiceController@postNewVariable',
]); ]);
$router->post('/service/{service}/option/{option}/variable/{variable}', [ $router->post('/service/{service}/option/{option}/variable/{variable}', [
'as' => 'admin.services.option.variable', 'as' => 'admin.services.option.variable',
'uses' => 'Admin\ServiceController@postOptionVariable' 'uses' => 'Admin\ServiceController@postOptionVariable',
]); ]);
$router->get('/service/{service}/option/{option}/variable/{variable}/delete', [ $router->get('/service/{service}/option/{option}/variable/{variable}/delete', [
'as' => 'admin.services.option.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 <?php
/** /**
* Pterodactyl - Panel * Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com> * Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>
* Some Modifications (c) 2015 Dylan Seidt <dylan.seidt@gmail.com> * Some Modifications (c) 2015 Dylan Seidt <dylan.seidt@gmail.com>.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Http\Routes; namespace Pterodactyl\Http\Routes;
use Illuminate\Routing\Router;
use Request;
use Pterodactyl\Models\User as User;
use Auth; use Auth;
class AuthRoutes { use Illuminate\Routing\Router;
public function map(Router $router) { class AuthRoutes
{
public function map(Router $router)
{
$router->group([ $router->group([
'prefix' => 'auth', 'prefix' => 'auth',
'middleware' => [ 'middleware' => [
'guest', 'guest',
'csrf' 'csrf',
] ],
], function () use ($router) { ], function () use ($router) {
// Display Login Page // Display Login Page
$router->get('login', [ $router->get('login', [
'as' => 'auth.login', 'as' => 'auth.login',
'uses' => 'Auth\LoginController@showLoginForm' 'uses' => 'Auth\LoginController@showLoginForm',
]); ]);
// Handle Login // Handle Login
$router->post('login', [ $router->post('login', [
'uses' => 'Auth\LoginController@login' 'uses' => 'Auth\LoginController@login',
]); ]);
// Determine if we need to ask for a TOTP Token // Determine if we need to ask for a TOTP Token
$router->post('login/totp', [ $router->post('login/totp', [
'uses' => 'Auth\LoginController@checkTotp' 'uses' => 'Auth\LoginController@checkTotp',
]); ]);
// Show Password Reset Form // Show Password Reset Form
$router->get('password', [ $router->get('password', [
'as' => 'auth.password', 'as' => 'auth.password',
'uses' => 'Auth\ForgotPasswordController@showLinkRequestForm' 'uses' => 'Auth\ForgotPasswordController@showLinkRequestForm',
]); ]);
// Handle Password Reset // Handle Password Reset
$router->post('password', [ $router->post('password', [
'uses' => 'Auth\ForgotPasswordController@sendResetLinkEmail' 'uses' => 'Auth\ForgotPasswordController@sendResetLinkEmail',
]); ]);
// Show Verification Checkpoint // Show Verification Checkpoint
$router->get('password/reset/{token}', [ $router->get('password/reset/{token}', [
'as' => 'auth.reset', 'as' => 'auth.reset',
'uses' => 'Auth\ResetPasswordController@showResetForm' 'uses' => 'Auth\ResetPasswordController@showResetForm',
]); ]);
// Handle Verification // Handle Verification
$router->post('password/reset', [ $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 // Not included above because we don't want the guest middleware
$router->get('auth/logout', [ $router->get('auth/logout', [
'as' => 'auth.logout', 'as' => 'auth.logout',
'middleware' => 'auth', 'middleware' => 'auth',
'uses' => 'Auth\LoginController@logout' 'uses' => 'Auth\LoginController@logout',
]); ]);
} }
} }

View file

@ -1,8 +1,8 @@
<?php <?php
/** /**
* Pterodactyl - Panel * Pterodactyl - Panel
* Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com> * Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>
* Some Modifications (c) 2015 Dylan Seidt <dylan.seidt@gmail.com> * Some Modifications (c) 2015 Dylan Seidt <dylan.seidt@gmail.com>.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Http\Routes; namespace Pterodactyl\Http\Routes;
use Illuminate\Routing\Router; use Illuminate\Routing\Router;
class BaseRoutes { class BaseRoutes
{
public function map(Router $router) { public function map(Router $router)
{
// Index of Panel // Index of Panel
$router->get('/', [ $router->get('/', [
'as' => 'index', 'as' => 'index',
'middleware' => 'auth', 'middleware' => 'auth',
'uses' => 'Base\IndexController@getIndex' 'uses' => 'Base\IndexController@getIndex',
]); ]);
// Handle Index. Redirect /index to / // Handle Index. Redirect /index to /
@ -46,7 +48,7 @@ class BaseRoutes {
$router->get('/password-gen/{length}', [ $router->get('/password-gen/{length}', [
'as' => 'password-gen', 'as' => 'password-gen',
'middleware' => 'auth', 'middleware' => 'auth',
'uses' => 'Base\IndexController@getPassword' 'uses' => 'Base\IndexController@getPassword',
]); ]);
// Account Routes // Account Routes
@ -54,18 +56,15 @@ class BaseRoutes {
'prefix' => 'account', 'prefix' => 'account',
'middleware' => [ 'middleware' => [
'auth', 'auth',
'csrf' 'csrf',
] ],
], function () use ($router) { ], function () use ($router) {
$router->get('/', [ $router->get('/', [
'as' => 'account', 'as' => 'account',
'uses' => 'Base\AccountController@index' 'uses' => 'Base\AccountController@index',
]); ]);
$router->post('/password', [ $router->post('/', [
'uses' => 'Base\AccountController@password' 'uses' => 'Base\AccountController@update',
]);
$router->post('/email', [
'uses' => 'Base\AccountController@email'
]); ]);
}); });
@ -74,23 +73,23 @@ class BaseRoutes {
'prefix' => 'account/api', 'prefix' => 'account/api',
'middleware' => [ 'middleware' => [
'auth', 'auth',
'csrf' 'csrf',
] ],
], function () use ($router) { ], function () use ($router) {
$router->get('/', [ $router->get('/', [
'as' => 'account.api', 'as' => 'account.api',
'uses' => 'Base\APIController@index' 'uses' => 'Base\APIController@index',
]); ]);
$router->get('/new', [ $router->get('/new', [
'as' => 'account.api.new', 'as' => 'account.api.new',
'uses' => 'Base\APIController@new' 'uses' => 'Base\APIController@create',
]); ]);
$router->post('/new', [ $router->post('/new', [
'uses' => 'Base\APIController@save' 'uses' => 'Base\APIController@save',
]); ]);
$router->delete('/revoke/{key}', [ $router->delete('/revoke/{key}', [
'uses' => 'Base\APIController@revoke' 'uses' => 'Base\APIController@revoke',
]); ]);
}); });
@ -99,28 +98,27 @@ class BaseRoutes {
'prefix' => 'account/security', 'prefix' => 'account/security',
'middleware' => [ 'middleware' => [
'auth', 'auth',
'csrf' 'csrf',
] ],
], function () use ($router) { ], function () use ($router) {
$router->get('/', [ $router->get('/', [
'as' => 'account.security', 'as' => 'account.security',
'uses' => 'Base\SecurityController@index' 'uses' => 'Base\SecurityController@index',
]); ]);
$router->get('/revoke/{id}', [ $router->get('/revoke/{id}', [
'as' => 'account.security.revoke', 'as' => 'account.security.revoke',
'uses' => 'Base\SecurityController@revoke' 'uses' => 'Base\SecurityController@revoke',
]); ]);
$router->put('/totp', [ $router->put('/totp', [
'uses' => 'Base\SecurityController@generateTotp' 'as' => 'account.security.totp',
'uses' => 'Base\SecurityController@generateTotp',
]); ]);
$router->post('/totp', [ $router->post('/totp', [
'uses' => 'Base\SecurityController@setTotp' 'uses' => 'Base\SecurityController@setTotp',
]); ]);
$router->delete('/totp', [ $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 <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Http\Routes; namespace Pterodactyl\Http\Routes;
use Illuminate\Routing\Router; use Illuminate\Routing\Router;
class LanguageRoutes { class LanguageRoutes
{
public function map(Router $router) public function map(Router $router)
{ {
$router->get('language/{lang}', [ $router->get('language/{lang}', [
'as' => 'langauge.set', 'as' => 'langauge.set',
'uses' => 'Base\LanguageController@setLanguage' 'uses' => 'Base\LanguageController@setLanguage',
]); ]);
} }
} }

View file

@ -1,7 +1,7 @@
<?php <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Http\Routes; namespace Pterodactyl\Http\Routes;
use Illuminate\Routing\Router; use Illuminate\Routing\Router;
use Request;
class RemoteRoutes { class RemoteRoutes
{
public function map(Router $router) { public function map(Router $router)
{
$router->group(['prefix' => 'remote'], function () use ($router) { $router->group(['prefix' => 'remote'], function () use ($router) {
// Handles Remote Download Authentication Requests // Handles Remote Download Authentication Requests
$router->post('download', [ $router->post('download', [
'as' => 'remote.download', 'as' => 'remote.download',
'uses' => 'Remote\RemoteController@postDownload' 'uses' => 'Remote\RemoteController@postDownload',
]); ]);
$router->post('install', [ $router->post('install', [
'as' => 'remote.install', 'as' => 'remote.install',
'uses' => 'Remote\RemoteController@postInstall' 'uses' => 'Remote\RemoteController@postInstall',
]); ]);
$router->post('event', [ $router->get('configuration/{token}', [
'as' => 'remote.event', 'as' => 'remote.configuration',
'uses' => 'Remote\RemoteController@event' 'uses' => 'Remote\RemoteController@getConfiguration',
]); ]);
}); });
} }
} }

View file

@ -1,7 +1,7 @@
<?php <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Http\Routes; namespace Pterodactyl\Http\Routes;
use Illuminate\Routing\Router; use Illuminate\Routing\Router;
class ServerRoutes { class ServerRoutes
{
public function map(Router $router) { public function map(Router $router)
{
$router->group([ $router->group([
'prefix' => 'server/{server}', 'prefix' => 'server/{server}',
'middleware' => [ 'middleware' => [
'auth', 'auth',
'server', 'server',
'csrf' 'csrf',
] ],
], function ($server) use ($router) { ], function ($server) use ($router) {
// Index View for Server // Index View for Server
$router->get('/', [ $router->get('/', [
'as' => 'server.index', 'as' => 'server.index',
'uses' => 'Server\ServerController@getIndex' 'uses' => 'Server\ServerController@getIndex',
]); ]);
// Settings // Settings
$router->get('/settings', [ $router->get('/settings', [
'as' => 'server.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', [ $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', [ $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 // File Manager Routes
$router->get('/files', [ $router->get('/files', [
'as' => 'server.files.index', 'as' => 'server.files.index',
'uses' => 'Server\ServerController@getFiles' 'uses' => 'Server\ServerController@getFiles',
]); ]);
$router->get('/files/edit/{file}', [ $router->get('/files/edit/{file}', [
'as' => 'server.files.edit', 'as' => 'server.files.edit',
'uses' => 'Server\ServerController@getEditFile' 'uses' => 'Server\ServerController@getEditFile',
])->where('file', '.*'); ])->where('file', '.*');
$router->get('/files/download/{file}', [ $router->get('/files/download/{file}', [
'as' => 'server.files.download', 'as' => 'server.files.download',
'uses' => 'Server\ServerController@getDownloadFile' 'uses' => 'Server\ServerController@getDownloadFile',
])->where('file', '.*'); ])->where('file', '.*');
$router->get('/files/add', [ $router->get('/files/add', [
'as' => 'server.files.add', 'as' => 'server.files.add',
'uses' => 'Server\ServerController@getAddFile' 'uses' => 'Server\ServerController@getAddFile',
]); ]);
$router->post('files/directory-list', [ $router->post('files/directory-list', [
'as' => 'server.files.directory-list', 'as' => 'server.files.directory-list',
'uses' => 'Server\AjaxController@postDirectoryList' 'uses' => 'Server\AjaxController@postDirectoryList',
]); ]);
$router->post('files/save', [ $router->post('files/save', [
'as' => 'server.files.save', 'as' => 'server.files.save',
'uses' => 'Server\AjaxController@postSaveFile' 'uses' => 'Server\AjaxController@postSaveFile',
]); ]);
// Sub-User Routes // Sub-User Routes
$router->get('users', [ $router->get('users', [
'as' => 'server.subusers', 'as' => 'server.subusers',
'uses' => 'Server\SubuserController@getIndex' 'uses' => 'Server\SubuserController@getIndex',
]); ]);
$router->get('users/new', [ $router->get('users/new', [
'as' => 'server.subusers.new', 'as' => 'server.subusers.new',
'uses' => 'Server\SubuserController@getNew' 'uses' => 'Server\SubuserController@getNew',
]); ]);
$router->post('users/new', [ $router->post('users/new', [
'uses' => 'Server\SubuserController@postNew' 'uses' => 'Server\SubuserController@postNew',
]); ]);
$router->get('users/view/{id}', [ $router->get('users/view/{id}', [
'as' => 'server.subusers.view', 'as' => 'server.subusers.view',
'uses' => 'Server\SubuserController@getView' 'uses' => 'Server\SubuserController@getView',
]); ]);
$router->post('users/view/{id}', [ $router->post('users/view/{id}', [
'uses' => 'Server\SubuserController@postView' 'uses' => 'Server\SubuserController@postView',
]); ]);
$router->delete('users/delete/{id}', [ $router->delete('users/delete/{id}', [
'uses' => 'Server\SubuserController@deleteSubuser' 'uses' => 'Server\SubuserController@deleteSubuser',
]); ]);
$router->get('tasks/', [ $router->get('tasks/', [
'as' => 'server.tasks', 'as' => 'server.tasks',
'uses' => 'Server\TaskController@getIndex' 'uses' => 'Server\TaskController@getIndex',
]); ]);
$router->get('tasks/view/{id}', [ $router->get('tasks/view/{id}', [
'as' => 'server.tasks.view', 'as' => 'server.tasks.view',
'uses' => 'Server\TaskController@getView' 'uses' => 'Server\TaskController@getView',
]); ]);
$router->get('tasks/new', [ $router->get('tasks/new', [
'as' => 'server.tasks.new', 'as' => 'server.tasks.new',
'uses' => 'Server\TaskController@getNew' 'uses' => 'Server\TaskController@getNew',
]); ]);
$router->post('tasks/new', [ $router->post('tasks/new', [
'uses' => 'Server\TaskController@postNew' 'uses' => 'Server\TaskController@postNew',
]); ]);
$router->delete('tasks/delete/{id}', [ $router->delete('tasks/delete/{id}', [
'as' => 'server.tasks.delete', 'as' => 'server.tasks.delete',
'uses' => 'Server\TaskController@deleteTask' 'uses' => 'Server\TaskController@deleteTask',
]); ]);
$router->post('tasks/toggle/{id}', [ $router->post('tasks/toggle/{id}', [
'as' => 'server.tasks.toggle', 'as' => 'server.tasks.toggle',
'uses' => 'Server\TaskController@toggleTask' 'uses' => 'Server\TaskController@toggleTask',
]); ]);
// Assorted AJAX Routes // Assorted AJAX Routes
$router->group(['prefix' => 'ajax'], function ($server) use ($router) { $router->group(['prefix' => 'ajax'], function ($server) use ($router) {
// Returns Server Status // Returns Server Status
$router->get('status', [ $router->get('status', [
'uses' => 'Server\AjaxController@getStatus' 'as' => 'server.ajax.status',
'uses' => 'Server\AjaxController@getStatus',
]); ]);
// Sets the Default Connection for the Server // Sets the Default Connection for the Server
$router->post('set-primary', [ $router->post('set-primary', [
'uses' => 'Server\AjaxController@postSetPrimary' 'uses' => 'Server\AjaxController@postSetPrimary',
]); ]);
$router->post('settings/reset-database-password', [ $router->post('settings/reset-database-password', [
'as' => 'server.ajax.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 <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Jobs; namespace Pterodactyl\Jobs;
use DB;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Pterodactyl\Models;
use Pterodactyl\Repositories\ServerRepository; use Pterodactyl\Repositories\ServerRepository;
class DeleteServer extends Job implements ShouldQueue class DeleteServer extends Job implements ShouldQueue
@ -46,7 +42,7 @@ class DeleteServer extends Job implements ShouldQueue
/** /**
* Create a new job instance. * Create a new job instance.
* *
* @param integer $server * @param int $server
* @return void * @return void
*/ */
public function __construct($id) public function __construct($id)

View file

@ -1,7 +1,7 @@
<?php <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Jobs; namespace Pterodactyl\Jobs;
use Pterodactyl\Jobs\Job; use Cron;
use Carbon;
use Pterodactyl\Models;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue; 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\PowerRepository;
use Pterodactyl\Repositories\Daemon\CommandRepository;
class SendScheduledTask extends Job implements ShouldQueue class SendScheduledTask extends Job implements ShouldQueue
{ {
@ -76,7 +74,7 @@ class SendScheduledTask extends Job implements ShouldQueue
if ($this->task->action === 'command') { if ($this->task->action === 'command') {
$repo = new CommandRepository($this->server); $repo = new CommandRepository($this->server);
$response = $repo->send($this->task->data); $response = $repo->send($this->task->data);
} else if ($this->task->action === 'power') { } elseif ($this->task->action === 'power') {
$repo = new PowerRepository($this->server); $repo = new PowerRepository($this->server);
$response = $repo->do($this->task->data); $response = $repo->do($this->task->data);
} }
@ -84,14 +82,14 @@ class SendScheduledTask extends Job implements ShouldQueue
'task_id' => $this->task->id, 'task_id' => $this->task->id,
'run_time' => $time, 'run_time' => $time,
'run_status' => 0, 'run_status' => 0,
'response' => $response 'response' => $response,
]); ]);
} catch (\Exception $ex) { } catch (\Exception $ex) {
$log->fill([ $log->fill([
'task_id' => $this->task->id, 'task_id' => $this->task->id,
'run_time' => $time, 'run_time' => $time,
'run_status' => 1, 'run_status' => 1,
'response' => $ex->getMessage() 'response' => $ex->getMessage(),
]); ]);
} finally { } finally {
$cron = Cron::factory(sprintf('%s %s %s %s %s %s', $cron = Cron::factory(sprintf('%s %s %s %s %s %s',
@ -105,7 +103,7 @@ class SendScheduledTask extends Job implements ShouldQueue
$this->task->fill([ $this->task->fill([
'last_run' => $time, 'last_run' => $time,
'next_run' => $cron->getNextRunDate(), 'next_run' => $cron->getNextRunDate(),
'queued' => 0 'queued' => 0,
]); ]);
$this->task->save(); $this->task->save();
$log->save(); $log->save();

View file

@ -1,7 +1,7 @@
<?php <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Jobs; namespace Pterodactyl\Jobs;
use Debugbar;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Pterodactyl\Repositories\ServerRepository; use Pterodactyl\Repositories\ServerRepository;
class SuspendServer extends Job implements ShouldQueue class SuspendServer extends Job implements ShouldQueue
@ -44,7 +42,7 @@ class SuspendServer extends Job implements ShouldQueue
/** /**
* Create a new job instance. * Create a new job instance.
* *
* @param integer $id * @param int $id
* @return void * @return void
*/ */
public function __construct($id) public function __construct($id)

View file

@ -1,7 +1,7 @@
<?php <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Models; namespace Pterodactyl\Models;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
class APIKey extends Model class APIKey extends Model
{ {
/** /**
* The table associated with the model. * The table associated with the model.
* *
@ -48,5 +48,4 @@ class APIKey extends Model
* @var array * @var array
*/ */
protected $guarded = ['id', 'created_at', 'updated_at']; protected $guarded = ['id', 'created_at', 'updated_at'];
} }

View file

@ -1,7 +1,7 @@
<?php <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Models; namespace Pterodactyl\Models;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
class APILog extends Model class APILog extends Model
{ {
/** /**
* The table associated with the model. * The table associated with the model.
* *
@ -49,13 +49,12 @@ class APILog extends Model
*/ */
protected $guarded = ['id', 'created_at', 'updated_at']; protected $guarded = ['id', 'created_at', 'updated_at'];
/** /**
* Cast values to correct type. * Cast values to correct type.
* *
* @var array * @var array
*/ */
protected $casts = [ protected $casts = [
'authorized' => 'boolean' 'authorized' => 'boolean',
]; ];
} }

View file

@ -1,7 +1,7 @@
<?php <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Models; namespace Pterodactyl\Models;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
class APIPermission extends Model class APIPermission extends Model
{ {
/** /**
* The table associated with the model. * The table associated with the model.
* *
@ -42,11 +42,11 @@ class APIPermission extends Model
*/ */
protected $guarded = ['id']; protected $guarded = ['id'];
/** /**
* Cast values to correct type. * Cast values to correct type.
* *
* @var array * @var array
*/ */
protected $casts = [ protected $casts = [
'key_id' => 'integer', 'key_id' => 'integer',
]; ];
@ -54,8 +54,7 @@ class APIPermission extends Model
/** /**
* Disable timestamps for this table. * Disable timestamps for this table.
* *
* @var boolean * @var bool
*/ */
public $timestamps = false; public $timestamps = false;
} }

View file

@ -1,7 +1,7 @@
<?php <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Models; namespace Pterodactyl\Models;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
class Allocation extends Model class Allocation extends Model
{ {
/** /**
* The table associated with the model. * The table associated with the model.
* *
@ -42,15 +42,14 @@ class Allocation extends Model
*/ */
protected $guarded = ['id', 'created_at', 'updated_at']; protected $guarded = ['id', 'created_at', 'updated_at'];
/** /**
* Cast values to correct type. * Cast values to correct type.
* *
* @var array * @var array
*/ */
protected $casts = [ protected $casts = [
'node' => 'integer', 'node' => 'integer',
'port' => 'integer', 'port' => 'integer',
'assigned_to' => '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 <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Models; namespace Pterodactyl\Models;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
class Database extends Model class Database extends Model
{ {
/** /**
* The table associated with the model. * The table associated with the model.
* *
@ -49,14 +49,13 @@ class Database extends Model
*/ */
protected $guarded = ['id', 'created_at', 'updated_at']; protected $guarded = ['id', 'created_at', 'updated_at'];
/** /**
* Cast values to correct type. * Cast values to correct type.
* *
* @var array * @var array
*/ */
protected $casts = [ protected $casts = [
'server' => 'integer', 'server' => 'integer',
'db_server' => 'integer', 'db_server' => 'integer',
]; ];
} }

View file

@ -1,7 +1,7 @@
<?php <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Models; namespace Pterodactyl\Models;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
class DatabaseServer extends Model class DatabaseServer extends Model
{ {
/** /**
* The table associated with the model. * The table associated with the model.
* *
@ -49,15 +49,14 @@ class DatabaseServer extends Model
*/ */
protected $guarded = ['id', 'created_at', 'updated_at']; protected $guarded = ['id', 'created_at', 'updated_at'];
/** /**
* Cast values to correct type. * Cast values to correct type.
* *
* @var array * @var array
*/ */
protected $casts = [ protected $casts = [
'id' => 'integer', 'id' => 'integer',
'server_id' => 'integer', 'server_id' => 'integer',
'db_server' => 'integer' 'db_server' => 'integer',
]; ];
} }

View file

@ -1,7 +1,7 @@
<?php <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Models; namespace Pterodactyl\Models;
use Debugbar;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
class Download extends Model class Download extends Model
{ {
/** /**
* The table associated with the model. * The table associated with the model.
* *
* @var string * @var string
*/ */
protected $table = 'downloads'; protected $table = 'downloads';
} }

View file

@ -1,7 +1,7 @@
<?php <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Models; namespace Pterodactyl\Models;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
class Location extends Model class Location extends Model
{ {
/** /**
* The table associated with the model. * The table associated with the model.
* *
@ -41,5 +41,4 @@ class Location extends Model
* @var array * @var array
*/ */
protected $guarded = ['id', 'created_at', 'updated_at']; protected $guarded = ['id', 'created_at', 'updated_at'];
} }

View file

@ -1,7 +1,7 @@
<?php <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Models; namespace Pterodactyl\Models;
use GuzzleHttp\Client; use GuzzleHttp\Client;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Notifications\Notifiable;
class Node extends Model class Node extends Model
{ {
use Notifiable;
/** /**
* The table associated with the model. * The table associated with the model.
@ -43,11 +46,11 @@ class Node extends Model
*/ */
protected $hidden = ['daemonSecret']; protected $hidden = ['daemonSecret'];
/** /**
* Cast values to correct type. * Cast values to correct type.
* *
* @var array * @var array
*/ */
protected $casts = [ protected $casts = [
'public' => 'integer', 'public' => 'integer',
'location' => 'integer', 'location' => 'integer',
@ -88,9 +91,9 @@ class Node extends Model
return self::$nodes[$id]; return self::$nodes[$id];
} }
self::$nodes[$id] = Node::where('id', $id)->first(); self::$nodes[$id] = self::where('id', $id)->first();
return self::$nodes[$id];
return self::$nodes[$id];
} }
/** /**
@ -116,7 +119,62 @@ class Node extends Model
]); ]);
return self::$guzzle[$node]; 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 <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
return [
/* namespace Pterodactyl\Models;
|--------------------------------------------------------------------------
| Password Reminder Language Lines use Illuminate\Database\Eloquent\Model;
|--------------------------------------------------------------------------
| class NodeConfigurationToken extends Model
| 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. * The table associated with the model.
| *
*/ * @var string
'password' => 'Senhas precisam ter ao menos 6 caracteres e combinar com a confirmação.', */
'reset' => 'Sua senha foi resetada!', protected $table = 'node_configuration_tokens';
'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.", * 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 <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Models; namespace Pterodactyl\Models;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
class Permission extends Model class Permission extends Model
{ {
/** /**
* The table associated with the model. * The table associated with the model.
* *
@ -42,11 +42,11 @@ class Permission extends Model
*/ */
protected $guarded = ['id', 'created_at', 'updated_at']; protected $guarded = ['id', 'created_at', 'updated_at'];
/** /**
* Cast values to correct type. * Cast values to correct type.
* *
* @var array * @var array
*/ */
protected $casts = [ protected $casts = [
'user_id' => 'integer', 'user_id' => 'integer',
'server_id' => 'integer', 'server_id' => 'integer',
@ -61,5 +61,4 @@ class Permission extends Model
{ {
return $query->where('server_id', $server->id); return $query->where('server_id', $server->id);
} }
} }

View file

@ -1,7 +1,7 @@
<?php <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Models; namespace Pterodactyl\Models;
use Auth; use Auth;
use Pterodactyl\Models\Subuser;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletes;
use Pterodactyl\Exceptions\DisplayException;
class Server extends Model class Server extends Model
{ {
use Notifiable, SoftDeletes;
use SoftDeletes;
/** /**
* The table associated with the model. * The table associated with the model.
@ -63,11 +61,11 @@ class Server extends Model
*/ */
protected $guarded = ['id', 'installed', 'created_at', 'updated_at', 'deleted_at']; protected $guarded = ['id', 'installed', 'created_at', 'updated_at', 'deleted_at'];
/** /**
* Cast values to correct type. * Cast values to correct type.
* *
* @var array * @var array
*/ */
protected $casts = [ protected $casts = [
'node' => 'integer', 'node' => 'integer',
'suspended' => 'integer', 'suspended' => 'integer',
@ -95,7 +93,7 @@ class Server extends Model
protected static $user; protected static $user;
/** /**
* Constructor * Constructor.
*/ */
public function __construct() public function __construct()
{ {
@ -112,7 +110,6 @@ class Server extends Model
*/ */
public static function getUserDaemonSecret(Server $server) public static function getUserDaemonSecret(Server $server)
{ {
if (self::$user->id === $server->owner || self::$user->root_admin === 1) { if (self::$user->id === $server->owner || self::$user->root_admin === 1) {
return $server->daemonSecret; return $server->daemonSecret;
} }
@ -124,7 +121,6 @@ class Server extends Model
} }
return $subuser->daemonSecret; return $subuser->daemonSecret;
} }
/** /**
@ -135,7 +131,6 @@ class Server extends Model
*/ */
public static function getUserServers($paginate = null) public static function getUserServers($paginate = null)
{ {
$query = self::select( $query = self::select(
'servers.*', 'servers.*',
'nodes.name as nodeName', 'nodes.name as nodeName',
@ -160,7 +155,6 @@ class Server extends Model
} }
return $query->get(); return $query->get();
} }
/** /**
@ -173,7 +167,6 @@ class Server extends Model
*/ */
public static function getByUUID($uuid) public static function getByUUID($uuid)
{ {
if (array_key_exists($uuid, self::$serverUUIDInstance)) { if (array_key_exists($uuid, self::$serverUUIDInstance)) {
return self::$serverUUIDInstance[$uuid]; return self::$serverUUIDInstance[$uuid];
} }
@ -189,33 +182,30 @@ class Server extends Model
$result = $query->first(); $result = $query->first();
if(!is_null($result)) { if (! is_null($result)) {
$result->daemonSecret = self::getUserDaemonSecret($result); $result->daemonSecret = self::getUserDaemonSecret($result);
} }
self::$serverUUIDInstance[$uuid] = $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 * @param string $uuid
* @return array * @return array
*/ */
public static function getGuzzleHeaders($uuid) public static function getGuzzleHeaders($uuid)
{ {
if (array_key_exists($uuid, self::$serverUUIDInstance)) { if (array_key_exists($uuid, self::$serverUUIDInstance)) {
return [ return [
'X-Access-Server' => self::$serverUUIDInstance[$uuid]->uuid, 'X-Access-Server' => self::$serverUUIDInstance[$uuid]->uuid,
'X-Access-Token' => self::$serverUUIDInstance[$uuid]->daemonSecret 'X-Access-Token' => self::$serverUUIDInstance[$uuid]->daemonSecret,
]; ];
} }
return []; return [];
} }
} }

View file

@ -1,7 +1,7 @@
<?php <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Models; namespace Pterodactyl\Models;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
class ServerVariables extends Model class ServerVariables extends Model
{ {
/** /**
* The table associated with the model. * The table associated with the model.
* *
@ -42,14 +42,13 @@ class ServerVariables extends Model
*/ */
protected $guarded = ['id', 'created_at', 'updated_at']; protected $guarded = ['id', 'created_at', 'updated_at'];
/** /**
* Cast values to correct type. * Cast values to correct type.
* *
* @var array * @var array
*/ */
protected $casts = [ protected $casts = [
'server_id' => 'integer', 'server_id' => 'integer',
'variable_id' => 'integer', 'variable_id' => 'integer',
]; ];
} }

View file

@ -1,7 +1,7 @@
<?php <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Models; namespace Pterodactyl\Models;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
class Service extends Model class Service extends Model
{ {
/** /**
* The table associated with the model. * The table associated with the model.
* *
@ -41,5 +41,4 @@ class Service extends Model
* @var array * @var array
*/ */
protected $guarded = ['id', 'created_at', 'updated_at']; protected $guarded = ['id', 'created_at', 'updated_at'];
} }

View file

@ -1,7 +1,7 @@
<?php <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Models; namespace Pterodactyl\Models;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
class ServiceOptions extends Model class ServiceOptions extends Model
{ {
/** /**
* The table associated with the model. * The table associated with the model.
* *
@ -42,13 +42,22 @@ class ServiceOptions extends Model
*/ */
protected $guarded = ['id', 'created_at', 'updated_at']; protected $guarded = ['id', 'created_at', 'updated_at'];
/** /**
* Cast values to correct type. * Cast values to correct type.
* *
* @var array * @var array
*/ */
protected $casts = [ protected $casts = [
'parent_service' => 'integer', '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 <?php
/** /**
* Pterodactyl - Panel * 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 * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * 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 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */
namespace Pterodactyl\Models; namespace Pterodactyl\Models;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
class ServiceVariables extends Model class ServiceVariables extends Model
{ {
/** /**
* The table associated with the model. * The table associated with the model.
* *
@ -42,16 +42,15 @@ class ServiceVariables extends Model
*/ */
protected $guarded = ['id', 'created_at', 'updated_at']; protected $guarded = ['id', 'created_at', 'updated_at'];
/** /**
* Cast values to correct type. * Cast values to correct type.
* *
* @var array * @var array
*/ */
protected $casts = [ protected $casts = [
'option_id' => 'integer', 'option_id' => 'integer',
'user_viewable' => 'integer', 'user_viewable' => 'integer',
'user_editable' => 'integer', 'user_editable' => 'integer',
'required' => 'integer', 'required' => 'integer',
]; ];
} }

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