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()