diff --git a/app/Extensions/NoDataSerializer.php b/app/Extensions/NoDataSerializer.php new file mode 100644 index 000000000..6db8e633c --- /dev/null +++ b/app/Extensions/NoDataSerializer.php @@ -0,0 +1,43 @@ +. + * + * 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\Extensions; + +use League\Fractal\Serializer\ArraySerializer; + +class NoDataSerializer extends ArraySerializer +{ + /** + * Serialize a collection and don't insert as a member of `data` + * + * @param string $resourceKey + * @param array $data + * + * @return array + */ + public function collection($resourceKey, array $data) + { + return $data; + } +} diff --git a/app/Http/Controllers/API/User/CoreController.php b/app/Http/Controllers/API/User/CoreController.php index be9ce30ab..e0e0cedea 100644 --- a/app/Http/Controllers/API/User/CoreController.php +++ b/app/Http/Controllers/API/User/CoreController.php @@ -24,13 +24,17 @@ namespace Pterodactyl\Http\Controllers\API\User; +use Fractal; use Illuminate\Http\Request; use Pterodactyl\Http\Controllers\Controller; +use Pterodactyl\Transformers\User\ServerTransformer; class CoreController extends Controller { public function index(Request $request) { - dd($request->user()); + $servers = $request->user()->access('service', 'node', 'allocation', 'option')->get(); + + return Fractal::collection($servers)->transformWith(new ServerTransformer)->toArray(); } } diff --git a/app/Http/Middleware/APISecretToken.php b/app/Http/Middleware/APISecretToken.php deleted file mode 100755 index 25bf891ba..000000000 --- a/app/Http/Middleware/APISecretToken.php +++ /dev/null @@ -1,133 +0,0 @@ -. - * - * 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\Middleware; - -use Auth; -use Crypt; -use Config; -use IPTools\IP; -use IPTools\Range; -use Dingo\Api\Routing\Route; -use Illuminate\Http\Request; -use Pterodactyl\Models\User; -use Pterodactyl\Models\APIKey; -use Pterodactyl\Models\APIPermission; -use Pterodactyl\Services\APILogService; -use Dingo\Api\Auth\Provider\Authorization; -use Symfony\Component\HttpKernel\Exception\HttpException; // 400 -use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; // 401 -use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; // 403 -use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException; //500 - -class APISecretToken extends Authorization -{ - protected $algo = 'sha256'; - - protected $permissionAllowed = false; - - protected $url = ''; - - public function __construct() - { - Config::set('session.driver', 'array'); - } - - public function getAuthorizationMethod() - { - return 'Authorization'; - } - - public function authenticate(Request $request, Route $route) - { - if (! $request->bearerToken() || empty($request->bearerToken())) { - APILogService::log($request, 'The authentication header was missing or malformed.'); - throw new UnauthorizedHttpException('The authentication header was missing or malformed.'); - } - - list($public, $hashed) = explode('.', $request->bearerToken()); - - $key = APIKey::where('public', $public)->first(); - if (! $key) { - APILogService::log($request, 'Invalid API Key.'); - throw new AccessDeniedHttpException('Invalid API Key.'); - } - - // Check for Resource Permissions - if (! empty($request->route()->getName())) { - if (! is_null($key->allowed_ips)) { - $inRange = false; - foreach (json_decode($key->allowed_ips) as $ip) { - if (Range::parse($ip)->contains(new IP($request->ip()))) { - $inRange = true; - break; - } - } - if (! $inRange) { - APILogService::log($request, 'This IP address <' . $request->ip() . '> does not have permission to use this API key.'); - throw new AccessDeniedHttpException('This IP address <' . $request->ip() . '> does not have permission to use this API key.'); - } - } - - $permission = APIPermission::where('key_id', $key->id)->where('permission', $request->route()->getName()); - - // Suport Wildcards - if (starts_with($request->route()->getName(), 'api.user')) { - $permission->orWhere('permission', 'api.user.*'); - } elseif (starts_with($request->route()->getName(), 'api.admin')) { - $permission->orWhere('permission', 'api.admin.*'); - } - - if (! $permission->first()) { - APILogService::log($request, 'You do not have permission to access this resource. This API Key requires the ' . $request->route()->getName() . ' permission node.'); - throw new AccessDeniedHttpException('You do not have permission to access this resource. This API Key requires the ' . $request->route()->getName() . ' permission node.'); - } - } - - try { - $decrypted = Crypt::decrypt($key->secret); - } catch (\Illuminate\Contracts\Encryption\DecryptException $ex) { - APILogService::log($request, 'There was an error while attempting to check your secret key.'); - throw new HttpException('There was an error while attempting to check your secret key.'); - } - - $this->url = urldecode($request->fullUrl()); - if ($this->_generateHMAC($request->getContent(), $decrypted) !== base64_decode($hashed)) { - APILogService::log($request, 'The hashed body was not valid. Potential modification of contents in route.'); - throw new BadRequestHttpException('The hashed body was not valid. Potential modification of contents in route.'); - } - - // Log the Route Access - APILogService::log($request, null, true); - - return Auth::loginUsingId($key->user_id); - } - - protected function _generateHMAC($body, $key) - { - $data = $this->url . $body; - - return hash_hmac($this->algo, $data, $key, true); - } -} diff --git a/app/Http/Routes/ServerRoutes.php b/app/Http/Routes/ServerRoutes.php deleted file mode 100644 index b03a530d6..000000000 --- a/app/Http/Routes/ServerRoutes.php +++ /dev/null @@ -1,192 +0,0 @@ -. - * - * 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 ServerRoutes -{ - /** - * Server routes. - * - * @param \Illuminate\Routing\Router $router - * @return void - */ - public function map(Router $router) - { - // Returns Server Status - $router->get('/server/{server}/ajax/status', [ - 'middleware' => ['auth', 'csrf'], - 'as' => 'server.ajax.status', - 'uses' => 'Server\AjaxController@getStatus', - ]); - - $router->group([ - 'prefix' => 'server/{server}', - 'middleware' => [ - 'auth', - 'server', - 'csrf', - ], - ], function ($server) use ($router) { - - // Index View for Server - $router->get('/', [ - 'as' => 'server.index', - 'uses' => 'Server\ServerController@getIndex', - ]); - - $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', [ - 'uses' => 'Server\ServerController@postSettingsSFTP', - ]); - - $router->get('/settings/startup', [ - 'as' => 'server.settings.startup', - 'uses' => 'Server\ServerController@getStartup', - ]); - - $router->post('/settings/startup', [ - 'uses' => 'Server\ServerController@postSettingsStartup', - ]); - - $router->get('/settings/allocation', [ - 'as' => 'server.settings.allocation', - 'uses' => 'Server\ServerController@getAllocation', - ]); - - // File Manager Routes - $router->get('/files', [ - 'as' => 'server.files.index', - 'uses' => 'Server\ServerController@getFiles', - ]); - - $router->get('/files/edit/{file}', [ - 'as' => 'server.files.edit', - 'uses' => 'Server\ServerController@getEditFile', - ])->where('file', '.*'); - - $router->get('/files/download/{file}', [ - 'as' => 'server.files.download', - 'uses' => 'Server\ServerController@getDownloadFile', - ])->where('file', '.*'); - - $router->get('/files/add', [ - 'as' => 'server.files.add', - 'uses' => 'Server\ServerController@getAddFile', - ]); - - $router->post('files/directory-list', [ - 'as' => 'server.files.directory-list', - 'uses' => 'Server\AjaxController@postDirectoryList', - ]); - - $router->post('files/save', [ - 'as' => 'server.files.save', - 'uses' => 'Server\AjaxController@postSaveFile', - ]); - - // Sub-User Routes - $router->get('users', [ - 'as' => 'server.subusers', - 'uses' => 'Server\SubuserController@getIndex', - ]); - - $router->get('users/new', [ - 'as' => 'server.subusers.new', - 'uses' => 'Server\SubuserController@getNew', - ]); - - $router->post('users/new', [ - 'uses' => 'Server\SubuserController@postNew', - ]); - - $router->get('users/view/{id}', [ - 'as' => 'server.subusers.view', - 'uses' => 'Server\SubuserController@getView', - ]); - - $router->post('users/view/{id}', [ - 'uses' => 'Server\SubuserController@postView', - ]); - - $router->delete('users/delete/{id}', [ - 'as' => 'server.subusers.delete', - 'uses' => 'Server\SubuserController@deleteSubuser', - ]); - - $router->get('tasks/', [ - 'as' => 'server.tasks', - 'uses' => 'Server\TaskController@getIndex', - ]); - - $router->get('tasks/view/{id}', [ - 'as' => 'server.tasks.view', - 'uses' => 'Server\TaskController@getView', - ]); - - $router->get('tasks/new', [ - 'as' => 'server.tasks.new', - 'uses' => 'Server\TaskController@getNew', - ]); - - $router->post('tasks/new', [ - 'uses' => 'Server\TaskController@postNew', - ]); - - $router->delete('tasks/delete/{id}', [ - 'as' => 'server.tasks.delete', - 'uses' => 'Server\TaskController@deleteTask', - ]); - - $router->post('tasks/toggle/{id}', [ - 'as' => 'server.tasks.toggle', - 'uses' => 'Server\TaskController@toggleTask', - ]); - - // Assorted AJAX Routes - $router->group(['prefix' => 'ajax'], function ($server) use ($router) { - // Sets the Default Connection for the Server - $router->post('set-primary', [ - 'uses' => 'Server\AjaxController@postSetPrimary', - ]); - - $router->post('settings/reset-database-password', [ - 'as' => 'server.ajax.reset-database-password', - 'uses' => 'Server\AjaxController@postResetDatabasePassword', - ]); - }); - }); - } -} diff --git a/app/Transformers/User/ServerTransformer.php b/app/Transformers/User/ServerTransformer.php new file mode 100644 index 000000000..2dba2adc2 --- /dev/null +++ b/app/Transformers/User/ServerTransformer.php @@ -0,0 +1,50 @@ +. + * + * 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\Transformers\User; + +use Pterodactyl\Models\Server; +use League\Fractal\TransformerAbstract; + +class ServerTransformer extends TransformerAbstract +{ + /** + * Return a generic transformed server array. + * + * @return array + */ + public function transform(Server $server) + { + return [ + 'short' => $server->uuidShort, + 'uuid' => $server->uuid, + 'name' => $server->name, + 'node' => $server->node->name, + 'ip' => $server->allocation->alias, + 'port' => $server->allocation->port, + 'service' => $server->service->name, + 'option' => $server->option->name, + ]; + } +} diff --git a/config/laravel-fractal.php b/config/laravel-fractal.php new file mode 100644 index 000000000..9406421d8 --- /dev/null +++ b/config/laravel-fractal.php @@ -0,0 +1,18 @@ + Pterodactyl\Extensions\NoDataSerializer::class, + +];