Add SFTP management to server front-end
This commit is contained in:
		
							parent
							
								
									b6e83b8e32
								
							
						
					
					
						commit
						52229d5d2e
					
				| @ -24,16 +24,21 @@ | |||||||
| namespace Pterodactyl\Http\Controllers\Server; | namespace Pterodactyl\Http\Controllers\Server; | ||||||
| 
 | 
 | ||||||
| use Auth; | use Auth; | ||||||
|  | use Debugbar; | ||||||
|  | use Uuid; | ||||||
|  | use Alert; | ||||||
|  | use Log; | ||||||
|  | 
 | ||||||
| use Pterodactyl\Models\Server; | use Pterodactyl\Models\Server; | ||||||
| use Pterodactyl\Models\Node; | use Pterodactyl\Models\Node; | ||||||
| use Pterodactyl\Models\Download; | use Pterodactyl\Models\Download; | ||||||
| use Pterodactyl\Models\Allocation; | use Pterodactyl\Models\Allocation; | ||||||
| use Debugbar; |  | ||||||
| use Uuid; |  | ||||||
| use Alert; |  | ||||||
| 
 | 
 | ||||||
| use Pterodactyl\Exceptions\DisplayException; | use Pterodactyl\Exceptions\DisplayException; | ||||||
| use Pterodactyl\Repositories; | use Pterodactyl\Exceptions\DisplayValidationException; | ||||||
|  | use Pterodactyl\Repositories\Daemon\FileRepository; | ||||||
|  | use Pterodactyl\Repositories\ServerRepository; | ||||||
|  | 
 | ||||||
| use Pterodactyl\Http\Controllers\Controller; | use Pterodactyl\Http\Controllers\Controller; | ||||||
| use Illuminate\Http\Request; | use Illuminate\Http\Request; | ||||||
| 
 | 
 | ||||||
| @ -127,7 +132,7 @@ class ServerController extends Controller | |||||||
|         $this->authorize('edit-files', $server); |         $this->authorize('edit-files', $server); | ||||||
| 
 | 
 | ||||||
|         $fileInfo = (object) pathinfo($file); |         $fileInfo = (object) pathinfo($file); | ||||||
|         $controller = new Repositories\Daemon\FileRepository($uuid); |         $controller = new FileRepository($uuid); | ||||||
| 
 | 
 | ||||||
|         try { |         try { | ||||||
|             $fileContent = $controller->returnFileContents($file); |             $fileContent = $controller->returnFileContents($file); | ||||||
| @ -184,4 +189,39 @@ class ServerController extends Controller | |||||||
| 
 | 
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * Renders server settings page. | ||||||
|  |      * | ||||||
|  |      * @param  \Illuminate\Http\Request $request | ||||||
|  |      * @return \Illuminate\Contracts\View\View | ||||||
|  |      */ | ||||||
|  |     public function getSettings(Request $request, $uuid) | ||||||
|  |     { | ||||||
|  |         $server = Server::getByUUID($uuid); | ||||||
|  |         return view('server.settings', [ | ||||||
|  |             'server' => $server, | ||||||
|  |             'node' => Node::find($server->node) | ||||||
|  |         ]); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public function postSettingsSFTP(Request $request, $uuid) | ||||||
|  |     { | ||||||
|  |         $server = Server::getByUUID($uuid); | ||||||
|  |         $this->authorize('reset-sftp', $server); | ||||||
|  | 
 | ||||||
|  |         try { | ||||||
|  |             $repo = new ServerRepository; | ||||||
|  |             $repo->updateSFTPPassword($server->id, $request->input('sftp_pass')); | ||||||
|  |             Alert::success('Successfully updated this servers SFTP password.')->flash(); | ||||||
|  |         } catch (DisplayValidationException $ex) { | ||||||
|  |             return redirect()->route('server.settings', $uuid)->withErrors(json_decode($ex->getMessage())); | ||||||
|  |         } catch (DisplayException $ex) { | ||||||
|  |             Alert::danger($ex->getMessage())->flash(); | ||||||
|  |         } catch (\Exception $ex) { | ||||||
|  |             Log::error($ex); | ||||||
|  |             Alert::danger('An unknown error occured while attempting to update this server\'s SFTP settings.')->flash(); | ||||||
|  |         } | ||||||
|  |         return redirect()->route('server.settings', $uuid); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  | |||||||
| @ -42,6 +42,17 @@ class ServerRoutes { | |||||||
|                 'uses' => 'Server\ServerController@getIndex' |                 'uses' => 'Server\ServerController@getIndex' | ||||||
|             ]); |             ]); | ||||||
| 
 | 
 | ||||||
|  |             // Settings
 | ||||||
|  |             $router->get('/settings', [ | ||||||
|  |                 'as' => 'server.settings', | ||||||
|  |                 'uses' => 'Server\ServerController@getSettings' | ||||||
|  |             ]); | ||||||
|  | 
 | ||||||
|  |             $router->post('/settings/sftp', [ | ||||||
|  |                 'as' => 'server.settings.sftp', | ||||||
|  |                 'uses' => 'Server\ServerController@postSettingsSFTP' | ||||||
|  |             ]); | ||||||
|  | 
 | ||||||
|             // File Manager Routes
 |             // File Manager Routes
 | ||||||
|             $router->get('/files', [ |             $router->get('/files', [ | ||||||
|                 'as' => 'files.index', |                 'as' => 'files.index', | ||||||
|  | |||||||
| @ -98,8 +98,8 @@ class Node extends Model | |||||||
|         // @TODO: Better solution to disabling verification. Security risk.
 |         // @TODO: Better solution to disabling verification. Security risk.
 | ||||||
|         self::$guzzle[$node] = new Client([ |         self::$guzzle[$node] = new Client([ | ||||||
|             'base_uri' => sprintf('%s://%s:%s/', $nodeData->scheme, $nodeData->fqdn, $nodeData->daemonListen), |             'base_uri' => sprintf('%s://%s:%s/', $nodeData->scheme, $nodeData->fqdn, $nodeData->daemonListen), | ||||||
|             'timeout' => 10.0, |             'timeout' => 5.0, | ||||||
|             'connect_timeout' => 5.0, |             'connect_timeout' => 3.0, | ||||||
|         ]); |         ]); | ||||||
| 
 | 
 | ||||||
|         return self::$guzzle[$node]; |         return self::$guzzle[$node]; | ||||||
|  | |||||||
| @ -724,4 +724,39 @@ class ServerRepository | |||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     public function updateSFTPPassword($id, $password) | ||||||
|  |     { | ||||||
|  |         $server = Models\Server::findOrFail($id); | ||||||
|  |         $node = Models\Node::findOrFail($server->node); | ||||||
|  | 
 | ||||||
|  |         $validator = Validator::make([ | ||||||
|  |             'password' => $password, | ||||||
|  |         ], [ | ||||||
|  |             'password' => 'required|regex:/^((?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,})$/' | ||||||
|  |         ]); | ||||||
|  | 
 | ||||||
|  |         if ($validator->fails()) { | ||||||
|  |             throw new DisplayValidationException(json_encode($validator->errors())); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         try { | ||||||
|  |             $client = Models\Node::guzzleRequest($server->node); | ||||||
|  |             $client->request('POST', '/server/password', [ | ||||||
|  |                 'headers' => [ | ||||||
|  |                     'X-Access-Token' => $node->daemonSecret, | ||||||
|  |                     'X-Access-Server' => $server->uuid | ||||||
|  |                 ], | ||||||
|  |                 'json' => [ | ||||||
|  |                     'password' => $password, | ||||||
|  |                 ], | ||||||
|  |             ]); | ||||||
|  |             return true; | ||||||
|  |         } catch (\GuzzleHttp\Exception\TransferException $ex) { | ||||||
|  |             throw new DisplayException('There was an error while attmping to contact the remote service to change the password.'); | ||||||
|  |         } catch (\Exception $ex) { | ||||||
|  |             throw $ex; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  | |||||||
| @ -218,7 +218,13 @@ | |||||||
|                                 <a href="/server/{{ $server->uuidShort }}/" class="list-group-item server-index">{{ trans('pagination.sidebar.overview') }}</a> |                                 <a href="/server/{{ $server->uuidShort }}/" class="list-group-item server-index">{{ trans('pagination.sidebar.overview') }}</a> | ||||||
|                                 @can('list-files', $server)<a href="/server/{{ $server->uuidShort }}/files" class="list-group-item server-files">{{ trans('pagination.sidebar.files') }}</a>@endcan |                                 @can('list-files', $server)<a href="/server/{{ $server->uuidShort }}/files" class="list-group-item server-files">{{ trans('pagination.sidebar.files') }}</a>@endcan | ||||||
|                                 @can('list-subusers', $server)<a href="/server/{{ $server->uuidShort }}/users" class="list-group-item server-users">{{ trans('pagination.sidebar.subusers') }}</a>@endcan |                                 @can('list-subusers', $server)<a href="/server/{{ $server->uuidShort }}/users" class="list-group-item server-users">{{ trans('pagination.sidebar.subusers') }}</a>@endcan | ||||||
|                                 @can('view-manage', $server)<a href="/server/{{ $server->uuidShort }}/settings" class="list-group-item server-settings">{{ trans('pagination.sidebar.manage') }}</a>@endcan |                                 @can('view-sftp', $server) | ||||||
|  |                                     <a href="/server/{{ $server->uuidShort }}/settings" class="list-group-item server-settings">{{ trans('pagination.sidebar.manage') }}</a> | ||||||
|  |                                 @else | ||||||
|  |                                     @can('view-startup', $server) | ||||||
|  |                                         <a href="/server/{{ $server->uuidShort }}/settings" class="list-group-item server-settings">{{ trans('pagination.sidebar.manage') }}</a> | ||||||
|  |                                     @endcan | ||||||
|  |                                 @endcan | ||||||
|                             </div> |                             </div> | ||||||
|                         @endif |                         @endif | ||||||
|                     @show |                     @show | ||||||
|  | |||||||
							
								
								
									
										96
									
								
								resources/views/server/settings.blade.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								resources/views/server/settings.blade.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,96 @@ | |||||||
|  | {{-- | ||||||
|  |     Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com> | ||||||
|  | 
 | ||||||
|  |     Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
|  |     of this software and associated documentation files (the "Software"), to deal | ||||||
|  |     in the Software without restriction, including without limitation the rights | ||||||
|  |     to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
|  |     copies of the Software, and to permit persons to whom the Software is | ||||||
|  |     furnished to do so, subject to the following conditions: | ||||||
|  | 
 | ||||||
|  |     The above copyright notice and this permission notice shall be included in all | ||||||
|  |     copies or substantial portions of the Software. | ||||||
|  | 
 | ||||||
|  |     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  |     IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  |     FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
|  |     AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
|  |     LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
|  |     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||||
|  |     SOFTWARE. | ||||||
|  | --}} | ||||||
|  | @extends('layouts.master') | ||||||
|  | 
 | ||||||
|  | @section('title') | ||||||
|  |     Server Settings | ||||||
|  | @endsection | ||||||
|  | 
 | ||||||
|  | @section('content') | ||||||
|  | <div class="col-md-12"> | ||||||
|  |     <h3 class="nopad">Server Settings</h3><hr /> | ||||||
|  |     <ul class="nav nav-tabs tabs_with_panel" id="config_tabs"> | ||||||
|  |         @can('view-sftp', $server)<li class="active"><a href="#tab_sftp" data-toggle="tab">SFTP Settings</a></li>@endcan | ||||||
|  |         @can('view-startup', $server)<li><a href="#tab_startup" data-toggle="tab">Startup Configuration</a></li>@endcan | ||||||
|  |     </ul> | ||||||
|  |     <div class="tab-content"> | ||||||
|  |         @can('view-sftp', $server) | ||||||
|  |             <div class="tab-pane active" id="tab_sftp"> | ||||||
|  |                 <div class="panel panel-default"> | ||||||
|  |                     <div class="panel-heading"></div> | ||||||
|  |                     <div class="panel-body"> | ||||||
|  |                         <div class="row"> | ||||||
|  |                             <div class="form-group col-md-6"> | ||||||
|  |                                 <label class="control-label">SFTP Connection Address:</label> | ||||||
|  |                                 <div> | ||||||
|  |                                     <input type="text" readonly="readonly" class="form-control" value="{{ $node->fqdn }}:{{ $node->daemonSFTP }}" /> | ||||||
|  |                                 </div> | ||||||
|  |                             </div> | ||||||
|  |                             <div class="form-group col-md-6"> | ||||||
|  |                                 <label class="control-label">SFTP Username:</label> | ||||||
|  |                                 <div> | ||||||
|  |                                     <input type="text" readonly="readonly" class="form-control" value="{{ $server->username }}" /> | ||||||
|  |                                 </div> | ||||||
|  |                             </div> | ||||||
|  |                         </div> | ||||||
|  |                         @can('reset-sftp', $server) | ||||||
|  |                             <form action="{{ route('server.settings.sftp', $server->uuidShort) }}" method="POST"> | ||||||
|  |                                 <div class="row"> | ||||||
|  |                                     <div class="form-group col-md-6"> | ||||||
|  |                                         <label class="control-label">New SFTP Password:</label> | ||||||
|  |                                         <div> | ||||||
|  |                                             <input type="password" name="sftp_pass" class="form-control" /> | ||||||
|  |                                             <p class="text-muted"><small>Passwords must meet the following requirements: at least one uppercase character, one lowercase character, one digit, and be at least 8 characters in length. <a href="#" data-action="generate-password">Click here</a> to generate one to use.</small></p> | ||||||
|  |                                         </div> | ||||||
|  |                                     </div> | ||||||
|  |                                     <div class="form-group col-md-6"> | ||||||
|  |                                         <label class="control-label"> </label> | ||||||
|  |                                         <div> | ||||||
|  |                                             {!! csrf_field() !!} | ||||||
|  |                                             <input type="submit" class="btn btn-sm btn-primary" value="Update Password" /> | ||||||
|  |                                         </div> | ||||||
|  |                                     </div> | ||||||
|  |                                 </div> | ||||||
|  |                             </form> | ||||||
|  |                         @endcan | ||||||
|  |                     </div> | ||||||
|  |                 </div> | ||||||
|  |             </div> | ||||||
|  |         @endcan | ||||||
|  |         @can('view-startup', $server) | ||||||
|  |             <div class="tab-pane" id="tab_startup"> | ||||||
|  |                 <div class="panel panel-default"> | ||||||
|  |                     <div class="panel-heading"></div> | ||||||
|  |                     <div class="panel-body"> | ||||||
|  |                         Startup | ||||||
|  |                     </div> | ||||||
|  |                 </div> | ||||||
|  |             </div> | ||||||
|  |         @endcan | ||||||
|  |     </div> | ||||||
|  | </div> | ||||||
|  | <script> | ||||||
|  | $(document).ready(function () { | ||||||
|  |     $('.server-settings').addClass('active'); | ||||||
|  | }); | ||||||
|  | </script> | ||||||
|  | @endsection | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Dane Everitt
						Dane Everitt