Advertisement
Guest User

Untitled

a guest
Feb 14th, 2017
152
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 23.16 KB | None | 0 0
  1. {{-- Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com> --}}
  2.  
  3. {{-- Permission is hereby granted, free of charge, to any person obtaining a copy --}}
  4. {{-- of this software and associated documentation files (the "Software"), to deal --}}
  5. {{-- in the Software without restriction, including without limitation the rights --}}
  6. {{-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell --}}
  7. {{-- copies of the Software, and to permit persons to whom the Software is --}}
  8. {{-- furnished to do so, subject to the following conditions: --}}
  9.  
  10. {{-- The above copyright notice and this permission notice shall be included in all --}}
  11. {{-- copies or substantial portions of the Software. --}}
  12.  
  13. {{-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR --}}
  14. {{-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, --}}
  15. {{-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE --}}
  16. {{-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER --}}
  17. {{-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, --}}
  18. {{-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE --}}
  19. {{-- SOFTWARE. --}}
  20. @extends('layouts.master')
  21.  
  22. @section('title')
  23. Server Settings
  24. @endsection
  25.  
  26. @section('scripts')
  27. @parent
  28. {!! Theme::js('js/vendor/typeahead/typeahead.min.js') !!}
  29. @endsection
  30.  
  31. @section('content')
  32. <div class="col-md-12">
  33. <h3 class="nopad">Server Settings</h3><hr />
  34. <ul class="nav nav-tabs tabs_with_panel" id="config_tabs">
  35. @can('view-sftp', $server)<li class="active"><a href="#tab_sftp" data-toggle="tab">SFTP Settings</a></li>@endcan
  36. @can('view-startup', $server)<li><a href="#tab_startup" data-toggle="tab">Startup Configuration</a></li>@endcan
  37. @can('view-databases', $server)<li><a href="#tab_databases" data-toggle="tab">Databases</a></li>@endcan
  38. @can('view-databases', $server)<li><a href="#tab_mods" data-toggle="tab">Mods</a></li>@endcan
  39. </ul>
  40. <div class="tab-content">
  41. @can('view-sftp', $server)
  42. <div class="tab-pane active" id="tab_sftp">
  43. <div class="panel panel-default">
  44. <div class="panel-heading"></div>
  45. <div class="panel-body">
  46. <div class="row">
  47. <div class="form-group col-md-6">
  48. <label class="control-label">SFTP Connection Address:</label>
  49. <div>
  50. <input type="text" readonly="readonly" class="form-control" value="{{ $node->fqdn }}:{{ $node->daemonSFTP }}" />
  51. </div>
  52. </div>
  53. <div class="form-group col-md-6">
  54. <label class="control-label">SFTP Username:</label>
  55. <div>
  56. <input type="text" readonly="readonly" class="form-control" value="{{ $server->username }}" />
  57. </div>
  58. </div>
  59. </div>
  60. <div class="row">
  61. <div class="col-md-12">
  62. <div id="gen_pass" class=" alert alert-success" style="display:none;margin-bottom: 10px;"></div>
  63. </div>
  64. <div class="form-group col-md-6">
  65. @can('reset-sftp', $server)
  66. <form action="{{ route('server.settings.sftp', $server->uuidShort) }}" method="POST">
  67. <label class="control-label">New SFTP Password:</label>
  68. <div class="input-group">
  69. <input type="password" class="form-control" name="sftp_pass" />
  70. <span class="input-group-btn">
  71. {!! csrf_field() !!}
  72. <input type="submit" class="btn btn-primary btn-sm" value="Reset" />
  73. </span>
  74. </div>
  75. <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>
  76. </form>
  77. @endcan
  78. </div>
  79. <div class="form-group col-md-6">
  80. @can('view-sftp-password', $server)
  81. <label class="control-label">Current Password:</label>
  82. <div>
  83. <input type="text" readonly="readonly" class="form-control" value="@if(!is_null($server->sftp_password)){{ Crypt::decrypt($server->sftp_password) }}@endif" />
  84. </div>
  85. @endcan
  86. </div>
  87. </div>
  88. </div>
  89. </div>
  90. </div>
  91. @endcan
  92.  
  93.  
  94.  
  95. @can('view-startup', $server)
  96. <div class="tab-pane" id="tab_startup">
  97. <form action="{{ route('server.settings.startup', $server->uuidShort) }}" method="POST">
  98. <div class="panel panel-default">
  99. <div class="panel-heading"></div>
  100. <div class="panel-body">
  101. <div class="row">
  102. <div class="form-group col-md-12">
  103. <label class="control-label">Startup Command:</label>
  104. <div class="input-group">
  105. <span class="input-group-addon">{{ $service->executable }}</span>
  106. <input type="text" class="form-control" readonly="readonly" value="{{ $processedStartup }}" />
  107. </div>
  108. </div>
  109. </div>
  110. </div>
  111. @can('edit-startup', $server)
  112. <div class="panel-heading" style="border-top: 1px solid #ddd;"></div>
  113. <div class="panel-body">
  114. <div class="row">
  115. @foreach($variables as $item)
  116. <div class="form-group col-md-6">
  117. <label class="control-label">
  118. @if($item->required === 1)<span class="label label-primary">Required</span> @endif
  119. {{ $item->name }}
  120. </label>
  121. <div>
  122. <input type="text"
  123. @if($item->user_editable === 1)
  124. name="{{ $item->env_variable }}"
  125. @else
  126. readonly="readonly"
  127. @endif
  128. class="form-control" value="{{ old($item->env_variable, $item->a_serverValue) }}" data-action="matchRegex" data-regex="{{ $item->regex }}" />
  129. </div>
  130. <p class="text-muted"><small>{!! $item->description !!}</small></p>
  131. </div>
  132. @endforeach
  133. </div>
  134. </div>
  135. <div class="panel-heading" style="border-top: 1px solid #ddd;"></div>
  136. <div class="panel-body">
  137. <div class="row">
  138. <div class="col-md-12">
  139. {!! csrf_field() !!}
  140. <input type="submit" class="btn btn-primary btn-sm" value="Update Startup Arguments" />
  141. </div>
  142. </div>
  143. </div>
  144. @endcan
  145. </div>
  146. </form>
  147. </div>
  148. @endcan
  149. @can('view-databases', $server)
  150. <div class="tab-pane" id="tab_databases">
  151. <div class="panel panel-default">
  152. <div class="panel-heading"></div>
  153. <div class="panel-body">
  154. @if(count($databases) > 0)
  155. <table class="table table-bordered table-hover" style="margin-bottom:0;">
  156. <thead>
  157. <tr>
  158. <th>Database</th>
  159. <th>Username</th>
  160. <th>Password</th>
  161. <th>DB Server</th>
  162. </th>
  163. </thead>
  164. <tbody>
  165. @foreach($databases as $database)
  166. <tr>
  167. <td>{{ $database->database }}</td>
  168. <td>{{ $database->username }}</td>
  169. <td><code>{{ Crypt::decrypt($database->password) }}</code> @can('reset-db-password', $server)<a href="#" data-action="reset-database-password" data-id="{{ $database->id }}"><i class="fa fa-refresh pull-right"></i></a>@endcan</td>
  170. <td><code>{{ $database->a_host }}:{{ $database->a_port }}</code></td>
  171. </tr>
  172. @endforeach
  173. </tbody>
  174. </table>
  175. @else
  176. <div class="alert alert-info" style="margin-bottom:0;">
  177. There are no databases configured for this server.
  178. @if(Auth::user()->root_admin === 1)
  179. <a href="{{ route('admin.servers.view', [
  180. 'id' => $server->id,
  181. 'tab' => 'tab_database'
  182. ]) }}" target="_blank">Add a new database.</a>
  183. @endif
  184. </div>
  185. @endif
  186. </div>
  187. </div>
  188. </div>
  189. @endcan
  190.  
  191. <!-- MY CODE -->
  192.  
  193. <div class="tab-pane" id="tab_mods">
  194. <form action="/admin/servers/new" method="POST">
  195. <div class="panel panel-default">
  196. <div class="panel-heading"></div>
  197. <div class="panel-body">
  198. <div class="row">
  199. <div class="col-md-6" id="load_services">
  200. <div class="well">
  201. <div class="row">
  202. <div class="ajax_loading_box" style="display:none;"><i class="fa fa-refresh fa-spin ajax_loading_position"></i></div>
  203. <div class="form-group col-md-12">
  204. <label for="service" class="control-label">Service Type</label>
  205. <div>
  206. <select name="service" id="getService" class="form-control">
  207. <option disabled selected> -- Select a Service</option>
  208. @foreach($services as $service)
  209. <option value="{{ $service->id }}">{{ $service->name }}</option>
  210. @endforeach
  211. </select>
  212. <p class="text-muted"><small>Select the type of service that this server will be running.</small></p>
  213. </div>
  214. </div>
  215. <div class="form-group col-md-12 hidden">
  216. <label for="option" class="control-label">Service Option</label>
  217. <div>
  218. <select name="option" id="getOption" class="form-control">
  219. <option disabled selected> -- Select a Service Option</option>
  220. </select>
  221. <p class="text-muted"><small>Select the type of service that this server will be running.</small></p>
  222. </div>
  223. </div>
  224. </div>
  225. </div>
  226. </div>
  227. <div class="col-md-6">
  228. <div class="well">
  229. <div class="row">
  230. <div class="form-group col-md-12">
  231. <label for="use_custom_image" class="control-label">Use Custom Docker Image</label>
  232. <div class="input-group">
  233. <span class="input-group-addon">
  234. <input @if(old('use_custom_image') === 'use_custom_image')checked="checked"@endif type="checkbox" name="use_custom_image"/>
  235. </span>
  236. <input type="text" class="form-control" name="custom_image_name" value="{{ old('custom_image_name') }}" disabled />
  237. </div>
  238. <p class="text-muted"><small>If you would like to use a custom docker image for this server please enter it here. Most users can ignore this option.</small></p>
  239. </div>
  240. </div>
  241. </div>
  242. </div>
  243. </div>
  244. <div class="well" id="serviceOptions" style="display:none;">
  245. <div class="row">
  246. <div class="form-group col-md-12">
  247. <h3 class="nopad">Service Setup &amp; Options</h3>
  248. <hr />
  249. <label for="startup" class="control-label">Startup Command</label>
  250. <div class="input-group">
  251. <span class="input-group-addon" id="startupExec"></span>
  252. <input type="text" class="form-control" name="startup" value="{{ old('startup') }}" />
  253. </div>
  254. <p class="text-muted"><small>The following data replacers are avaliable for the startup command: <code>@{{SERVER_MEMORY}}</code>, <code>@{{SERVER_IP}}</code>, and <code>@{{SERVER_PORT}}</code>. They will be replaced with the allocated memory, server ip, and server port respectively.</small></p>
  255. </div>
  256. </div>
  257. <div class="row">
  258. <div class="col-md-12">
  259. <div class="alert alert-info">Some service options have additional environment variables that you can define for a given instance. They will show up below when you select a service option. If none show up, chances are that none were defined, and there is nothing to worry about.</div>
  260. </div>
  261. </div>
  262. <div class="row" id="serverVariables"></div>
  263. </div>
  264. <div class="well">
  265. <div class="row">
  266. <div class="col-md-12 text-center">
  267. {!! csrf_field() !!}
  268. <input type="submit" class="btn btn-primary btn-sm" value="Create New Server" />
  269. </div>
  270. </div>
  271. </div>
  272. </div>
  273. </div>
  274. </form>
  275. </div>
  276.  
  277. <!-- END MY CODE -->
  278.  
  279. </div>
  280. </div>
  281. <script>
  282. $(document).ready(function () {
  283. $('.server-settings').addClass('active');
  284.  
  285. $('[data-action="matchRegex"]').keyup(function (event) {
  286. if (!$(this).data('regex')) return;
  287. var input = $(this).val();
  288. console.log(escapeRegExp($(this).data('regex')));
  289. var regex = new RegExp(escapeRegExp($(this).data('regex')));
  290. console.log(regex);
  291. if (!regex.test(input)) {
  292. $(this).parent().parent().removeClass('has-success').addClass('has-error');
  293. } else {
  294. $(this).parent().parent().removeClass('has-error').addClass('has-success');
  295. }
  296. });
  297. $('[data-action="generate-password"]').click(function(e){
  298. e.preventDefault();
  299. $.ajax({
  300. type: "GET",
  301. url: "/password-gen/12",
  302. headers: {
  303. 'X-CSRF-TOKEN': '{{ csrf_token() }}'
  304. },
  305. success: function(data) {
  306. $("#gen_pass").html('<strong>Generated Password:</strong> ' + data).slideDown();
  307. $('input[name="sftp_pass"]').val(data);
  308. return false;
  309. }
  310. });
  311. return false;
  312. });
  313. $('[data-action="reset-database-password"]').click(function (e) {
  314. e.preventDefault();
  315. var block = $(this);
  316. $(this).find('i').addClass('fa-spin');
  317. $.ajax({
  318. type: 'POST',
  319. url: '{{ route('server.ajax.reset-database-password', $server->uuidShort) }}',
  320. headers: {
  321. 'X-CSRF-TOKEN': '{{ csrf_token() }}'
  322. },
  323. data: {
  324. 'database': $(this).data('id')
  325. }
  326. }).done(function (data) {
  327. block.parent().find('code').html(data);
  328. }).fail(function(jqXHR, textStatus, errorThrown) {
  329. console.error(jqXHR);
  330. var error = 'An error occured while trying to process this request.';
  331. if (typeof jqXHR.responseJSON !== 'undefined' && typeof jqXHR.responseJSON.error !== 'undefined') {
  332. error = jqXHR.responseJSON.error;
  333. }
  334. swal({
  335. type: 'error',
  336. title: 'Whoops!',
  337. text: error
  338. });
  339. }).always(function () {
  340. block.find('i').removeClass('fa-spin');
  341. });
  342. });
  343.  
  344. <!- MY CODE ->
  345.  
  346. var currentService = null;
  347.  
  348. $('#getService').on('change', function (event) {
  349.  
  350. alert('An error occured while attempting to list options for this service.');
  351.  
  352. if ($('#getService').val() === '' || $('#getService').val() === currentService) {
  353. return;
  354. }
  355.  
  356. alert('An error occured while attempting to list options for this service.');
  357.  
  358. currentService = $('#getService').val();
  359. handleLoader('#load_services', true);
  360. $('#serviceOptions').slideUp();
  361. $('#getOption').html('<option disabled selected> -- Select a Service Option</option>');
  362.  
  363. $.ajax({
  364. method: 'POST',
  365. url: '/admin/servers/new/service-options',
  366. headers: {
  367. 'X-CSRF-TOKEN': '{{ csrf_token() }}'
  368. },
  369. data: {
  370. service: $('#getService').val()
  371. }
  372. }).done(function (data) {
  373. $.each(data, function (i, option) {
  374. $('#getOption').append('<option value="' + option.id + '" data-image="' + option.docker_image + '">' + option.name + '</option>');
  375. });
  376. $('#getOption').parent().parent().removeClass('hidden');
  377. }).fail(function (jqXHR) {
  378. alert('An error occured while attempting to list options for this service.');
  379. currentService = null;
  380. console.error(jqXHR);
  381. }).always(function () {
  382. handleLoader('#load_services');
  383. });
  384.  
  385. });
  386.  
  387. $('#getOption').on('change', function (event) {
  388.  
  389. handleLoader('#load_services', true);
  390. handleLoader('#serviceOptions', true);
  391. $('#serverVariables').html('');
  392. $('input[name="custom_image_name"]').val($(this).find(':selected').data('image'));
  393.  
  394. $.ajax({
  395. method: 'POST',
  396. url: '/admin/servers/new/service-variables',
  397. headers: {
  398. 'X-CSRF-TOKEN': '{{ csrf_token() }}'
  399. },
  400. data: {
  401. option: $('#getOption').val()
  402. }
  403. }).done(function (data) {
  404. $('#startupExec').html(data.exec);
  405. $('input[name="startup"]').val(data.startup);
  406. $.each(data.variables, function (i, item) {
  407. var isRequired = (item.required === 1) ? '<span class="label label-primary">Required</span> ' : '';
  408. var dataAppend = ' \
  409. <div class="form-group col-md-12">\
  410. <label for="var_ref_' + item.id + '" class="control-label">' + isRequired + item.name + '</label> \
  411. <div>\
  412. <input type="text" autocomplete="off" name="env_' + item.env_variable + '" class="form-control" value="' + item.default_value + '" />\
  413. <p class="text-muted"><small>' + item.description + '</small></p>\
  414. <p class="text-muted"><small>Regex Requirements for Input: <code>' + item.regex + '</code></small></p>\
  415. <p class="text-muted"><small>Access in Startup: <code>@{{' + item.env_variable + '}}</code></small></p>\
  416. </div>\
  417. </div>\
  418. ';
  419. $('#serverVariables').append(dataAppend);
  420. });
  421. $('#serviceOptions').slideDown();
  422. }).fail(function (jqXHR) {
  423. console.error(jqXHR);
  424. }).always(function () {
  425. handleLoader('#load_services');
  426. handleLoader('#serviceOptions');
  427. });
  428.  
  429. });
  430.  
  431. // Show Loading Animation
  432. function handleLoader (element, show) {
  433.  
  434. var spinner = $(element).find('.ajax_loading_position');
  435. var popover = $(element).find('.ajax_loading_box');
  436.  
  437. // Show Animation
  438. if (typeof show !== 'undefined') {
  439. var height = $(element).height();
  440. var width = $(element).width();
  441. var center_height = (height / 2) - 16;
  442. var center_width = (width / 2) - 16;
  443. spinner.css({
  444. 'top': center_height,
  445. 'left': center_width,
  446. 'font-size': '32px'
  447. });
  448. popover.css({
  449. 'height': height,
  450. 'margin': '-20px 0 0 -5px',
  451. 'width': width
  452. }).fadeIn();
  453. } else {
  454. popover.hide();
  455. }
  456.  
  457. }
  458.  
  459. });
  460. </script>
  461. @endsection
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement