From 7cf7a5a961c9b0ef87a654e8dbf21d40b7883e14 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Fri, 14 Oct 2016 17:15:36 -0400 Subject: [PATCH 01/11] Split account things into own controllers. --- .../Controllers/Base/AccountController.php | 108 +++++++++++ app/Http/Controllers/Base/IndexController.php | 177 +----------------- .../Controllers/Base/SecurityController.php | 130 +++++++++++++ app/Http/Routes/BaseRoutes.php | 22 +-- resources/views/base/security.blade.php | 6 +- 5 files changed, 255 insertions(+), 188 deletions(-) create mode 100644 app/Http/Controllers/Base/AccountController.php create mode 100644 app/Http/Controllers/Base/SecurityController.php diff --git a/app/Http/Controllers/Base/AccountController.php b/app/Http/Controllers/Base/AccountController.php new file mode 100644 index 000000000..c79063706 --- /dev/null +++ b/app/Http/Controllers/Base/AccountController.php @@ -0,0 +1,108 @@ + + * Some Modifications (c) 2015 Dylan Seidt + * + * 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\Base; + +use Alert; + +use Pterodactyl\Exceptions\DisplayException; +use Pterodactyl\Http\Controllers\Controller; + +use Illuminate\Http\Request; + +class AccountController extends Controller +{ + /** + * Display base account information page. + * + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Contracts\View\View + */ + public function index(Request $request) + { + return view('base.account'); + } + + /** + * Update an account email. + * + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Http\Response + */ + public function email(Request $request) + { + + $this->validate($request, [ + 'new_email' => 'required|email', + 'password' => 'required' + ]); + + $user = $request->user(); + + if (!password_verify($request->input('password'), $user->password)) { + Alert::danger('The password provided was not valid for this account.')->flash(); + return redirect()->route('account'); + } + + $user->email = $request->input('new_email'); + $user->save(); + + 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|regex:((?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,})', + 'new_password_confirmation' => 'required' + ]); + + $user = $request->user(); + + if (!password_verify($request->input('current_password'), $user->password)) { + Alert::danger('The password provided was not valid for this account.')->flash(); + return redirect()->route('account'); + } + + try { + $user->setPassword($request->input('new_password')); + Alert::success('Your password has successfully been updated.')->flash(); + } catch (DisplayException $e) { + Alert::danger($e->getMessage())->flash(); + } + + return redirect()->route('account'); + + } +} diff --git a/app/Http/Controllers/Base/IndexController.php b/app/Http/Controllers/Base/IndexController.php index d6e1513fd..bed1cb988 100644 --- a/app/Http/Controllers/Base/IndexController.php +++ b/app/Http/Controllers/Base/IndexController.php @@ -24,15 +24,9 @@ */ namespace Pterodactyl\Http\Controllers\Base; -use Auth; -use Hash; -use Google2FA; -use Alert; - -use Pterodactyl\Models; -use Pterodactyl\Exceptions\DisplayException; - +use Pterodactyl\Models\Server; use Pterodactyl\Http\Controllers\Controller; + use Illuminate\Http\Request; class IndexController extends Controller @@ -55,7 +49,7 @@ class IndexController extends Controller public function getIndex(Request $request) { return view('base.index', [ - 'servers' => Models\Server::getUserServers(10), + 'servers' => Server::getUserServers(10), ]); } @@ -71,169 +65,4 @@ class IndexController extends Controller return str_random($length); } - /** - * Returns Security Management Page. - * - * @param \Illuminate\Http\Request $request - * @return \Illuminate\Contracts\View\View - */ - public function getAccountSecurity(Request $request) - { - return view('base.security', [ - 'sessions' => Models\Session::where('user_id', Auth::user()->id)->get() - ]); - } - - /** - * Generates TOTP Secret and returns popup data for user to verify - * that they can generate a valid response. - * - * @param \Illuminate\Http\Request $request - * @return \Illuminate\Contracts\View\View - */ - public function putAccountTotp(Request $request) - { - - $user = $request->user(); - - $user->totp_secret = Google2FA::generateSecretKey(); - $user->save(); - - return response()->json([ - 'qrImage' => Google2FA::getQRCodeGoogleUrl( - 'Pterodactyl', - $user->email, - $user->totp_secret - ), - 'secret' => $user->totp_secret - ]); - - } - - /** - * Verifies that 2FA token recieved is valid and will work on the account. - * - * @param \Illuminate\Http\Request $request - * @return \Illuminate\Http\Response - */ - public function postAccountTotp(Request $request) - { - - if (!$request->has('token')) { - return response(null, 500); - } - - $user = $request->user(); - if($user->toggleTotp($request->input('token'))) { - return response('true'); - } - - return response('false'); - - } - - /** - * Disables TOTP on an account. - * - * @param \Illuminate\Http\Request $request - * @return \Illuminate\Http\Response - */ - public function deleteAccountTotp(Request $request) - { - - if (!$request->has('token')) { - Alert::danger('Missing required `token` field in request.')->flash(); - return redirect()->route('account.totp'); - } - - $user = $request->user(); - if($user->toggleTotp($request->input('token'))) { - return redirect()->route('account.totp'); - } - - Alert::danger('The TOTP token provided was invalid.')->flash(); - return redirect()->route('account.totp'); - - } - - /** - * Display base account information page. - * - * @param \Illuminate\Http\Request $request - * @return \Illuminate\Contracts\View\View - */ - public function getAccount(Request $request) - { - return view('base.account'); - } - - /** - * Update an account email. - * - * @param \Illuminate\Http\Request $request - * @return \Illuminate\Http\Response - */ - public function postAccountEmail(Request $request) - { - - $this->validate($request, [ - 'new_email' => 'required|email', - 'password' => 'required' - ]); - - $user = $request->user(); - - if (!password_verify($request->input('password'), $user->password)) { - Alert::danger('The password provided was not valid for this account.')->flash(); - return redirect()->route('account'); - } - - $user->email = $request->input('new_email'); - $user->save(); - - 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 postAccountPassword(Request $request) - { - - $this->validate($request, [ - 'current_password' => 'required', - 'new_password' => 'required|confirmed|different:current_password|regex:((?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,})', - 'new_password_confirmation' => 'required' - ]); - - $user = $request->user(); - - if (!password_verify($request->input('current_password'), $user->password)) { - Alert::danger('The password provided was not valid for this account.')->flash(); - return redirect()->route('account'); - } - - try { - $user->setPassword($request->input('new_password')); - Alert::success('Your password has successfully been updated.')->flash(); - } catch (DisplayException $e) { - Alert::danger($e->getMessage())->flash(); - } - - return redirect()->route('account'); - - } - - public function getRevokeSession(Request $request, $id) - { - $session = Models\Session::where('id', $id)->where('user_id', Auth::user()->id)->firstOrFail(); - $session->delete(); - return redirect()->route('account.security'); - } - } diff --git a/app/Http/Controllers/Base/SecurityController.php b/app/Http/Controllers/Base/SecurityController.php new file mode 100644 index 000000000..dec2f3fd1 --- /dev/null +++ b/app/Http/Controllers/Base/SecurityController.php @@ -0,0 +1,130 @@ + + * Some Modifications (c) 2015 Dylan Seidt + * + * 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\Base; + +use Google2FA; +use Alert; + +use Pterodactyl\Models\Session; +use Pterodactyl\Http\Controllers\Controller; + +use Illuminate\Http\Request; + +class SecurityController extends Controller +{ + + /** + * Returns Security Management Page. + * + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Contracts\View\View + */ + public function index(Request $request) + { + return view('base.security', [ + 'sessions' => Session::where('user_id', $request->user()->id)->get() + ]); + } + + /** + * Generates TOTP Secret and returns popup data for user to verify + * that they can generate a valid response. + * + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Contracts\View\View + */ + public function generateTotp(Request $request) + { + + $user = $request->user(); + + $user->totp_secret = Google2FA::generateSecretKey(); + $user->save(); + + return response()->json([ + 'qrImage' => Google2FA::getQRCodeGoogleUrl( + 'Pterodactyl', + $user->email, + $user->totp_secret + ), + 'secret' => $user->totp_secret + ]); + + } + + /** + * Verifies that 2FA token recieved is valid and will work on the account. + * + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Http\Response + */ + public function setTotp(Request $request) + { + + if (!$request->has('token')) { + return response(null, 500); + } + + $user = $request->user(); + if($user->toggleTotp($request->input('token'))) { + return response('true'); + } + + return response('false'); + + } + + /** + * Disables TOTP on an account. + * + * @param \Illuminate\Http\Request $request + * @return \Illuminate\Http\Response + */ + public function disableTotp(Request $request) + { + + if (!$request->has('token')) { + Alert::danger('Missing required `token` field in request.')->flash(); + return redirect()->route('account.totp'); + } + + $user = $request->user(); + if($user->toggleTotp($request->input('token'))) { + return redirect()->route('account.security'); + } + + Alert::danger('The TOTP token provided was invalid.')->flash(); + return redirect()->route('account.security'); + + } + + public function revoke(Request $request, $id) + { + $session = Session::where('id', $id)->where('user_id', $request->user()->id)->firstOrFail(); + $session->delete(); + return redirect()->route('account.security'); + } + +} diff --git a/app/Http/Routes/BaseRoutes.php b/app/Http/Routes/BaseRoutes.php index 26e488ac2..19b5bb7a6 100644 --- a/app/Http/Routes/BaseRoutes.php +++ b/app/Http/Routes/BaseRoutes.php @@ -59,13 +59,13 @@ class BaseRoutes { ], function () use ($router) { $router->get('account', [ 'as' => 'account', - 'uses' => 'Base\IndexController@getAccount' + 'uses' => 'Base\AccountController@index' ]); $router->post('/account/password', [ - 'uses' => 'Base\IndexController@postAccountPassword' + 'uses' => 'Base\AccountController@password' ]); $router->post('/account/email', [ - 'uses' => 'Base\IndexController@postAccountEmail' + 'uses' => 'Base\AccountController@email' ]); }); @@ -79,20 +79,20 @@ class BaseRoutes { ], function () use ($router) { $router->get('/', [ 'as' => 'account.security', - 'uses' => 'Base\IndexController@getAccountSecurity' + 'uses' => 'Base\SecurityController@index' ]); $router->get('/revoke/{id}', [ 'as' => 'account.security.revoke', - 'uses' => 'Base\IndexController@getRevokeSession' + 'uses' => 'Base\SecurityController@revoke' ]); - $router->put('/', [ - 'uses' => 'Base\IndexController@putAccountTotp' + $router->put('/totp', [ + 'uses' => 'Base\SecurityController@generateTotp' ]); - $router->post('/', [ - 'uses' => 'Base\IndexController@postAccountTotp' + $router->post('/totp', [ + 'uses' => 'Base\SecurityController@setTotp' ]); - $router->delete('/', [ - 'uses' => 'Base\IndexController@deleteAccountTotp' + $router->delete('/totp', [ + 'uses' => 'Base\SecurityController@disableTotp' ]); }); diff --git a/resources/views/base/security.blade.php b/resources/views/base/security.blade.php index b0723043a..48b730555 100644 --- a/resources/views/base/security.blade.php +++ b/resources/views/base/security.blade.php @@ -72,7 +72,7 @@

{{ trans('base.account.totp_disable_help') }}


-
+
{{ trans('base.account.totp_token') }} @@ -155,7 +155,7 @@ $(document).ready(function () { $.ajax({ type: 'PUT', - url: '/account/totp', + url: '/account/security/totp', headers: { 'X-CSRF-Token': '{{ csrf_token() }}' } }).done(function (data) { var image = new Image(); @@ -180,7 +180,7 @@ $(document).ready(function () { $.ajax({ type: 'POST', - url:'/account/totp', + url:'/account/security/totp', headers: { 'X-CSRF-Token': '{{ csrf_token() }}' }, data: { token: $('#totp_token').val() From 126df091523ed33bfe213635eceab17aa13940f6 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Fri, 14 Oct 2016 17:17:35 -0400 Subject: [PATCH 02/11] Fix route handling --- app/Http/Routes/BaseRoutes.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/Http/Routes/BaseRoutes.php b/app/Http/Routes/BaseRoutes.php index 19b5bb7a6..510bd7b18 100644 --- a/app/Http/Routes/BaseRoutes.php +++ b/app/Http/Routes/BaseRoutes.php @@ -51,20 +51,20 @@ class BaseRoutes { // Account Routes $router->group([ - 'profix' => 'account', + 'prefix' => 'account', 'middleware' => [ 'auth', 'csrf' ] ], function () use ($router) { - $router->get('account', [ + $router->get('/', [ 'as' => 'account', 'uses' => 'Base\AccountController@index' ]); - $router->post('/account/password', [ + $router->post('/password', [ 'uses' => 'Base\AccountController@password' ]); - $router->post('/account/email', [ + $router->post('/email', [ 'uses' => 'Base\AccountController@email' ]); }); From 745c735b32e3cb0064324a368d47a07f557ef05e Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Fri, 14 Oct 2016 20:22:23 -0400 Subject: [PATCH 03/11] Add initial basic API changes New route is `/api/me` --- .../Controllers/API/User/InfoController.php | 58 +++++ .../Controllers/API/User/PowerController.php | 39 +++ app/Http/Controllers/Base/APIController.php | 60 +++++ app/Http/Middleware/APISecretToken.php | 20 +- app/Http/Routes/APIRoutes.php | 53 ++-- app/Http/Routes/BaseRoutes.php | 21 ++ app/Http/Routes/ServerRoutes.php | 2 + app/Models/Server.php | 13 +- app/Models/Subuser.php | 6 +- app/Repositories/UserRepository.php | 3 +- config/app.php | 2 + config/session.php | 4 +- .../2016_10_14_164802_update_api_keys.php | 36 +++ public/themes/default/css/pterodactyl.css | 4 + resources/views/base/api/index.blade.php | 66 +++++ resources/views/base/api/new.blade.php | 238 ++++++++++++++++++ resources/views/layouts/master.blade.php | 2 + 17 files changed, 587 insertions(+), 40 deletions(-) create mode 100644 app/Http/Controllers/API/User/InfoController.php create mode 100644 app/Http/Controllers/API/User/PowerController.php create mode 100644 app/Http/Controllers/Base/APIController.php create mode 100644 database/migrations/2016_10_14_164802_update_api_keys.php create mode 100644 resources/views/base/api/index.blade.php create mode 100644 resources/views/base/api/new.blade.php diff --git a/app/Http/Controllers/API/User/InfoController.php b/app/Http/Controllers/API/User/InfoController.php new file mode 100644 index 000000000..2e2e3a03b --- /dev/null +++ b/app/Http/Controllers/API/User/InfoController.php @@ -0,0 +1,58 @@ + + * + * 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\API\User; + +use Auth; +use Dingo; +use Pterodactyl\Models; +use Illuminate\Http\Request; + +use Pterodactyl\Http\Controllers\API\BaseController; + +class InfoController extends BaseController +{ + public function me(Request $request) + { + $servers = Models\Server::getUserServers(); + $response = []; + + foreach($servers as &$server) { + $response = array_merge($response, [[ + 'id' => $server->uuidShort, + 'uuid' => $server->uuid, + 'name' => $server->name, + 'node' => $server->nodeName, + 'ip' => [ + 'set' => $server->ip, + 'alias' => $server->ip_alias + ], + 'port' => $server->port, + 'service' => $server->a_serviceName, + 'option' => $server->a_serviceOptionName + ]]); + } + + return $response; + } +} diff --git a/app/Http/Controllers/API/User/PowerController.php b/app/Http/Controllers/API/User/PowerController.php new file mode 100644 index 000000000..c92637b66 --- /dev/null +++ b/app/Http/Controllers/API/User/PowerController.php @@ -0,0 +1,39 @@ + + * + * 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\API\User; + +use Pterodactyl\Models; +use Illuminate\Http\Request; + +class PowerController extends BaseController +{ + public function __constructor() + { + } + + public function pass(Request $request, $uuid) + { + //$server = Models\Server::where('id', $id)->where(); + } +} diff --git a/app/Http/Controllers/Base/APIController.php b/app/Http/Controllers/Base/APIController.php new file mode 100644 index 000000000..42109857a --- /dev/null +++ b/app/Http/Controllers/Base/APIController.php @@ -0,0 +1,60 @@ + + * Some Modifications (c) 2015 Dylan Seidt + * + * 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\Base; + +use Alert; + +use Pterodactyl\Models; + +use Pterodactyl\Exceptions\DisplayException; +use Pterodactyl\Http\Controllers\Controller; + +use Illuminate\Http\Request; + +class APIController extends Controller +{ + public function index(Request $request) + { + $keys = Models\APIKey::where('user', $request->user()->id)->get(); + foreach($keys as &$key) { + $key->permissions = Models\APIPermission::where('key_id', $key->id)->get(); + } + + return view('base.api.index', [ + 'keys' => $keys + ]); + + } + + public function new(Request $request) + { + return view('base.api.new'); + } + + public function save(Request $request) + { + + } +} diff --git a/app/Http/Middleware/APISecretToken.php b/app/Http/Middleware/APISecretToken.php index a78728b34..ef150f1f2 100755 --- a/app/Http/Middleware/APISecretToken.php +++ b/app/Http/Middleware/APISecretToken.php @@ -23,12 +23,15 @@ */ namespace Pterodactyl\Http\Middleware; +use Auth; use Crypt; +use Config; use IPTools\IP; use IPTools\Range; use Pterodactyl\Models\APIKey; use Pterodactyl\Models\APIPermission; +use Pterodactyl\Models\User; use Pterodactyl\Services\APILogService; use Illuminate\Http\Request; @@ -51,7 +54,7 @@ class APISecretToken extends Authorization public function __construct() { - // + Config::set('session.driver', 'array'); } public function getAuthorizationMethod() @@ -90,14 +93,11 @@ class APISecretToken extends Authorization } } - foreach(APIPermission::where('key_id', $key->id)->get() as &$row) { - if ($row->permission === '*' || $row->permission === $request->route()->getName()) { - $this->permissionAllowed = true; - continue; - } - } - - if (!$this->permissionAllowed) { + $permission = APIPermission::where('key_id', $key->id) + ->where('permission', $request->route()->getName()) + ->orWhere('permission', '*') + ->first(); + if (!$permission) { APILogService::log($request, 'You do not have permission to access this resource.'); throw new AccessDeniedHttpException('You do not have permission to access this resource.'); } @@ -118,7 +118,7 @@ class APISecretToken extends Authorization // Log the Route Access APILogService::log($request, null, true); - return true; + return Auth::loginUsingId($key->user); } diff --git a/app/Http/Routes/APIRoutes.php b/app/Http/Routes/APIRoutes.php index 15fcab78e..3213a641a 100755 --- a/app/Http/Routes/APIRoutes.php +++ b/app/Http/Routes/APIRoutes.php @@ -32,33 +32,40 @@ class APIRoutes public function map(Router $router) { $api = app('Dingo\Api\Routing\Router'); - $api->version('v1', ['middleware' => 'api.auth'], function ($api) { + $api->version('v1', ['prefix' => 'api/me', 'middleware' => 'api.auth'], function ($api) { + $api->get('/', [ + 'as' => 'api.user', + 'uses' => 'Pterodactyl\Http\Controllers\API\User\InfoController@me' + ]); + }); + + $api->version('v1', ['prefix' => 'api', 'middleware' => 'api.auth'], function ($api) { /** * User Routes */ $api->get('users', [ - 'as' => 'api.users.list', + 'as' => 'api.admin.users.list', 'uses' => 'Pterodactyl\Http\Controllers\API\UserController@list' ]); $api->post('users', [ - 'as' => 'api.users.create', + 'as' => 'api.admin.users.create', 'uses' => 'Pterodactyl\Http\Controllers\API\UserController@create' ]); $api->get('users/{id}', [ - 'as' => 'api.users.view', + 'as' => 'api.admin.users.view', 'uses' => 'Pterodactyl\Http\Controllers\API\UserController@view' ]); $api->patch('users/{id}', [ - 'as' => 'api.users.update', + 'as' => 'api.admin.users.update', 'uses' => 'Pterodactyl\Http\Controllers\API\UserController@update' ]); $api->delete('users/{id}', [ - 'as' => 'api.users.delete', + 'as' => 'api.admin.users.delete', 'uses' => 'Pterodactyl\Http\Controllers\API\UserController@delete' ]); @@ -66,42 +73,42 @@ class APIRoutes * Server Routes */ $api->get('servers', [ - 'as' => 'api.servers.list', + 'as' => 'api.admin.servers.list', 'uses' => 'Pterodactyl\Http\Controllers\API\ServerController@list' ]); $api->post('servers', [ - 'as' => 'api.servers.create', + 'as' => 'api.admin.servers.create', 'uses' => 'Pterodactyl\Http\Controllers\API\ServerController@create' ]); $api->get('servers/{id}', [ - 'as' => 'api.servers.view', + 'as' => 'api.admin.servers.view', 'uses' => 'Pterodactyl\Http\Controllers\API\ServerController@view' ]); $api->patch('servers/{id}/config', [ - 'as' => 'api.servers.config', + 'as' => 'api.admin.servers.config', 'uses' => 'Pterodactyl\Http\Controllers\API\ServerController@config' ]); $api->patch('servers/{id}/build', [ - 'as' => 'api.servers.build', + 'as' => 'api.admin.servers.build', 'uses' => 'Pterodactyl\Http\Controllers\API\ServerController@build' ]); $api->post('servers/{id}/suspend', [ - 'as' => 'api.servers.suspend', + 'as' => 'api.admin.servers.suspend', 'uses' => 'Pterodactyl\Http\Controllers\API\ServerController@suspend' ]); $api->post('servers/{id}/unsuspend', [ - 'as' => 'api.servers.unsuspend', + 'as' => 'api.admin.servers.unsuspend', 'uses' => 'Pterodactyl\Http\Controllers\API\ServerController@unsuspend' ]); $api->delete('servers/{id}/{force?}', [ - 'as' => 'api.servers.delete', + 'as' => 'api.admin.servers.delete', 'uses' => 'Pterodactyl\Http\Controllers\API\ServerController@delete' ]); @@ -109,32 +116,32 @@ class APIRoutes * Node Routes */ $api->get('nodes', [ - 'as' => 'api.nodes.list', + 'as' => 'api.admin.nodes.list', 'uses' => 'Pterodactyl\Http\Controllers\API\NodeController@list' ]); $api->post('nodes', [ - 'as' => 'api.nodes.create', + 'as' => 'api.admin.nodes.create', 'uses' => 'Pterodactyl\Http\Controllers\API\NodeController@create' ]); $api->get('nodes/allocations', [ - 'as' => 'api.nodes.allocations', + 'as' => 'api.admin.nodes.allocations', 'uses' => 'Pterodactyl\Http\Controllers\API\NodeController@allocations' ]); $api->get('nodes/{id}', [ - 'as' => 'api.nodes.view', + 'as' => 'api.admin.nodes.view', 'uses' => 'Pterodactyl\Http\Controllers\API\NodeController@view' ]); $api->get('nodes/{id}/config', [ - 'as' => 'api.nodes.view', + 'as' => 'api.admin.nodes.view', 'uses' => 'Pterodactyl\Http\Controllers\API\NodeController@config' ]); $api->delete('nodes/{id}', [ - 'as' => 'api.nodes.delete', + 'as' => 'api.admin.nodes.delete', 'uses' => 'Pterodactyl\Http\Controllers\API\NodeController@delete' ]); @@ -142,7 +149,7 @@ class APIRoutes * Location Routes */ $api->get('locations', [ - 'as' => 'api.locations.list', + 'as' => 'api.admin.locations.list', 'uses' => 'Pterodactyl\Http\Controllers\API\LocationController@list' ]); @@ -150,12 +157,12 @@ class APIRoutes * Service Routes */ $api->get('services', [ - 'as' => 'api.services.list', + 'as' => 'api.admin.services.list', 'uses' => 'Pterodactyl\Http\Controllers\API\ServiceController@list' ]); $api->get('services/{id}', [ - 'as' => 'api.services.view', + 'as' => 'api.admin.services.view', 'uses' => 'Pterodactyl\Http\Controllers\API\ServiceController@view' ]); diff --git a/app/Http/Routes/BaseRoutes.php b/app/Http/Routes/BaseRoutes.php index 510bd7b18..60ac32a8a 100644 --- a/app/Http/Routes/BaseRoutes.php +++ b/app/Http/Routes/BaseRoutes.php @@ -69,6 +69,27 @@ class BaseRoutes { ]); }); + // API Management Routes + $router->group([ + 'prefix' => 'account/api', + 'middleware' => [ + 'auth', + 'csrf' + ] + ], function () use ($router) { + $router->get('/', [ + 'as' => 'account.api', + 'uses' => 'Base\APIController@index' + ]); + $router->get('/new', [ + 'as' => 'account.api.new', + 'uses' => 'Base\APIController@new' + ]); + $router->post('/new', [ + 'uses' => 'Base\APIController@save' + ]); + }); + // TOTP Routes $router->group([ 'prefix' => 'account/security', diff --git a/app/Http/Routes/ServerRoutes.php b/app/Http/Routes/ServerRoutes.php index 9624a0d4e..5916287e2 100644 --- a/app/Http/Routes/ServerRoutes.php +++ b/app/Http/Routes/ServerRoutes.php @@ -28,6 +28,7 @@ use Illuminate\Routing\Router; class ServerRoutes { public function map(Router $router) { + $router->group([ 'prefix' => 'server/{server}', 'middleware' => [ @@ -36,6 +37,7 @@ class ServerRoutes { 'csrf' ] ], function ($server) use ($router) { + // Index View for Server $router->get('/', [ 'as' => 'server.index', diff --git a/app/Models/Server.php b/app/Models/Server.php index e0665ee13..af160da7b 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -24,7 +24,6 @@ namespace Pterodactyl\Models; use Auth; - use Pterodactyl\Models\Subuser; use Illuminate\Database\Eloquent\Model; @@ -91,7 +90,11 @@ class Server extends Model */ public function __construct() { - self::$user = Auth::user(); + if (!is_null(Auth::user())) { + self::$user = Auth::user(); + } else { + throw new \Exception('Auth::user and Dingo::user cannot both be null.'); + } } /** @@ -133,9 +136,13 @@ class Server extends Model 'locations.short as a_locationShort', 'allocations.ip', 'allocations.ip_alias', - 'allocations.port' + 'allocations.port', + 'services.name as a_serviceName', + 'service_options.name as a_serviceOptionName' )->join('nodes', 'servers.node', '=', 'nodes.id') ->join('locations', 'nodes.location', '=', 'locations.id') + ->join('services', 'servers.service', '=', 'services.id') + ->join('service_options', 'servers.option', '=', 'service_options.id') ->join('allocations', 'servers.allocation', '=', 'allocations.id'); if (self::$user->root_admin !== 1) { diff --git a/app/Models/Subuser.php b/app/Models/Subuser.php index 5c22adfb7..1243a3ddd 100644 --- a/app/Models/Subuser.php +++ b/app/Models/Subuser.php @@ -70,7 +70,11 @@ class Subuser extends Model */ public function __construct() { - self::$user = Auth::user(); + if (!is_null(Auth::user())) { + self::$user = Auth::user(); + } else { + throw new \Exception('Auth::user and Dingo::user cannot both be null.'); + } } /** diff --git a/app/Repositories/UserRepository.php b/app/Repositories/UserRepository.php index f90bab484..01cad4269 100644 --- a/app/Repositories/UserRepository.php +++ b/app/Repositories/UserRepository.php @@ -162,7 +162,8 @@ class UserRepository throw new DisplayException('Cannot delete a user with active servers attached to thier account.'); } - if(Auth::user()->id === $id) { + // @TODO: this should probably be checked outside of this method because we won't always have Auth::user() + if(!is_null(Auth::user()) && Auth::user()->id === $id) { throw new DisplayException('Cannot delete your own account.'); } diff --git a/config/app.php b/config/app.php index b28fb0a69..6dea77b4f 100644 --- a/config/app.php +++ b/config/app.php @@ -188,6 +188,8 @@ return [ 'Crypt' => Illuminate\Support\Facades\Crypt::class, 'DB' => Illuminate\Support\Facades\DB::class, 'Debugbar' => Barryvdh\Debugbar\Facade::class, + 'Dingo' => Dingo\Api\Facade\API::class, + 'DingoRoute'=> Dingo\Api\Facade\Route::class, 'Eloquent' => Illuminate\Database\Eloquent\Model::class, 'Event' => Illuminate\Support\Facades\Event::class, 'File' => Illuminate\Support\Facades\File::class, diff --git a/config/session.php b/config/session.php index f1b004214..59ad9182f 100644 --- a/config/session.php +++ b/config/session.php @@ -29,9 +29,9 @@ return [ | */ - 'lifetime' => 120, + 'lifetime' => 30, - 'expire_on_close' => false, + 'expire_on_close' => true, /* |-------------------------------------------------------------------------- diff --git a/database/migrations/2016_10_14_164802_update_api_keys.php b/database/migrations/2016_10_14_164802_update_api_keys.php new file mode 100644 index 000000000..80d7f9501 --- /dev/null +++ b/database/migrations/2016_10_14_164802_update_api_keys.php @@ -0,0 +1,36 @@ +unsignedInteger('user')->after('id'); + $table->text('memo')->after('allowed_ips')->nullable(); + $table->timestamp('expires_at')->after('memo')->nullable(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('api_keys', function (Blueprint $table) { + $table->dropColumn('user'); + $table->dropColumn('memo'); + $table->dropColumn('expires_at'); + }); + } +} diff --git a/public/themes/default/css/pterodactyl.css b/public/themes/default/css/pterodactyl.css index d3f5d7241..86cd27ca3 100755 --- a/public/themes/default/css/pterodactyl.css +++ b/public/themes/default/css/pterodactyl.css @@ -263,3 +263,7 @@ li.btn.btn-default.pill:active,li.btn.btn-default.pill:focus,li.btn.btn-default. .left-icon + td { border-left: 0px !important; } + +.fuelux .wizard .step-content > .alert { + margin-bottom: 0 !important; +} diff --git a/resources/views/base/api/index.blade.php b/resources/views/base/api/index.blade.php new file mode 100644 index 000000000..75891d158 --- /dev/null +++ b/resources/views/base/api/index.blade.php @@ -0,0 +1,66 @@ +{{-- Copyright (c) 2015 - 2016 Dane Everitt --}} + +{{-- 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. --}} +@extends('layouts.master') + +@section('title', 'API Access') + +@section('sidebar-server') +@endsection + +@section('content') +
+ + + + + + + + + + + + @foreach ($keys as $key) + + + + + + + + @endforeach + +
Public KeyMemoCreatedExpires
{{ $key->public }}{{ $key->memo }}{{ (new Carbon($key->created_at))->toDayDateTimeString() }} + @if(is_null($key->expires_at)) + Never + @else + {{ (new Carbon($key->expires_at))->toDayDateTimeString() }} + @endif +
+ +
+ +@endsection diff --git a/resources/views/base/api/new.blade.php b/resources/views/base/api/new.blade.php new file mode 100644 index 000000000..e1049a2bb --- /dev/null +++ b/resources/views/base/api/new.blade.php @@ -0,0 +1,238 @@ +{{-- Copyright (c) 2015 - 2016 Dane Everitt --}} + +{{-- 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. --}} +@extends('layouts.master') + +@section('title', 'API Access') + +@section('sidebar-server') +@endsection + +@section('content') +
+
+
+
    +
  • + 1Permissions + +
  • +
  • + 2Admin + +
  • +
  • + 3Security + +
  • +
  • + 4Finish + +
  • +
+
+
+ + +
+
+ {{-- --}} +
+
+
+
+
+
+
+
+
+
+

User Management


+
+
+
+
+
+
+
+
+
+
+
+
+

Server Management


+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

Node Management


+
+
+
+
+
+
+
+
+
+
+
+
+

Service Management


+
+
+
+
+

Location Management


+
+
+
+
+
+
+
+ +
+ +

Enter a line delimitated list of IPs that are allowed to access the API using this key. CIDR notation is allowed. Leave blank to allow any IP.

+
+
+
+
+ Whoa +
+ +
+
+ + {{-- --}} +
+ +@endsection diff --git a/resources/views/layouts/master.blade.php b/resources/views/layouts/master.blade.php index 919cd5191..522155139 100644 --- a/resources/views/layouts/master.blade.php +++ b/resources/views/layouts/master.blade.php @@ -184,6 +184,7 @@ @@ -237,6 +238,7 @@ {{ trans('pagination.sidebar.account_controls') }} {{ trans('pagination.sidebar.account_settings') }} {{ trans('pagination.sidebar.account_security') }} + API Access {{ trans('pagination.sidebar.servers') }}
@section('sidebar-server') From 5a03ce7e1a1cf63c45463efdf9cebe9824d0f4b6 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Thu, 20 Oct 2016 13:39:39 -0400 Subject: [PATCH 04/11] Add support for controlling server power from API. --- ...werController.php => ServerController.php} | 31 ++++++++++++++++--- app/Http/Middleware/VerifyCsrfToken.php | 1 + app/Http/Routes/APIRoutes.php | 10 ++++++ 3 files changed, 38 insertions(+), 4 deletions(-) rename app/Http/Controllers/API/User/{PowerController.php => ServerController.php} (56%) diff --git a/app/Http/Controllers/API/User/PowerController.php b/app/Http/Controllers/API/User/ServerController.php similarity index 56% rename from app/Http/Controllers/API/User/PowerController.php rename to app/Http/Controllers/API/User/ServerController.php index c92637b66..805ca0c99 100644 --- a/app/Http/Controllers/API/User/PowerController.php +++ b/app/Http/Controllers/API/User/ServerController.php @@ -26,14 +26,37 @@ namespace Pterodactyl\Http\Controllers\API\User; use Pterodactyl\Models; use Illuminate\Http\Request; -class PowerController extends BaseController +use Pterodactyl\Http\Controllers\API\BaseController; + +class ServerController extends BaseController { - public function __constructor() + + public function info(Request $request, $uuid) { + // Will return server info including latest query and stats from daemon. } - public function pass(Request $request, $uuid) + public function power(Request $request, $uuid) { - //$server = Models\Server::where('id', $id)->where(); + $server = Models\Server::getByUUID($uuid); + $node = Models\Node::getByID($server->node); + $client = Models\Node::guzzleRequest($server->node); + + $res = $client->request('PUT', '/server/power', [ + 'headers' => [ + 'X-Access-Server' => $server->uuid, + 'X-Access-Token' => $server->daemonSecret + ], + 'exceptions' => false, + 'json' => [ + 'action' => $request->input('action') + ] + ]); + + if ($res->getStatusCode() !== 204) { + return $this->response->error(json_decode($res->getBody())->error, $res->getStatusCode()); + } + + return $this->response->noContent(); } } diff --git a/app/Http/Middleware/VerifyCsrfToken.php b/app/Http/Middleware/VerifyCsrfToken.php index 97aa64965..be7b74e42 100644 --- a/app/Http/Middleware/VerifyCsrfToken.php +++ b/app/Http/Middleware/VerifyCsrfToken.php @@ -13,5 +13,6 @@ class VerifyCsrfToken extends BaseVerifier */ protected $except = [ 'remote/*', + 'api/*' ]; } diff --git a/app/Http/Routes/APIRoutes.php b/app/Http/Routes/APIRoutes.php index 3213a641a..5ba792b35 100755 --- a/app/Http/Routes/APIRoutes.php +++ b/app/Http/Routes/APIRoutes.php @@ -37,6 +37,16 @@ class APIRoutes 'as' => 'api.user', 'uses' => 'Pterodactyl\Http\Controllers\API\User\InfoController@me' ]); + + $api->get('/server/{uuid}', [ + 'as' => 'api.user.server', + 'uses' => 'Pterodactyl\Http\Controllers\API\User\ServerController@info' + ]); + + $api->put('/server/{uuid}', [ + 'as' => 'api.user.server.power', + 'uses' => 'Pterodactyl\Http\Controllers\API\User\ServerController@power' + ]); }); $api->version('v1', ['prefix' => 'api', 'middleware' => 'api.auth'], function ($api) { From 125856d92f02f7cc2182d058fe3173b488111d31 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Thu, 20 Oct 2016 16:42:54 -0400 Subject: [PATCH 05/11] Support for server info and minor changes to API setup --- CHANGELOG.md | 2 + .../Controllers/API/User/ServerController.php | 54 ++++++++++++++++++- app/Models/Server.php | 11 +++- 3 files changed, 64 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b3be6bf7b..d670a3ab1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,11 +9,13 @@ This project follows [Semantic Versioning](http://semver.org) guidelines. * Return node configuration from remote API by using `/api/nodes/{id}/config` endpoint. Only accepts SSL connections. * Support for filtering servers within Admin CP to narrow down results by name, email, allocation, or defined fields. * Setup scripts (user, mail, env) now support argument flags for use in containers and other non-terminal environments. +* New API endpoints for individual users to control their servers with at `/api/me/*`. ### Changed * Creating a user, server, or node now returns `HTTP/1.1 200` and a JSON element with the user/server/node's ID. * Environment setting script is much more user friendly and does not require an excessive amount of clicking and typing. * File upload method switched from BinaryJS to Socket.io implementation to fix bugs as well as be a little speedier and allow upload throttling. +* `Server::getbyUUID()` now accepts either the `uuidShort` or full-length `uuid` for server identification. ## v0.5.0-pre.2 (Bodacious Boreopterus) diff --git a/app/Http/Controllers/API/User/ServerController.php b/app/Http/Controllers/API/User/ServerController.php index 805ca0c99..b29b4c9f8 100644 --- a/app/Http/Controllers/API/User/ServerController.php +++ b/app/Http/Controllers/API/User/ServerController.php @@ -23,6 +23,7 @@ */ namespace Pterodactyl\Http\Controllers\API\User; +use Log; use Pterodactyl\Models; use Illuminate\Http\Request; @@ -33,7 +34,58 @@ class ServerController extends BaseController public function info(Request $request, $uuid) { - // Will return server info including latest query and stats from daemon. + $server = Models\Server::getByUUID($uuid); + $node = Models\Node::findOrFail($server->node); + $client = Models\Node::guzzleRequest($node->id); + + try { + $response = $client->request('GET', '/server', [ + 'headers' => [ + 'X-Access-Token' => $server->daemonSecret, + 'X-Access-Server' => $server->uuid + ] + ]); + + $json = json_decode($response->getBody()); + $daemon = [ + 'status' => $json->status, + 'stats' => $json->proc, + 'query' => $json->query + ]; + } catch (\Exception $ex) { + $daemon = [ + 'error' => 'An error was encountered while trying to connect to the daemon to collece information. It might be offline.' + ]; + Log::error($ex); + } + + $allocations = Models\Allocation::select('id', 'ip', 'port', 'ip_alias as alias')->where('assigned_to', $server->id)->get(); + foreach($allocations as &$allocation) { + $allocation->default = ($allocation->id === $server->allocation); + unset($allocation->id); + } + return [ + 'uuidShort' => $server->uuidShort, + 'uuid' => $server->uuid, + 'name' => $server->name, + 'node' => $node->name, + 'limits' => [ + 'memory' => $server->memory, + 'swap' => $server->swap, + 'disk' => $server->disk, + 'io' => $server->io, + 'cpu' => $server->cpu, + 'oom_disabled' => (bool) $server->oom_disabled + ], + 'allocations' => $allocations, + 'sftp' => [ + 'username' => $server->username + ], + 'daemon' => [ + 'token' => ($request->secure()) ? $server->daemonSecret : false, + 'response' => $daemon + ] + ]; } public function power(Request $request, $uuid) diff --git a/app/Models/Server.php b/app/Models/Server.php index af160da7b..af62a528b 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -27,6 +27,8 @@ use Auth; use Pterodactyl\Models\Subuser; use Illuminate\Database\Eloquent\Model; +use Pterodactyl\Exception\DisplayException; + class Server extends Model { @@ -104,7 +106,7 @@ class Server extends Model * @param Illuminate\Database\Eloquent\Model\Server $server * @return string */ - protected static function getUserDaemonSecret(Server $server) + public static function getUserDaemonSecret(Server $server) { if (self::$user->id === $server->owner || self::$user->root_admin === 1) { @@ -174,7 +176,8 @@ class Server extends Model $query = self::select('servers.*', 'services.file as a_serviceFile') ->join('services', 'services.id', '=', 'servers.service') - ->where('uuidShort', $uuid); + ->where('uuidShort', $uuid) + ->orWhere('uuid', $uuid); if (self::$user->root_admin !== 1) { $query->whereIn('servers.id', Subuser::accessServers()); @@ -182,6 +185,10 @@ class Server extends Model $result = $query->first(); + if (!$result) { + throw new DisplayException('No server was found belonging to this user.'); + } + if(!is_null($result)) { $result->daemonSecret = self::getUserDaemonSecret($result); } From 9fd8a087b8385868a5c56e7faeedec39df8d709d Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Thu, 20 Oct 2016 16:48:37 -0400 Subject: [PATCH 06/11] Revert some changes that cause issues with other URLs --- app/Models/Server.php | 6 +----- app/Models/Subuser.php | 6 +----- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/app/Models/Server.php b/app/Models/Server.php index af62a528b..bf18ddd7a 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -92,11 +92,7 @@ class Server extends Model */ public function __construct() { - if (!is_null(Auth::user())) { - self::$user = Auth::user(); - } else { - throw new \Exception('Auth::user and Dingo::user cannot both be null.'); - } + self::$user = Auth::user(); } /** diff --git a/app/Models/Subuser.php b/app/Models/Subuser.php index 1243a3ddd..5c22adfb7 100644 --- a/app/Models/Subuser.php +++ b/app/Models/Subuser.php @@ -70,11 +70,7 @@ class Subuser extends Model */ public function __construct() { - if (!is_null(Auth::user())) { - self::$user = Auth::user(); - } else { - throw new \Exception('Auth::user and Dingo::user cannot both be null.'); - } + self::$user = Auth::user(); } /** From dfeed013ba940b945d655f70dbefea65139b8b06 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Thu, 20 Oct 2016 17:04:58 -0400 Subject: [PATCH 07/11] Server API obey's the subuser permissions as well --- app/Http/Controllers/API/User/ServerController.php | 5 ++++- app/Models/Server.php | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/API/User/ServerController.php b/app/Http/Controllers/API/User/ServerController.php index b29b4c9f8..613f90582 100644 --- a/app/Http/Controllers/API/User/ServerController.php +++ b/app/Http/Controllers/API/User/ServerController.php @@ -23,6 +23,7 @@ */ namespace Pterodactyl\Http\Controllers\API\User; +use Auth; use Log; use Pterodactyl\Models; use Illuminate\Http\Request; @@ -79,7 +80,7 @@ class ServerController extends BaseController ], 'allocations' => $allocations, 'sftp' => [ - 'username' => $server->username + 'username' => (Auth::user()->can('view-sftp', $server)) ? $server->username : null ], 'daemon' => [ 'token' => ($request->secure()) ? $server->daemonSecret : false, @@ -94,6 +95,8 @@ class ServerController extends BaseController $node = Models\Node::getByID($server->node); $client = Models\Node::guzzleRequest($server->node); + Auth::user()->can('power-' . $request->input('action'), $server); + $res = $client->request('PUT', '/server/power', [ 'headers' => [ 'X-Access-Server' => $server->uuid, diff --git a/app/Models/Server.php b/app/Models/Server.php index bf18ddd7a..d9c2f958a 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -27,7 +27,7 @@ use Auth; use Pterodactyl\Models\Subuser; use Illuminate\Database\Eloquent\Model; -use Pterodactyl\Exception\DisplayException; +use Pterodactyl\Exceptions\DisplayException; class Server extends Model { From 53ec2c55ec9b667d4f5e852e46a24c4b495dba74 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Thu, 20 Oct 2016 18:20:58 -0400 Subject: [PATCH 08/11] Add front-end support for adding and deleting API keys. --- app/Http/Controllers/Base/APIController.php | 30 +- app/Http/Routes/APIRoutes.php | 2 +- app/Http/Routes/BaseRoutes.php | 4 + app/Repositories/APIRepository.php | 117 +++++-- public/themes/default/css/pterodactyl.css | 4 + resources/views/base/api/index.blade.php | 43 +++ resources/views/base/api/new.blade.php | 368 +++++++++++--------- resources/views/layouts/master.blade.php | 36 +- 8 files changed, 379 insertions(+), 225 deletions(-) diff --git a/app/Http/Controllers/Base/APIController.php b/app/Http/Controllers/Base/APIController.php index 42109857a..da9a20d78 100644 --- a/app/Http/Controllers/Base/APIController.php +++ b/app/Http/Controllers/Base/APIController.php @@ -25,9 +25,12 @@ namespace Pterodactyl\Http\Controllers\Base; use Alert; +use Log; use Pterodactyl\Models; +use Pterodactyl\Repositories\APIRepository; +use Pterodactyl\Exceptions\DisplayValidationException; use Pterodactyl\Exceptions\DisplayException; use Pterodactyl\Http\Controllers\Controller; @@ -45,7 +48,6 @@ class APIController extends Controller return view('base.api.index', [ 'keys' => $keys ]); - } public function new(Request $request) @@ -55,6 +57,32 @@ class APIController extends Controller public function save(Request $request) { + try { + $repo = new APIRepository($request->user()); + $secret = $repo->new($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.

' . $secret . '')->flash(); + return redirect()->route('account.api'); + } catch (DisplayValidationException $ex) { + return redirect()->route('account.api.new')->withErrors(json_decode($ex->getMessage()))->withInput(); + } catch (DisplayException $ex) { + Alert::danger($ex->getMessage())->flash(); + } catch (\Exception $ex) { + Log::error($ex); + Alert::danger('An unhandled exception occured while attempting to add this API key.')->flash(); + } + return redirect()->route('account.api.new')->withInput(); + } + public function revoke(Request $request, $key) + { + try { + $repo = new APIRepository($request->user()); + $repo->revoke($key); + return response('', 204); + } catch (\Exception $ex) { + return response()->json([ + 'error' => 'An error occured while attempting to remove this key.' + ], 503); + } } } diff --git a/app/Http/Routes/APIRoutes.php b/app/Http/Routes/APIRoutes.php index 5ba792b35..33d3d7177 100755 --- a/app/Http/Routes/APIRoutes.php +++ b/app/Http/Routes/APIRoutes.php @@ -34,7 +34,7 @@ class APIRoutes $api = app('Dingo\Api\Routing\Router'); $api->version('v1', ['prefix' => 'api/me', 'middleware' => 'api.auth'], function ($api) { $api->get('/', [ - 'as' => 'api.user', + 'as' => 'api.user.me', 'uses' => 'Pterodactyl\Http\Controllers\API\User\InfoController@me' ]); diff --git a/app/Http/Routes/BaseRoutes.php b/app/Http/Routes/BaseRoutes.php index 60ac32a8a..6841ea1b6 100644 --- a/app/Http/Routes/BaseRoutes.php +++ b/app/Http/Routes/BaseRoutes.php @@ -88,6 +88,10 @@ class BaseRoutes { $router->post('/new', [ 'uses' => 'Base\APIController@save' ]); + + $router->delete('/revoke/{key}', [ + 'uses' => 'Base\APIController@revoke' + ]); }); // TOTP Routes diff --git a/app/Repositories/APIRepository.php b/app/Repositories/APIRepository.php index b92a7cab0..b18c8ec90 100644 --- a/app/Repositories/APIRepository.php +++ b/app/Repositories/APIRepository.php @@ -23,6 +23,7 @@ */ namespace Pterodactyl\Repositories; +use Auth; use DB; use Crypt; use Validator; @@ -40,38 +41,51 @@ class APIRepository * @var array */ protected $permissions = [ - '*', + 'admin' => [ + '*', - // User Management Routes - 'api.users.list', - 'api.users.create', - 'api.users.view', - 'api.users.update', - 'api.users.delete', + // User Management Routes + 'users.list', + 'users.create', + 'users.view', + 'users.update', + 'users.delete', - // Server Manaement Routes - 'api.servers.list', - 'api.servers.create', - 'api.servers.view', - 'api.servers.config', - 'api.servers.build', - 'api.servers.suspend', - 'api.servers.unsuspend', - 'api.servers.delete', + // Server Manaement Routes + 'servers.list', + 'servers.create', + 'servers.view', + 'servers.config', + 'servers.build', + 'servers.suspend', + 'servers.unsuspend', + 'servers.delete', - // Node Management Routes - 'api.nodes.list', - 'api.nodes.create', - 'api.nodes.list', - 'api.nodes.allocations', - 'api.nodes.delete', + // Node Management Routes + 'nodes.list', + 'nodes.create', + 'nodes.list', + 'nodes.allocations', + 'nodes.delete', - // Service Routes - 'api.services.list', - 'api.services.view', + // Service Routes + 'services.list', + 'services.view', - // Location Routes - 'api.locations.list', + // Location Routes + 'locations.list', + + ], + 'user' => [ + '*', + + // Informational + 'me', + + // Server Control + 'server', + 'server.power', + ], ]; /** @@ -80,12 +94,17 @@ class APIRepository */ protected $allowed = []; + protected $user; + /** * Constructor */ - public function __construct() + public function __construct(Models\User $user = null) { - // + $this->user = is_null($user) ? Auth::user() : $user; + if (is_null($this->user)) { + throw new \Exception('Cannot access API Repository without passing a user to __construct().'); + } } /** @@ -101,7 +120,9 @@ class APIRepository public function new(array $data) { $validator = Validator::make($data, [ - 'permissions' => 'required|array' + 'memo' => 'string|max:500', + 'permissions' => 'sometimes|required|array', + 'adminPermissions' => 'sometimes|required|array' ]); $validator->after(function($validator) use ($data) { @@ -125,31 +146,53 @@ class APIRepository } DB::beginTransaction(); - try { - $secretKey = str_random(16) . '.' . str_random(15); + $secretKey = str_random(16) . '.' . str_random(7) . '.' . str_random(7); $key = new Models\APIKey; $key->fill([ + 'user' => $this->user->id, 'public' => str_random(16), 'secret' => Crypt::encrypt($secretKey), - 'allowed_ips' => empty($this->allowed) ? null : json_encode($this->allowed) + 'allowed_ips' => empty($this->allowed) ? null : json_encode($this->allowed), + 'memo' => $data['memo'], + 'expires_at' => null ]); $key->save(); - foreach($data['permissions'] as $permission) { - if (in_array($permission, $this->permissions)) { + foreach($data['permissions'] as $permNode) { + if (!strpos($permNode, ':')) continue; + + list($toss, $permission) = explode(':', $permNode); + if (in_array('api.user.' . $permission, $this->permissions['user'])) { $model = new Models\APIPermission; $model->fill([ 'key_id' => $key->id, - 'permission' => $permission + 'permission' => 'api.user.' . $permission ]); $model->save(); } } + if ($this->user->root_admin === 1) { + foreach($data['permissions'] as $permNode) { + if (!strpos($permNode, ':')) continue; + + list($toss, $permission) = explode(':', $permNode); + if (in_array('api.admin.' . $permission, $this->permissions['admin'])) { + $model = new Models\APIPermission; + $model->fill([ + 'key_id' => $key->id, + 'permission' => 'api.admin.' . $permission + ]); + $model->save(); + } + } + } + DB::commit(); return $secretKey; } catch (\Exception $ex) { + DB::rollBack(); throw $ex; } @@ -169,7 +212,7 @@ class APIRepository DB::beginTransaction(); try { - $model = Models\APIKey::where('public', $key)->firstOrFail(); + $model = Models\APIKey::where('public', $key)->where('user', $this->user->id)->firstOrFail(); $permissions = Models\APIPermission::where('key_id', $model->id)->delete(); $model->delete(); diff --git a/public/themes/default/css/pterodactyl.css b/public/themes/default/css/pterodactyl.css index 86cd27ca3..c25130929 100755 --- a/public/themes/default/css/pterodactyl.css +++ b/public/themes/default/css/pterodactyl.css @@ -267,3 +267,7 @@ li.btn.btn-default.pill:active,li.btn.btn-default.pill:focus,li.btn.btn-default. .fuelux .wizard .step-content > .alert { margin-bottom: 0 !important; } + +.fuelux .wizard .steps-container { + background-color: #eee; +} diff --git a/resources/views/base/api/index.blade.php b/resources/views/base/api/index.blade.php index 75891d158..0fcc69a79 100644 --- a/resources/views/base/api/index.blade.php +++ b/resources/views/base/api/index.blade.php @@ -24,6 +24,12 @@ @section('sidebar-server') @endsection +@section('scripts') + @parent + {!! Theme::css('css/vendor/sweetalert/sweetalert.min.css') !!} + {!! Theme::js('js/vendor/sweetalert/sweetalert.min.js') !!} +@endsection + @section('content')
@@ -61,6 +67,43 @@ @endsection diff --git a/resources/views/base/api/new.blade.php b/resources/views/base/api/new.blade.php index e1049a2bb..e8ff08a4f 100644 --- a/resources/views/base/api/new.blade.php +++ b/resources/views/base/api/new.blade.php @@ -41,10 +41,6 @@ 3Security -
  • - 4Finish - -
  • @@ -54,185 +50,225 @@
    +
    - {{-- --}} -
    -
    -
    -
    -
    -
    +
    +
    Any servers that you are a subuser for will be accessible through this API with the same permissions that you currently have.
    +
    +
    +

    Base Information


    +
    +
    +
    +
    -
    -
    -

    User Management


    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    +
    +

    Server Management


    +
    +
    -
    -

    Server Management


    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -

    Node Management


    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -

    Service Management


    -
    -
    -
    -
    -

    Location Management


    -
    -
    +
    +
    -
    -
    - -
    - -

    Enter a line delimitated list of IPs that are allowed to access the API using this key. CIDR notation is allowed. Leave blank to allow any IP.

    +
    +
    +
    +
    +
    +
    -
    - Whoa +
    +
    +

    User Management


    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    Server Management


    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    - +
    +
    +

    Node Management


    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    Service Management


    +
    +
    +
    +
    +

    Location Management


    +
    +
    +
    +
    +
    +
    +
    + +
    + +

    Enter a breif description of what this API key will be used for.

    +
    +
    +
    + +
    + +

    Enter a line delimitated list of IPs that are allowed to access the API using this key. CIDR notation is allowed. Leave blank to allow any IP.

    +
    +
    +
    + {!! csrf_field() !!} +
    - - {{-- --}}
    @endsection diff --git a/resources/views/layouts/master.blade.php b/resources/views/layouts/master.blade.php index 522155139..903ec0a4e 100644 --- a/resources/views/layouts/master.blade.php +++ b/resources/views/layouts/master.blade.php @@ -260,29 +260,25 @@
    - @section('resp-errors') - @if (count($errors) > 0) -
    + @if (count($errors) > 0) +
    + + {{ trans('strings.whoops') }}! {{ trans('auth.errorencountered') }}

    +
      + @foreach ($errors->all() as $error) +
    • {{ $error }}
    • + @endforeach +
    +
    + @endif + @foreach (Alert::getMessages() as $type => $messages) + @foreach ($messages as $message) + - @endif - @show - @section('resp-alerts') - @foreach (Alert::getMessages() as $type => $messages) - @foreach ($messages as $message) - - @endforeach @endforeach - @show + @endforeach
    From 0f4648b13ac74c211dea76a988e7fb2f91d7b592 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Thu, 20 Oct 2016 18:29:34 -0400 Subject: [PATCH 09/11] Fixes adding api keys a little more --- app/Repositories/APIRepository.php | 41 ++++++++++++++++++------------ 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/app/Repositories/APIRepository.php b/app/Repositories/APIRepository.php index b18c8ec90..c093c86ed 100644 --- a/app/Repositories/APIRepository.php +++ b/app/Repositories/APIRepository.php @@ -159,26 +159,31 @@ class APIRepository ]); $key->save(); - foreach($data['permissions'] as $permNode) { - if (!strpos($permNode, ':')) continue; - - list($toss, $permission) = explode(':', $permNode); - if (in_array('api.user.' . $permission, $this->permissions['user'])) { - $model = new Models\APIPermission; - $model->fill([ - 'key_id' => $key->id, - 'permission' => 'api.user.' . $permission - ]); - $model->save(); - } - } - - if ($this->user->root_admin === 1) { + $totalPermissions = 0; + if (isset($data['permissions'])) { foreach($data['permissions'] as $permNode) { if (!strpos($permNode, ':')) continue; list($toss, $permission) = explode(':', $permNode); - if (in_array('api.admin.' . $permission, $this->permissions['admin'])) { + if (in_array($permission, $this->permissions['user'])) { + $totalPermissions++; + $model = new Models\APIPermission; + $model->fill([ + 'key_id' => $key->id, + 'permission' => 'api.user.' . $permission + ]); + $model->save(); + } + } + } + + if ($this->user->root_admin === 1 && isset($data['adminPermissions'])) { + foreach($data['adminPermissions'] as $permNode) { + if (!strpos($permNode, ':')) continue; + + list($toss, $permission) = explode(':', $permNode); + if (in_array($permission, $this->permissions['admin'])) { + $totalPermissions++; $model = new Models\APIPermission; $model->fill([ 'key_id' => $key->id, @@ -189,6 +194,10 @@ class APIRepository } } + if ($totalPermissions < 1) { + throw new DisplayException('No valid permissions were passed.'); + } + DB::commit(); return $secretKey; } catch (\Exception $ex) { From b1a9a597070bd4d594ed7ff13df6922933d6c30e Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Thu, 20 Oct 2016 18:35:55 -0400 Subject: [PATCH 10/11] Update middleware to handle wildcards correctly. --- app/Http/Middleware/APISecretToken.php | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/app/Http/Middleware/APISecretToken.php b/app/Http/Middleware/APISecretToken.php index ef150f1f2..fab4d177d 100755 --- a/app/Http/Middleware/APISecretToken.php +++ b/app/Http/Middleware/APISecretToken.php @@ -93,13 +93,18 @@ class APISecretToken extends Authorization } } - $permission = APIPermission::where('key_id', $key->id) - ->where('permission', $request->route()->getName()) - ->orWhere('permission', '*') - ->first(); - if (!$permission) { - APILogService::log($request, 'You do not have permission to access this resource.'); - throw new AccessDeniedHttpException('You do not have permission to access this resource.'); + $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.*'); + } else if(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.'); } } From f24347d1bd06251cd3c2303021c645e974518d2d Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Thu, 20 Oct 2016 18:40:16 -0400 Subject: [PATCH 11/11] Remove old admin routes, fix display to non-admins Complete! --- app/Http/Controllers/Admin/APIController.php | 100 ------ app/Http/Routes/AdminRoutes.php | 26 -- resources/views/admin/api/index.blade.php | 113 ------- resources/views/admin/api/new.blade.php | 213 ------------- resources/views/base/api/new.blade.php | 318 ++++++++++--------- resources/views/layouts/admin.blade.php | 2 - 6 files changed, 161 insertions(+), 611 deletions(-) delete mode 100644 app/Http/Controllers/Admin/APIController.php delete mode 100644 resources/views/admin/api/index.blade.php delete mode 100644 resources/views/admin/api/new.blade.php diff --git a/app/Http/Controllers/Admin/APIController.php b/app/Http/Controllers/Admin/APIController.php deleted file mode 100644 index 0d1684484..000000000 --- a/app/Http/Controllers/Admin/APIController.php +++ /dev/null @@ -1,100 +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\Controllers\Admin; - -use Alert; -use Log; - -use Pterodactyl\Models; -use Pterodactyl\Repositories\APIRepository; -use Pterodactyl\Http\Controllers\Controller; - -use Pterodactyl\Exceptions\DisplayValidationException; -use Pterodactyl\Exceptions\DisplayException; - -use Illuminate\Http\Request; - -class APIController extends Controller -{ - - public function __construct() - { - // - } - - public function getIndex(Request $request) - { - $keys = Models\APIKey::all(); - foreach($keys as &$key) { - $key->permissions = Models\APIPermission::where('key_id', $key->id)->get(); - } - - return view('admin.api.index', [ - 'keys' => $keys - ]); - } - - public function getNew(Request $request) - { - return view('admin.api.new'); - } - - public function postNew(Request $request) - { - try { - $api = new APIRepository; - $secret = $api->new($request->except(['_token'])); - // Alert::info('An API Keypair has successfully been generated. The API secret for this public key is shown below and will not be shown again.

    Secret: ' . $secret . '')->flash(); - Alert::info("")->flash(); - return redirect()->route('admin.api'); - } catch (DisplayValidationException $ex) { - return redirect()->route('admin.api.new')->withErrors(json_decode($ex->getMessage()))->withInput(); - } catch (DisplayException $ex) { - Alert::danger($ex->getMessage())->flash(); - } catch (\Exception $ex) { - Log::error($ex); - Alert::danger('An unhandled exception occured while attempting to add this API key.')->flash(); - } - return redirect()->route('admin.api.new')->withInput(); - } - - public function deleteRevokeKey(Request $request, $key) - { - try { - $api = new APIRepository; - $api->revoke($key); - return response('', 204); - } catch (\Exception $ex) { - return response()->json([ - 'error' => 'An error occured while attempting to remove this key.' - ], 503); - } - } - -} diff --git a/app/Http/Routes/AdminRoutes.php b/app/Http/Routes/AdminRoutes.php index a1d1956e0..3f6e73bcb 100644 --- a/app/Http/Routes/AdminRoutes.php +++ b/app/Http/Routes/AdminRoutes.php @@ -303,32 +303,6 @@ class AdminRoutes { ]); }); - // API Routes - $router->group([ - 'prefix' => 'admin/api', - 'middleware' => [ - 'auth', - 'admin', - 'csrf' - ] - ], function () use ($router) { - $router->get('/', [ - 'as' => 'admin.api', - 'uses' => 'Admin\APIController@getIndex' - ]); - $router->get('/new', [ - 'as' => 'admin.api.new', - 'uses' => 'Admin\APIController@getNew' - ]); - $router->post('/new', [ - 'uses' => 'Admin\APIController@postNew' - ]); - $router->delete('/revoke/{key?}', [ - 'as' => 'admin.api.revoke', - 'uses' => 'Admin\APIController@deleteRevokeKey' - ]); - }); - // Database Routes $router->group([ 'prefix' => 'admin/databases', diff --git a/resources/views/admin/api/index.blade.php b/resources/views/admin/api/index.blade.php deleted file mode 100644 index 205b6e88f..000000000 --- a/resources/views/admin/api/index.blade.php +++ /dev/null @@ -1,113 +0,0 @@ -{{-- Copyright (c) 2015 - 2016 Dane Everitt --}} - -{{-- 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. --}} -@extends('layouts.admin') - -@section('title') - API Management -@endsection - -@section('content') -
    - -

    API Key Information


    -
    - - - - - - - - - - - @foreach ($keys as $key) - - - - - - - - @endforeach - -
    API Public KeyAllowed IPsPermissionsCreated
    {{ $key->public }} - @if (is_null($key->allowed_ips)) - * - @else - @foreach(json_decode($key->allowed_ips) as $ip) - {{ $ip }}
    - @endforeach - @endif -
    - @foreach(json_decode($key->permissions) as &$perm) - {{ $perm->permission }}
    - @endforeach -
    {{ (new Carbon($key->created_at))->toDayDateTimeString() }}
    - -
    - -@endsection diff --git a/resources/views/admin/api/new.blade.php b/resources/views/admin/api/new.blade.php deleted file mode 100644 index 11f6b22b9..000000000 --- a/resources/views/admin/api/new.blade.php +++ /dev/null @@ -1,213 +0,0 @@ -{{-- Copyright (c) 2015 - 2016 Dane Everitt --}} - -{{-- 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. --}} -@extends('layouts.admin') - -@section('title') - API Management -@endsection - -@section('content') -
    - -

    Add New API Key


    -
    -
    -
    -
    -
    -
    -
    -
    -
    -

    User Management


    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -

    Server Management


    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -

    Node Management


    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -

    Service Management


    -
    -
    -
    -
    -

    Location Management


    -
    -
    -
    -
    -
    -
    -
    - -
    - -

    Enter a line delimitated list of IPs that are allowed to access the API using this key. CIDR notation is allowed. Leave blank to allow any IP.

    -
    -
    -
    -
    -
    - {!! csrf_field() !!} - -
    -
    -
    -
    -
    - -@endsection diff --git a/resources/views/base/api/new.blade.php b/resources/views/base/api/new.blade.php index e8ff08a4f..0fb75caac 100644 --- a/resources/views/base/api/new.blade.php +++ b/resources/views/base/api/new.blade.php @@ -33,12 +33,14 @@ 1Permissions -
  • - 2Admin - -
  • + @if(Auth::user()->root_admin === 1) +
  • + 2Admin + +
  • + @endif
  • - 3Security + @if(Auth::user()->root_admin === 1)3 @else 2 @endifSecurity
  • @@ -87,161 +89,163 @@
    -
    -
    -
    -
    -
    + @endif
    diff --git a/resources/views/layouts/admin.blade.php b/resources/views/layouts/admin.blade.php index 72fc70ff2..2ff4b0713 100644 --- a/resources/views/layouts/admin.blade.php +++ b/resources/views/layouts/admin.blade.php @@ -60,7 +60,6 @@ @@ -128,7 +127,6 @@ Management Admin Index General Settings - API Management Database Management