Internal Themes

This commit is contained in:
DDynamic 2016-02-04 17:28:14 -06:00
parent 9a07cc83d1
commit 192498e51a
80 changed files with 20 additions and 1 deletions

View file

@ -1,61 +0,0 @@
{{-- Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com> --}}
{{-- Some Modifications (c) 2015 Dylan Seidt <dylan.seidt@gmail.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.admin')
@section('title')
Account List
@endsection
@section('content')
<div class="col-md-12">
<ul class="breadcrumb">
<li><a href="/admin">Admin Control</a></li>
<li class="active">Accounts</li>
</ul>
<h3>All Registered Users</h3><hr />
<table class="table table-striped table-bordered table-hover">
<thead>
<tr>
<th>Email</th>
<th>Account Created</th>
<th>Account Updated</th>
</tr>
</thead>
<tbody>
@foreach ($users as $user)
<tr>
<td><a href="/admin/accounts/view/{{ $user->id }}"><code>{{ $user->email }}</code></a> @if($user->root_admin === 1)<span class="badge">Administrator</span>@endif</td>
<td>{{ $user->created_at }}</td>
<td>{{ $user->updated_at }}</td>
</tr>
@endforeach
</tbody>
</table>
<div class="row">
<div class="col-md-12 text-center">{!! $users->render() !!}</div>
</div>
</div>
<script>
$(document).ready(function () {
$('#sidebar_links').find("a[href='/admin/accounts']").addClass('active');
});
</script>
@endsection

View file

@ -1,94 +0,0 @@
{{-- Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com> --}}
{{-- Some Modifications (c) 2015 Dylan Seidt <dylan.seidt@gmail.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.admin')
@section('title')
New Account
@endsection
@section('content')
<div class="col-md-12">
<ul class="breadcrumb">
<li><a href="/admin">Admin Controls</a></li>
<li><a href="/admin/accounts">Accounts</a></li>
<li class="active">Add New Account</li>
</ul>
<h3>Create New Account</h3><hr />
<form action="new" method="post">
<fieldset>
<div class="form-group">
<label for="email" class="control-label">Email</label>
<div>
<input type="text" autocomplete="off" name="email" class="form-control" />
</div>
</div>
<div class="row">
<div class="col-md-12">
<div id="gen_pass" class=" alert alert-success" style="display:none;margin-bottom: 10px;"></div>
</div>
<div class="form-group col-md-6">
<label for="pass" class="control-label">Password</label>
<div>
<input type="password" name="password" class="form-control" />
</div>
</div>
<div class="form-group col-md-6">
<label for="pass_2" class="control-label">Password Again</label>
<div>
<input type="password" name="password_confirmation" class="form-control" />
</div>
</div>
</div>
<div class="form-group">
<div>
{!! csrf_field() !!}
<button class="btn btn-primary btn-sm" type="submit">Create Account</button>
<button class="btn btn-default btn-sm" id="gen_pass_bttn" type="button">Generate Password</button>
</div>
</div>
</fieldset>
</form>
</div>
<script>
$(document).ready(function(){
$("#sidebar_links").find("a[href='/admin/account/new']").addClass('active');
$("#gen_pass_bttn").click(function(e){
e.preventDefault();
$.ajax({
type: "GET",
url: "/password-gen/12",
headers: {
'X-CSRF-TOKEN': '{{ csrf_token() }}'
},
success: function(data) {
$("#gen_pass").html('<strong>Generated Password:</strong> ' + data).slideDown();
$('input[name="password"], input[name="password_confirmation"]').val(data);
return false;
}
});
return false;
});
});
$(document).ready(function () {
$('#sidebar_links').find("a[href='/admin/accounts/new']").addClass('active');
});
</script>
@endsection

View file

@ -1,173 +0,0 @@
{{-- Copyright (c) 2015 - 2016 Dane Everitt <dane@daneeveritt.com> --}}
{{-- Some Modifications (c) 2015 Dylan Seidt <dylan.seidt@gmail.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.admin')
@section('title')
Viewing User
@endsection
@section('content')
<div class="col-md-12">
<ul class="breadcrumb">
<li><a href="/admin">Admin Controls</a></li>
<li><a href="/admin/accounts">Accounts</a></li>
<li class="active">{{ $user->email }}</li>
</ul>
<h3>Viewing User: {{ $user->email }}</h3><hr />
<div class="row">
<div class="col-md-12">
<form action="/admin/accounts/update" method="post">
<div class="col-md-6">
<fieldset>
<div class="form-group">
<label for="email" class="control-label">{{ trans('strings.email') }}</label>
<div>
<input type="text" name="email" value="{{ $user->email }}" class="form-control">
</div>
</div>
<div class="form-group">
<label for="registered" class="control-label">{{ trans('strings.registered') }}</label>
<div>
<input type="text" name="registered" value="{{ $user->created_at }}" readonly="readonly" class="form-control">
</div>
</div>
<div class="form-group">
<label for="root_admin" class="control-label">{{ trans('strings.root_administrator') }}</label>
<div>
<select name="root_admin" class="form-control">
<option value="0">{{ trans('strings.no') }}</option>
<option value="1" @if($user->root_admin)selected="selected"@endif>{{ trans('strings.yes') }}</option>
</select>
<p><small class="text-muted"><em><strong><i class="fa fa-warning"></i></strong> {{ trans('base.root_administrator') }}</em></small></p>
</div>
</div>
<div class="form-group">
<input type="hidden" name="user" value="{{ $user->id }}">
{!! csrf_field() !!}
<input type="submit" value="{{ trans('base.account.update_user') }}" class="btn btn-primary btn-sm">
<a href="#">
<button type="button" class="btn btn-sm btn-danger" data-action="deleteUser" value="{{ trans('base.account.delete_user') }}">{{ trans('base.account.delete_user') }}</button>
</a>
</div>
</fieldset>
</div>
<div class="col-md-6">
<div class="well" style="padding-bottom: 0;">
<h4 class="nopad">{{ trans('base.account.update_pass') }}</h5><hr>
<div class="alert alert-success" style="display:none;margin-bottom:10px;" id="gen_pass"></div>
<div class="form-group">
<label for="password" class="control-label">{{ trans('strings.password') }}</label>
<div>
<input type="password" id="password" name="password" class="form-control">
</div>
</div>
<div class="form-group">
<label for="password_confirmation" class="control-label">{{ trans('auth.confirmpassword') }}</label>
<div>
<input type="password" id="password_confirmation" name="password_confirmation" class="form-control">
<div class="checkbox">
<label><input type="checkbox" name="email_user" value="1">{{ trans('base.account.email_password') }}</label>
</div>
</div>
<button class="btn btn-default btn-sm" id="gen_pass_bttn" type="button">Generate Password</button>
</div>
</div>
</div>
</form>
</div>
</div>
<div class="row">
<div class="col-md-12">
<h3>Associated Servers</h3><hr>
@if($servers)
<table class="table table-striped table-bordered table-hover">
<thead>
<tr>
<th style="width:2%;"></th>
<th>Server Name</th>
<th>Node</th>
<th>Connection</th>
<th style="width:10%;"></th>
</tr>
</thead>
<tbody>
@foreach($servers as $server)
<tr>
<td><a href="/server/{{ $server->uuidShort }}/"><i class="fa fa-tachometer"></i></a></td>
<td><a href="/admin/servers/view/{{ $server->id }}">{{ $server->name }}</a></td>
<td>{{ $server->nodeName }}</td>
<td><code>{{ $server->ip }}:{{ $server->port }}</code></td>
<td>@if($server->active)<span class="label label-success">Enabled</span>@else<span class="label label-danger">Disabled</span>@endif</td>
</td>
@endforeach
</tbody>
</table>
@else
<div class="alert alert-info">There are no servers associated with this account.</div>
@endif
<a href="/admin/servers/new?email={{ $user->email }}"><button type="button" class="btn btn-success btn-sm">{{ trans('server.index.add_new') }}</button></a>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function(){
$("#sidebar_links").find("a[href='/admin/accounts']").addClass('active');
$('#delete').click(function() {
if(confirm('{{ trans('base.confirm') }}')) {
$('#delete').load($(this).attr('href'));
}
});
$("#gen_pass_bttn").click(function(e){
e.preventDefault();
$.ajax({
type: "GET",
url: "/password-gen/12",
headers: {
'X-CSRF-TOKEN': '{{ csrf_token() }}'
},
success: function(data) {
$("#gen_pass").html('<strong>Generated Password:</strong> ' + data).slideDown();
$('input[name="password"], input[name="password_confirmation"]').val(data);
return false;
}
});
return false;
});
$('button[data-action="deleteUser"]').click(function (event) {
event.preventDefault();
$.ajax({
method: 'DELETE',
url: '/admin/accounts/view/{{ $user->id }}',
headers: {
'X-CSRF-TOKEN': '{{ csrf_token() }}'
}
}).done(function (data) {
alert('Account was successfully deleted from the system.');
window.location = '/admin/accounts';
}).fail(function (jqXHR) {
console.error(jqXHR);
alert('An error occured: ' + jqXHR.JSONResponse.error);
})
})
});
</script>
@endsection

View file

@ -1,113 +0,0 @@
{{-- 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.admin')
@section('title')
API Management
@endsection
@section('content')
<div class="col-md-12">
<ul class="breadcrumb">
<li><a href="/admin">Admin Control</a></li>
<li class="active">API Management</li>
</ul>
<h3>API Key Information</h3><hr />
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>API Public Key</th>
<th>Allowed IPs</th>
<th>Permissions</th>
<th class="text-center">Created</th>
<th class="text-center"></th>
</tr>
</thead>
<tbody>
@foreach ($keys as $key)
<tr>
<td><code>{{ $key->public }}</code></td>
<td>
@if (is_null($key->allowed_ips))
<code>*</code>
@else
@foreach(json_decode($key->allowed_ips) as $ip)
<code style="line-height:2;">{{ $ip }}</code><br />
@endforeach
@endif
</td>
<td>
@foreach(json_decode($key->permissions) as &$perm)
<code style="line-height:2;">{{ $perm->permission }}</code><br />
@endforeach
</td>
<td class="text-center">{{ $key->created_at }}</td>
<td class="text-center"><a href="#delete" class="text-danger" data-action="delete" data-attr="{{ $key->public }}"><i class="fa fa-trash"></i></a></td>
</tr>
@endforeach
</tbody>
</table>
<div class="well">
<a href="{{ route('admin.api.new') }}"><button class="btn btn-success btn-sm">Create New API Key</button></a>
</div>
</div>
<script>
$(document).ready(function () {
$('#sidebar_links').find("a[href='/admin/api']").addClass('active');
$('[data-action="delete"]').click(function (event) {
var self = $(this);
event.preventDefault();
swal({
type: 'error',
title: 'Revoke API Key',
text: 'Once this API key is revoked any applications currently using it will stop working.',
showCancelButton: true,
allowOutsideClick: true,
closeOnConfirm: false,
confirmButtonText: 'Revoke',
confirmButtonColor: '#d9534f',
showLoaderOnConfirm: true
}, function () {
$.ajax({
method: 'DELETE',
url: '{{ route('admin.api.revoke') }}/' + self.data('attr'),
headers: {
'X-CSRF-TOKEN': '{{ csrf_token() }}'
}
}).done(function (data) {
swal({
type: 'success',
title: '',
text: 'API Key has been revoked.'
});
self.parent().parent().slideUp();
}).fail(function (jqXHR) {
console.error(jqXHR);
swal({
type: 'error',
title: 'Whoops!',
text: 'An error occured while attempting to revoke this key.'
});
});
});
});
});
</script>
@endsection

View file

@ -1,201 +0,0 @@
{{-- 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.admin')
@section('title')
API Management
@endsection
@section('content')
<div class="col-md-12">
<ul class="breadcrumb">
<li><a href="/admin">Admin Control</a></li>
<li><a href="/admin/api">API Management</a></li>
<li class="active">New</li>
</ul>
<h3>Add New API Key</h3><hr />
<form action="{{ route('admin.api.new') }}" method="POST">
<div class="row">
<div class="col-md-12 fuelux">
<div class="checkbox highlight">
<label class="checkbox-custom highlight" data-initialize="checkbox">
<input class="sr-only" name="permissions[]" type="checkbox" value="*"> <strong>*</strong>
<p class="text-muted"><small><span class="label label-danger">Danger</span> Allows performing any action aganist the API.</small><p>
</label>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6 fuelux">
<h4>User Management</h4><hr />
<div class="checkbox highlight">
<label class="checkbox-custom highlight" data-initialize="checkbox">
<input class="sr-only" name="permissions[]" type="checkbox" value="api.users"> <strong>GET /users</strong>
<p class="text-muted"><small>Allows listing of all users currently on the system.</small><p>
</label>
</div>
<div class="checkbox highlight">
<label class="checkbox-custom highlight" data-initialize="checkbox">
<input class="sr-only" name="permissions[]" type="checkbox" value="api.users.post"> <strong>POST /users</strong>
<p class="text-muted"><small>Allows creating a new user on the system.</small><p>
</label>
</div>
<div class="checkbox highlight">
<label class="checkbox-custom highlight" data-initialize="checkbox">
<input class="sr-only" name="permissions[]" type="checkbox" value="api.users.view"> <strong>GET /users/{id}</strong>
<p class="text-muted"><small>Allows viewing details about a specific user including active services.</small><p>
</label>
</div>
<div class="checkbox highlight">
<label class="checkbox-custom highlight" data-initialize="checkbox">
<input class="sr-only" name="permissions[]" type="checkbox" value="api.users.patch"> <strong>PATCH /users/{id}</strong>
<p class="text-muted"><small>Allows modifying user details (email, password, TOTP information).</small><p>
</label>
</div>
<div class="checkbox highlight">
<label class="checkbox-custom highlight" data-initialize="checkbox">
<input class="sr-only" name="permissions[]" type="checkbox" value="api.users.delete"> <strong>DELETE /users/{id}</strong>
<p class="text-muted"><small>Allows deleting a user.</small><p>
</label>
</div>
</div>
<div class="col-md-6 fuelux">
<h4>Server Management</h4><hr />
<div class="checkbox highlight">
<label class="checkbox-custom highlight" data-initialize="checkbox">
<input class="sr-only" name="permissions[]" type="checkbox" value="api.servers"> <strong>GET /servers</strong>
<p class="text-muted"><small>Allows listing of all servers currently on the system.</small><p>
</label>
</div>
<div class="checkbox highlight">
<label class="checkbox-custom highlight" data-initialize="checkbox">
<input class="sr-only" name="permissions[]" type="checkbox" value="api.servers.post"> <strong>POST /servers</strong>
<p class="text-muted"><small>Allows creating a new server on the system.</small><p>
</label>
</div>
<div class="checkbox highlight">
<label class="checkbox-custom highlight" data-initialize="checkbox">
<input class="sr-only" name="permissions[]" type="checkbox" value="api.servers.view"> <strong>GET /servers/{id}</strong>
<p class="text-muted"><small>Allows viewing details about a specific server.</small><p>
</label>
</div>
<div class="checkbox highlight">
<label class="checkbox-custom highlight" data-initialize="checkbox">
<input class="sr-only" name="permissions[]" type="checkbox" value="api.servers.suspend"> <strong>POST /servers/{id}/suspend</strong>
<p class="text-muted"><small>Allows suspending a server instance.</small><p>
</label>
</div>
<div class="checkbox highlight">
<label class="checkbox-custom highlight" data-initialize="checkbox">
<input class="sr-only" name="permissions[]" type="checkbox" value="api.servers.unsuspend"> <strong>POST /servers/{id}/unsuspend</strong>
<p class="text-muted"><small>Allows unsuspending a server instance.</small><p>
</label>
</div>
<div class="checkbox highlight">
<label class="checkbox-custom highlight" data-initialize="checkbox">
<input class="sr-only" name="permissions[]" type="checkbox" value="api.servers.delete"> <strong>DELETE /servers/{id}</strong>
<p class="text-muted"><small>Allows deleting a server.</small><p>
</label>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6 fuelux">
<h4>Node Management</h4><hr />
<div class="checkbox highlight">
<label class="checkbox-custom highlight" data-initialize="checkbox">
<input class="sr-only" name="permissions[]" type="checkbox" value="api.nodes"> <strong>GET /nodes</strong>
<p class="text-muted"><small>Allows listing of all nodes currently on the system.</small><p>
</label>
</div>
<div class="checkbox highlight">
<label class="checkbox-custom highlight" data-initialize="checkbox">
<input class="sr-only" name="permissions[]" type="checkbox" value="api.nodes.post"> <strong>POST /nodes</strong>
<p class="text-muted"><small>Allows creating a new node on the system.</small><p>
</label>
</div>
<div class="checkbox highlight">
<label class="checkbox-custom highlight" data-initialize="checkbox">
<input class="sr-only" name="permissions[]" type="checkbox" value="api.nodes.view"> <strong>GET /nodes/{id}</strong>
<p class="text-muted"><small>Allows viewing details about a specific node including active services.</small><p>
</label>
</div>
<div class="checkbox highlight">
<label class="checkbox-custom highlight" data-initialize="checkbox">
<input class="sr-only" name="permissions[]" type="checkbox" value="api.nodes.view_allocations"> <strong>GET /nodes/{id}/allocations</strong>
<p class="text-muted"><small>Allows viewing details about a specific node including active services.</small><p>
</label>
</div>
<div class="checkbox highlight">
<label class="checkbox-custom highlight" data-initialize="checkbox">
<input class="sr-only" name="permissions[]" type="checkbox" value="api.nodes.delete"> <strong>DELETE /nodes/{id}</strong>
<p class="text-muted"><small>Allows deleting a node.</small><p>
</label>
</div>
</div>
<div class="col-md-6 fuelux">
<h4>Service Management</h4><hr />
<div class="checkbox highlight">
<label class="checkbox-custom highlight" data-initialize="checkbox">
<input class="sr-only" name="permissions[]" type="checkbox" value="api.services"> <strong>GET /services</strong>
<p class="text-muted"><small>Allows listing of all services configured on the system.</small><p>
</label>
</div>
<div class="checkbox highlight">
<label class="checkbox-custom highlight" data-initialize="checkbox">
<input class="sr-only" name="permissions[]" type="checkbox" value="api.services.view"> <strong>GET /services/{id}</strong>
<p class="text-muted"><small>Allows listing details about each service on the system including service options and variables.</small><p>
</label>
</div>
<h4>Location Management</h4><hr />
<div class="checkbox highlight">
<label class="checkbox-custom highlight" data-initialize="checkbox">
<input class="sr-only" name="permissions[]" type="checkbox" value="api.locations"> <strong>GET /locations</strong>
<p class="text-muted"><small>Allows listing all locations and thier associated nodes.</small><p>
</label>
</div>
</div>
</div>
<div class="well">
<div class="row">
<div class="form-group col-md-12">
<label for="allowed_ips" class="control-label">Allowed IPs</label>
<div>
<textarea name="allowed_ips" class="form-control" rows="5">{{ old('allowed_ips') }}</textarea>
<p class="text-muted"><small>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.</small></p>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
{!! csrf_field() !!}
<input type="submit" class="btn btn-sm btn-primary" value="Create New Key" />
</div>
</div>
</div>
</form>
</div>
<script>
$(document).ready(function () {
$('#sidebar_links').find("a[href='/admin/api']").addClass('active');
$('[data-initialize="checkbox"]').checkbox();
});
</script>
@endsection

View file

@ -1,40 +0,0 @@
{{-- 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.admin')
@section('title')
Administration
@endsection
@section('content')
<div class="col-md-12">
<ul class="breadcrumb">
<li class="active">Admin Control</li>
</ul>
<h3 class="nopad">Pterodactyl Admin Control Panel</h3><hr />
<p>Welcome to the most advanced, lightweight, and user-friendly open source game server control panel.</p>
<p>You are running version <code>{{ config('app.version') }}</code>.</p>
</div>
<script>
$(document).ready(function () {
$('#sidebar_links').find("a[href='/admin']").addClass('active');
});
</script>
@endsection

View file

@ -1,211 +0,0 @@
{{-- 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.admin')
@section('title')
Location List
@endsection
@section('content')
<div class="col-md-12">
<ul class="breadcrumb">
<li><a href="/admin">Admin Control</a></li>
<li class="active">Locations</li>
</ul>
<h3>All Locations</h3><hr />
<table class="table table-bordered table-hover table-striped">
<thead>
<tr>
<th>Location</th>
<th>Description</th>
<th class="text-center">Nodes</th>
<th class="text-center">Servers</th>
<th class="text-center"></th>
<th class="text-center"></th>
</tr>
</thead>
<tbody>
@foreach ($locations as $location)
<tr>
<td><code>{{ $location->short }}</code></td>
<td>{{ $location->long }}</td>
<td class="text-center">{{ $location->a_nodeCount }}</td>
<td class="text-center">{{ $location->a_serverCount }}</td>
<td class="text-center"><a href="#edit"><i class="fa fa-wrench" data-toggle="modal" data-target="#editModal" data-action="edit" data-id="{{ $location->id }}" data-short="{{ $location->short }}" data-long="{{ $location->long }}"></i></a></td>
<td class="text-center"><a href="#delete" class="text-danger" data-action="delete" data-id="{{ $location->id }}"><i class="fa fa-trash-o"></i></a></td>
</tr>
@endforeach
</tbody>
</table>
<div class="row">
<div class="col-md-12 text-center">{!! $locations->render() !!}</div>
</div>
<div class="well">
<div class="row">
<div class="col-md-12">
<button class="btn btn-sm btn-success" data-toggle="modal" data-target="#addModal">Add New Location</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="editModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Editing Location</h4>
</div>
<form action="{{ route('admin.locations') }}" method="POST" id="editLocationForm">
<div class="modal-body">
<div class="form-group">
<label for="location-short" class="control-label">Location Code:</label>
<input type="text" class="form-control" id="location-short">
<p class="text-muted"><small>This should be a short identifier for this location (e.g. <code>ny1</code>). This field is limited to a maximum of 10 characters from the following list: <code>a-zA-Z0-9_-.</code></small></p>
</div>
<div class="form-group">
<label for="location-long" class="control-label">Description:</label>
<input type="text" class="form-control" id="location-long">
<p class="text-muted"><small>This should be a longer description of the location for internal reference.</small></p>
</div>
</div>
<div class="modal-footer">
<input type="hidden" id="location-id">
<button type="button" class="btn btn-sm btn-default" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-sm btn-primary">Edit Location</button>
</div>
</form>
</div>
</div>
</div>
<div class="modal fade" id="addModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Add New Location</h4>
</div>
<form action="{{ route('admin.locations') }}" method="POST" id="addLocationForm">
<div class="modal-body">
<div class="form-group">
<label for="short" class="control-label">Location Code:</label>
<div>
<input type="text" class="form-control" name="short" value="{{ old('short') }}">
<p class="text-muted"><small>This should be a short identifier for this location (e.g. <code>ny1</code>). This field is limited to a maximum of 10 characters from the following list: <code>a-zA-Z0-9_-.</code></small></p>
</div>
</div>
<div class="form-group">
<label for="long" class="control-label">Description:</label>
<div>
<input type="text" class="form-control" name="long" value="{{ old('long') }}">
<p class="text-muted"><small>This should be a longer description of the location for internal reference.</small></p>
</div>
</div>
</div>
<div class="modal-footer">
{!! csrf_field() !!}
<button type="button" class="btn btn-sm btn-default" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-sm btn-primary">Add Location</button>
</div>
</form>
</div>
</div>
</div>
<script>
$(document).ready(function () {
$('#sidebar_links').find("a[href='/admin/locations']").addClass('active');
$('#editModal').on('show.bs.modal', function (event) {
var button = $(event.relatedTarget);
var short = button.data('short');
var long = button.data('long');
var id = button.data('id');
var modal = $(this);
modal.find('#location-id').val(id);
modal.find('#location-short').val(short);
modal.find('#location-long').val(long);
});
$('#editLocationForm').submit(function (event) {
event.preventDefault();
$.ajax({
method: 'PATCH',
url: '{{ route('admin.locations') }}/' + $('#location-id').val(),
headers: {
'X-CSRF-TOKEN': '{{ csrf_token() }}'
},
data: {
short: $('#location-short').val(),
long: $('#location-long').val()
}
}).done(function (data) {
swal({
type: 'success',
title: '',
text: 'Successfully updated location information.',
closeOnConfirm: false,
showLoaderOnConfirm: true
}, function () {
window.location = '{{ route('admin.locations') }}';
});
}).fail(function (jqXHR) {
console.error(jqXHR);
swal({
type: 'error',
title: 'Whoops!',
text: (typeof jqXHR.responseJSON.error !== 'undefined') ? jqXHR.responseJSON.error : 'An error occured while processing this request.'
});
});
});
$('[data-action="delete"]').click(function (event) {
event.preventDefault();
var self = $(this);
swal({
type: 'warning',
title: '',
text: 'Do you really want to delete this location?',
showCancelButton: true,
closeOnConfirm: false,
showLoaderOnConfirm: true
}, function () {
$.ajax({
method: 'DELETE',
url: '{{ route('admin.locations') }}/' + self.data('id'),
headers: {
'X-CSRF-TOKEN': '{{ csrf_token() }}'
}
}).done(function () {
swal({
type: 'success',
title: '',
text: 'Location was successfully deleted.'
});
self.parent().parent().slideUp();
}).fail(function (jqXHR) {
console.error(jqXHR);
swal({
type: 'error',
title: 'Whoops!',
text: (typeof jqXHR.responseJSON.error !== 'undefined') ? jqXHR.responseJSON.error : 'An error occured while processing this request.'
});
});
});
});
});
</script>
@endsection

View file

@ -1,70 +0,0 @@
{{-- 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.admin')
@section('title')
Node List
@endsection
@section('content')
<div class="col-md-12">
<ul class="breadcrumb">
<li><a href="/admin">Admin Control</a></li>
<li class="active">Nodes</li>
</ul>
<h3>All Nodes</h3><hr />
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>Name</th>
<th class="visible-lg">Location</th>
<th>FQDN</th>
<th class="hidden-xs">Memory</th>
<th class="hidden-xs">Disk</th>
<th class="text-center hidden-xs">Servers</th>
<th class="text-center">HTTPS</th>
<th class="text-center">Public</th>
</tr>
</thead>
<tbody>
@foreach ($nodes as $node)
<tr>
<td><a href="/admin/nodes/view/{{ $node->id }}">{{ $node->name }}</td>
<td class="visible-lg">{{ $node->a_locationName }}</td>
<td><code>{{ $node->fqdn }}</code></td>
<td class="hidden-xs">{{ $node->memory }} MB</td>
<td class="hidden-xs">{{ $node->disk }} MB</td>
<td class="text-center hidden-xs">{{ $node->a_serverCount }}</td>
<td class="text-center" style="color:{{ ($node->scheme === 'https') ? '#50af51' : '#d9534f' }}"><i class="fa fa-{{ ($node->scheme === 'https') ? 'lock' : 'unlock' }}"></i></td>
<td class="text-center"><i class="fa fa-{{ ($node->public === 1) ? 'check' : 'times' }}"></i></td>
</tr>
@endforeach
</tbody>
</table>
<div class="row">
<div class="col-md-12 text-center">{!! $nodes->render() !!}</div>
</div>
</div>
<script>
$(document).ready(function () {
$('#sidebar_links').find("a[href='/admin/nodes']").addClass('active');
});
</script>
@endsection

View file

@ -1,187 +0,0 @@
{{-- 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.admin')
@section('title')
Create Node
@endsection
@section('content')
<div class="col-md-12">
<ul class="breadcrumb">
<li><a href="/admin">Admin Control</a></li>
<li><a href="/admin/nodes">Nodes</a></li>
<li class="active">Create New Node</li>
</ul>
<h3>Create New Node</h3><hr />
<form action="/admin/nodes/new" method="POST">
<div class="well">
<div class="row">
<div class="form-group col-md-6">
<label for="name" class="control-label">Node Name</label>
<div>
<input type="text" autocomplete="off" name="name" class="form-control" value="{{ old('name') }}" />
<p class="text-muted"><small>Character limits: <code>a-zA-Z0-9_.-</code> and <code>[Space]</code> (min 1, max 100 characters).</small></p>
</div>
</div>
<div class="form-group col-md-4">
<label for="name" class="control-label">Location</label>
<div>
<select name="location" class="form-control">
@foreach($locations as $location)
<option value="{{ $location->id }}" {{ (old('location') === $location->id) ? 'checked' : '' }}>{{ $location->long }} ({{ $location->short }})</option>
@endforeach
</select>
</div>
</div>
<div class="form-group col-md-2">
<label for="public" class="control-label">Public <sup><a data-toggle="tooltip" data-placement="top" title="Allow automatic allocation to this Node?">?</a></sup></label>
<div>
<input type="radio" name="public" value="1" {{ (old('public') === '1') ? 'checked' : '' }} id="public_1" checked> <label for="public_1" style="padding-left:5px;">Yes</label><br />
<input type="radio" name="public" value="0" {{ (old('public') === '0') ? 'checked' : '' }} id="public_0"> <label for="public_0" style="padding-left:5px;">No</label>
</div>
</div>
</div>
</div>
<div class="well">
<div class="row">
<div class="form-group col-md-6">
<label for="fqdn" class="control-label">Fully Qualified Domain Name</label>
<div>
<input type="text" autocomplete="off" name="fqdn" class="form-control" value="{{ old('fqdn') }}" />
</div>
<p class="text-muted"><small>This <strong>must</strong> be a fully qualified domain name, you may not enter an IP address or a domain that does not exist.
<a tabindex="0" data-toggle="popover" data-trigger="focus" title="Why do I need a FQDN?" data-content="In order to secure communications between your server and this node we use SSL. We cannot generate a SSL certificate for IP Addresses, and as such you will need to provide a FQDN.">Why?</a>
</small></p>
</div>
<div class="form-group col-md-6">
<label for="scheme" class="control-label">Secure Socket Layer</label>
<div class="row" style="padding: 7px 0;">
<div class="col-xs-6">
<input type="radio" name="scheme" value="https" id="scheme_ssl" checked /> <label for="scheme_ssl" style="padding-left: 5px;">Enable HTTPS/SSL</label>
</div>
<div class="col-xs-6">
<input type="radio" name="scheme" value="http" id="scheme_nossl" /> <label for="scheme_nossl" style="padding-left: 5px;">Disable HTTPS/SSL</label>
</div>
</div>
<p class="text-muted"><small>You should always leave SSL enabled for nodes. Disabling SSL could allow a malicious user to intercept traffic between the panel and the daemon potentially exposing sensitive information.</small></p>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="well">
<div class="row">
<div class="form-group col-md-6 col-xs-6">
<label for="memory" class="control-label">Total Memory</label>
<div class="input-group">
<input type="text" name="memory" class="form-control" value="{{ old('memory') }}"/>
<span class="input-group-addon">MB</span>
</div>
</div>
<div class="form-group col-md-6 col-xs-6">
<label for="memory_overallocate" class="control-label">Overallocate</label>
<div class="input-group">
<input type="text" name="memory_overallocate" class="form-control" value="{{ old('memory_overallocate') }}"/>
<span class="input-group-addon">%</span>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<p class="text-muted"><small>Enter the total amount of memory avaliable for new servers. If you would like to allow overallocation of memory enter the percentage that you want to allow. To disable checking for overallocation enter <code>-1</code> into the field. Entering <code>0</code> will prevent creating new servers if it would put the node over the limit.</small></p>
</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="well">
<div class="row">
<div class="form-group col-md-6 col-xs-6">
<label for="disk" class="control-label">Disk Space</label>
<div class="input-group">
<input type="text" name="disk" class="form-control" value="{{ old('disk') }}"/>
<span class="input-group-addon">MB</span>
</div>
</div>
<div class="form-group col-md-6 col-xs-6">
<label for="disk_overallocate" class="control-label">Overallocate</label>
<div class="input-group">
<input type="text" name="disk_overallocate" class="form-control" value="{{ old('disk_overallocate') }}"/>
<span class="input-group-addon">%</span>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<p class="text-muted"><small>Enter the total amount of disk space avaliable for new servers. If you would like to allow overallocation of disk space enter the percentage that you want to allow. To disable checking for overallocation enter <code>-1</code> into the field. Entering <code>0</code> will prevent creating new servers if it would put the node over the limit.</small></p>
</div>
</div>
</div>
</div>
</div>
<div class="well">
<div class="row">
<div class="form-group col-md-6">
<label for="daemonBase" class="control-label">Daemon Server File Location</label>
<div>
<input type="text" name="daemonBase" class="form-control" value="{{ old('daemonBase', '/srv/daemon-data') }}"/>
</div>
<p class="text-muted"><small>The location at which your server files will be stored. Most users do not need to change this.</small></p>
</div>
<div class="form-group col-md-6">
<div class="row">
<div class="form-group col-md-6">
<label for="daemonListen" class="control-label">Daemon Listening Port</label>
<div>
<input type="text" name="daemonListen" class="form-control" value="{{ old('daemonListen', '8080') }}"/>
</div>
</div>
<div class="form-group col-md-6">
<label for="daemonSFTP" class="control-label">Daemon SFTP Port</label>
<div>
<input type="text" name="daemonSFTP" class="form-control" value="{{ old('daemonSFTP', '2022') }}"/>
</div>
</div>
</div>
<p class="text-muted"><small>The daemon runs its own SFTP management container and does not use the SSHd process on the main physical server. <Strong>Do not use the same port that you have assigned for your physcial server's SSH process.</strong></small></p>
</div>
</div>
</div>
<div class="well">
<div class="row">
<div class="col-md-12">
{!! csrf_field() !!}
<input type="submit" class="btn btn-sm btn-primary" value="Create Node" />
</div>
</div>
</div>
</form>
</div>
<script>
$(document).ready(function () {
$('#sidebar_links').find("a[href='/admin/nodes/new']").addClass('active');
$('[data-toggle="popover"]').popover({
placement: 'auto'
});
$('[data-toggle="tooltip"]').tooltip();
});
</script>
@endsection

View file

@ -1,823 +0,0 @@
{{-- 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.admin')
@section('title')
Managing Node: {{ $node->name }}
@endsection
@section('scripts')
@parent
<script src="//cdnjs.cloudflare.com/ajax/libs/highcharts/4.2.1/highcharts.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.7/socket.io.min.js"></script>
<script src="{{ asset('js/bootstrap-notify.min.js') }}"></script>
<script>
$(document).ready(function () {
$.notifyDefaults({
placement: {
from: 'bottom',
align: 'right'
},
newest_on_top: true,
delay: 2000,
animate: {
enter: 'animated fadeInUp',
exit: 'animated fadeOutDown'
}
});
});
</script>
@endsection
@section('content')
<div class="col-md-12">
<ul class="breadcrumb">
<li><a href="/admin">Admin Control</a></li>
<li><a href="/admin/nodes">Nodes</a></li>
<li class="active">{{ $node->name }}</li>
</ul>
<ul class="nav nav-tabs tabs_with_panel" id="config_tabs">
<li class="active"><a href="#tab_about" data-toggle="tab">About</a></li>
<li><a href="#tab_settings" data-toggle="tab">Settings</a></li>
<li><a href="#tab_configuration" data-toggle="tab">Configuration</a></li>
<li><a href="#tab_allocation" data-toggle="tab">Allocation</a></li>
<li><a href="#tab_servers" data-toggle="tab">Servers</a></li>
@if(count($servers) === 0)<li><a href="#tab_delete" data-toggle="tab">Delete</a></li>@endif
</ul>
<div class="tab-content">
<div class="tab-pane active" id="tab_about">
<div class="panel panel-default">
<div class="panel-heading"></div>
<div class="panel-body">
<table class="table table-striped" style="margin-bottom:0;">
<tbody>
<tr>
<td>Total Servers</td>
<td>{{ count($servers) }}</td>
</tr>
<tr>
<td>Memory Allocated</td>
<td><strong class="{{ ($stats->memory < ($node->memory * .8)) ? 'text-success' : 'text-danger' }}">{{ is_numeric($stats->memory) ? $stats->memory : 0 }} MB</strong> of
@if(!is_null($node->memory_overallocate))
<abbr data-toggle="tooltip" data-placement="top" title="Allows up to {{ ($node->memory * (1 + ($node->memory_overallocate / 100)) - $node->memory) }} MB over">{{ $node->memory }}</abbr>
@else
{{ $node->memory }}
@endif
MB
</td>
</tr>
<tr>
<td>Disk Allocated</td>
<td><strong class="{{ ($stats->disk < ($node->disk * .8)) ? 'text-success' : 'text-danger' }}">{{ is_numeric($stats->disk) ? $stats->disk : 0 }} MB</strong> of
@if(!is_null($node->disk_overallocate))
<abbr data-toggle="tooltip" data-placement="top" title="Allows up to {{ ($node->disk * (1 + ($node->disk_overallocate / 100)) - $node->disk) }} MB over">{{ $node->disk }}</abbr>
@else
{{ $node->disk }}
@endif
MB
</td>
</tr>
</tbody>
</table>
</div>
<div class="panel-heading" style="border-top: 1px solid #ddd;"></div>
<div class="panel-body">
<div class="row">
<div class="col-xs-11 text-center" id="chart_memory" style="height:250px;"></div>
<div class="col-xs-11 text-center" id="chart_cpu" style="height:250px;"></div>
<div class="col-xs-11 text-center" id="chart_players" style="height:250px;"></div>
</div>
</div>
</div>
</div>
<div class="tab-pane" id="tab_settings">
<form method="POST" action="/admin/nodes/view/{{ $node->id }}">
<div class="panel panel-default">
<div class="panel-heading"></div>
<div class="panel-body">
<div class="alert alert-warning">
Changing some details below may require that you change the configuration file on the node as well as restart the daemon. They have been marked with <span class="label label-warning"><i class="fa fa-power-off"></i></span> below.
</div>
<div class="row">
<div class="form-group col-md-6">
<label for="name" class="control-label">Node Name</label>
<div>
<input type="text" autocomplete="off" name="name" class="form-control" value="{{ old('name', $node->name) }}" />
<p class="text-muted"><small>Character limits: <code>a-zA-Z0-9_.-</code> and <code>[Space]</code> (min 1, max 100 characters).</small></p>
</div>
</div>
<div class="form-group col-md-4">
<label for="name" class="control-label">Location</label>
<div>
<select name="location" class="form-control">
@foreach($locations as $location)
<option value="{{ $location->id }}" {{ (old('location', $node->location) === $location->id) ? 'checked' : '' }}>{{ $location->long }} ({{ $location->short }})</option>
@endforeach
</select>
</div>
</div>
<div class="form-group col-md-2">
<label for="public" class="control-label">Public <sup><a data-toggle="tooltip" data-placement="top" title="Allow automatic allocation to this Node?">?</a></sup></label>
<div>
<input type="radio" name="public" value="1" {{ (old('public', $node->public) === '1') ? 'checked' : '' }} id="public_1" checked> <label for="public_1" style="padding-left:5px;">Yes</label><br />
<input type="radio" name="public" value="0" {{ (old('public', $node->public) === '0') ? 'checked' : '' }} id="public_0"> <label for="public_0" style="padding-left:5px;">No</label>
</div>
</div>
</div>
<div class="row">
<div class="form-group col-md-6">
<label for="fqdn" class="control-label">Fully Qualified Domain Name</label>
<div>
<input type="text" autocomplete="off" name="fqdn" class="form-control" value="{{ old('fqdn', $node->fqdn) }}" />
</div>
<p class="text-muted"><small>This <strong>must</strong> be a fully qualified domain name, you may not enter an IP address or a domain that does not exist.
<a tabindex="0" data-toggle="popover" data-trigger="focus" title="Why do I need a FQDN?" data-content="In order to secure communications between your server and this node we use SSL. We cannot generate a SSL certificate for IP Addresses, and as such you will need to provide a FQDN.">Why?</a>
</small></p>
</div>
<div class="form-group col-md-6">
<label for="scheme" class="control-label"><span class="label label-warning"><i class="fa fa-power-off"></i></span> Secure Socket Layer</label>
<div class="row" style="padding: 7px 0;">
<div class="col-xs-6">
<input type="radio" name="scheme" value="https" id="scheme_ssl" {{ (old('scheme', $node->scheme) === 'https') ? 'checked' : '' }}/> <label for="scheme_ssl" style="padding-left: 5px;">Enable HTTPS/SSL</label>
</div>
<div class="col-xs-6">
<input type="radio" name="scheme" value="http" id="scheme_nossl" {{ (old('scheme', $node->scheme) === 'http') ? 'checked' : '' }}/> <label for="scheme_nossl" style="padding-left: 5px;">Disable HTTPS/SSL</label>
</div>
</div>
<p class="text-muted"><small>You should always leave SSL enabled for nodes. Disabling SSL could allow a malicious user to intercept traffic between the panel and the daemon potentially exposing sensitive information.</small></p>
</div>
</div>
</div>
<div class="panel-heading" style="border-top: 1px solid #ddd;"></div>
<div class="panel-body">
<div class="row">
<div class="form-group col-md-3 col-xs-6">
<label for="memory" class="control-label">Total Memory</label>
<div class="input-group">
<input type="text" name="memory" class="form-control" value="{{ old('memory', $node->memory) }}"/>
<span class="input-group-addon">MB</span>
</div>
</div>
<div class="form-group col-md-3 col-xs-6">
<label for="memory_overallocate" class="control-label">Overallocate</label>
<div class="input-group">
<input type="text" name="memory_overallocate" class="form-control" value="{{ old('memory_overallocate', $node->memory_overallocate) }}"/>
<span class="input-group-addon">%</span>
</div>
</div>
<div class="form-group col-md-3 col-xs-6">
<label for="disk" class="control-label">Disk Space</label>
<div class="input-group">
<input type="text" name="disk" class="form-control" value="{{ old('disk', $node->disk) }}"/>
<span class="input-group-addon">MB</span>
</div>
</div>
<div class="form-group col-md-3 col-xs-6">
<label for="disk_overallocate" class="control-label">Overallocate</label>
<div class="input-group">
<input type="text" name="disk_overallocate" class="form-control" value="{{ old('disk_overallocate', $node->disk_overallocate) }}"/>
<span class="input-group-addon">%</span>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<p class="text-muted"><small>Enter the total amount of disk space and memory avaliable for new servers. If you would like to allow overallocation of disk space or memory enter the percentage that you want to allow. To disable checking for overallocation enter <code>-1</code> into the field. Entering <code>0</code> will prevent creating new servers if it would put the node over the limit.</small></p>
</div>
</div>
</div>
<div class="panel-heading" style="border-top: 1px solid #ddd;"></div>
<div class="panel-body">
<div class="row">
<div class="col-xs-6">
<div class="row">
<div class="form-group col-md-6">
<label for="daemonListen" class="control-label"><span class="label label-warning"><i class="fa fa-power-off"></i></span> Daemon Port</label>
<div>
<input type="text" name="daemonListen" class="form-control" value="{{ old('daemonListen', $node->daemonListen) }}"/>
</div>
</div>
<div class="form-group col-md-6">
<label for="daemonSFTP" class="control-label"><span class="label label-warning"><i class="fa fa-power-off"></i></span> Daemon SFTP Port</label>
<div>
<input type="text" name="daemonSFTP" class="form-control" value="{{ old('daemonSFTP', $node->daemonSFTP) }}"/>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<p class="text-muted"><small>The daemon runs its own SFTP management container and does not use the SSHd process on the main physical server. <Strong>Do not use the same port that you have assigned for your physcial server's SSH process.</strong></small></p>
</div>
</div>
</div>
<div class="col-xs-6">
<div class="row">
<div class="form-group col-md-12">
<label for="reset_secret" class="control-label"><span class="label label-warning"><i class="fa fa-power-off"></i></span> Reset Daemon Key</label>
<div style="padding: 7px 0;">
<input type="checkbox" name="reset_secret" id="reset_secret" /> Reset Daemon Master Key
</div>
</div>
<div class="col-md-12">
<p class="text-muted"><small>Resetting the daemon master key will void any request coming from the old key. This key is used for all sensitive operations on the daemon including server creation and deletion. We suggest changing this key regularly for security.</small></p>
</div>
</div>
</div>
</div>
</div>
<div class="panel-heading" style="border-top: 1px solid #ddd;"></div>
<div class="panel-body">
<div class="row">
<div class="col-md-12">
{!! csrf_field() !!}
<input type="submit" class="btn btn-sm btn-primary" value="Update Node Information" />
</div>
</div>
</div>
</div>
</form>
</div>
<div class="tab-pane" id="tab_configuration">
<div class="panel panel-default">
<div class="panel-heading"></div>
<div class="panel-body">
<div class="alert alert-info">
Below is the configuration file for your daemon on this node. We recommend <strong>not</strong> simply copy and pasting the code below unless you know what you are doing. You should run the <code>auto-installer</code> or <code>auto-updater</code> to setup the daemon.
</div>
<div class="col-md-12">
<pre><code>{
"web": {
"listen": {{ $node->daemonListen }},
"ssl": {
"enabled": {{ $node->sceheme === 'https' ? 'true' : 'false' }},
"certificate": "/etc/letsencrypt/live/{{ $node->fqdn }}/fullchain.pem",
"key": "/etc/letsencrypt/live/{{ $node->fqdn }}/privkey.pem"
}
},
"docker": {
"socket": "/var/run/docker.sock"
},
"sftp": {
"path": "{{ $node->daemonBase }}",
"port": {{ $node->daemonSFTP }},
"container": "container_id"
},
"logger": {
"path": "logs/",
"src": false,
"level": "info",
"period": "1d",
"count": 3
},
"remote": {
"download": "{{ route('remote.download') }}",
"installed": "{{ route('remote.install') }}"
},
"uploads": {
"maximumSize": 100000000
},
"keys": [
"{{ $node->daemonSecret }}"
]
}</code></pre>
</div>
</div>
</div>
</div>
<div class="tab-pane" id="tab_allocation">
<div class="panel panel-default">
<div class="panel-heading"></div>
<div class="panel-body">
<table class="table table-striped table-bordered table-hover" style="margin-bottom:0;">
<thead>
<td>IP Address</td>
<td>Ports</td>
<td></td>
</thead>
<tbody>
@foreach($allocations as $ip => $ports)
<tr>
<td><span style="cursor:pointer" data-action="delete" data-ip="{{ $ip }}" data-total="{{ count($ports) }}" class="is-ipblock"><i class="fa fa-fw fa-square-o"></i></span> {{ $ip }}</td>
<td>
@foreach($ports as $id => $allocation)
@if (($id % 2) === 0)
@if($allocation->assigned_to === null)
<span style="cursor:pointer" data-action="delete" data-ip="{{ $ip }}" data-port="{{ $allocation->port }}"><i class="fa fa-fw fa-square-o"></i> {{ $allocation->port }} <br /></span>
@else
<i class="fa fa-fw fa-check-square-o"></i> {{ $allocation->port }} <br />
@endif
@endif
@endforeach
</td>
<td>
@foreach($ports as $id => $allocation)
@if (($id % 2) === 1)
@if($allocation->assigned_to === null)
<span style="cursor:pointer" data-action="delete" data-ip="{{ $ip }}" data-port="{{ $allocation->port }}"><i class="fa fa-fw fa-square-o"></i> {{ $allocation->port }} <br /></span>
@else
<i class="fa fa-fw fa-check-square-o"></i> {{ $allocation->port }} <br />
@endif
@endif
@endforeach
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
<div class="panel-heading" style="border-top: 1px solid #ddd;"></div>
<div class="panel-body">
<h4 style="margin-top:0;">Allocate Additional Ports</h4>
<form action="{{ route('admin.nodes.post.allocations', $node->id) }}" method="POST">
<div class="row" id="duplicate">
<div class="col-md-4 fuelux">
<label for="" class="control-label">IP Address</label>
<div class="input-group input-append dropdown combobox allocationComboBox" data-initialize="combobox">
<input type="text" name="allocate_ip[]" class="form-control pillbox_ip" style="border-right:0;">
<div class="input-group-btn">
<button type="button" class="btn btn-sm btn-primary dropdown-toggle" data-toggle="dropdown"><span class="caret"></span></button>
<ul class="dropdown-menu dropdown-menu-right">
@foreach($allocations as $ip => $ports)
<li data-action="alloc_dropdown_val" data-value="{{ $ip }}"><a href="#">{{ $ip }}</a></li>
@endforeach
</ul>
</div>
</div>
</div>
<div class="form-group col-md-7 col-xs-10 fuelux">
<label for="" class="control-label">Ports</label>
<div class="pillbox allocationPillbox" data-initialize="pillbox">
<ul class="clearfix pill-group">
<li class="pillbox-input-wrap btn-group">
<input type="text" class="form-control dropdown-toggle pillbox-add-item" placeholder="add port">
</li>
</ul>
</div>
<input name="allocate_port[]" type="hidden" class="pillboxMain"/>
</div>
<div class="form-group col-md-1 col-xs-2" style="margin-left: -10px;">
<label for="" class="control-label">&nbsp;</label>
<button class="btn btn-danger btn-allocate-delete removeClone disabled"><i class="fa fa-close"></i></button>
</div>
</div>
<div class="row">
<div class="col-md-12">
<hr />
{!! csrf_field() !!}
<input type="submit" class="btn btn-sm btn-primary" value="Add Ports" />
<button class="btn btn-success btn-sm cloneElement">Add More Rows</button>
</div>
</div>
</form>
</div>
</div>
</div>
<div class="tab-pane" id="tab_servers">
<div class="panel panel-default">
<div class="panel-heading"></div>
<div class="panel-body">
<div class="alert alert-info">
The data below is live output from the daemon. CPU usage is displayed relative to the assigned CPU allocation. For example, if a server is assigned <code>10%</code> and the CPU usage below displays <code>90%</code> that means the server is using <code>9%</code> of the total system CPU.
</div>
<table class="table table-striped" style="margin-bottom: 0;">
<thead>
<tr>
<th>Name</th>
<th>Owner</th>
<th>Service</th>
<th class="text-center">Memory</th>
<th class="text-center">Disk</th>
<th class="text-center">CPU</th>
<th class="text-center">Status</th>
</tr>
</thead>
<tbody>
@foreach($servers as $server)
<tr data-server="{{ $server->uuid }}">
<td><a href="/admin/servers/view/{{ $server->id }}">{{ $server->name }}</a></td>
<td><a href="/admin/users/view/{{ $server->owner }}"><code>{{ $server->a_ownerEmail }}</a></a></td>
<td>{{ $server->a_serviceName }}</td>
<td class="text-center"><span data-action="memory">--</span> / {{ $server->memory }} MB</td>
<td class="text-center">{{ $server->disk }} MB</td>
<td class="text-center"><span data-action="cpu" data-cpumax="{{ $server->cpu }}">--</span> %</td>
<td class="text-center" data-action="status">--</td>
</tr>
@endforeach
</tbody>
</table>
<div class="row">
<div class="col-md-12 text-center">{!! $servers->appends(['tab' => 'tab_servers'])->render() !!}</div>
</div>
</div>
</div>
</div>
@if(count($servers) === 0)
<div class="tab-pane" id="tab_delete">
<div class="panel panel-default">
<div class="panel-heading"></div>
<div class="panel-body">
<div class="row">
<div class="col-xs-4 text-center">
<form action="{{ route('admin.nodes.delete', $node->id) }}" method="POST" id="deleteNodeForm">
{!! method_field('DELETE') !!}
{!! csrf_field() !!}
<input type="submit" name="doSomethingForFucksSake" value="Delete Node" class="btn btn-sm btn-danger" />
</form>
</div>
<div class="col-xs-8">
<div class="alert alert-danger" style="margin-bottom:0;">Deleting this node is a permanent action, it cannot be undone.</div>
</div>
</div>
</div>
</div>
</div>
@endif
</div>
<div class="row">
<div class="col-xs-11" id="col11_setter"></div>
</div>
</div>
<script>
$(document).ready(function () {
$('#sidebar_links').find("a[href='/admin/nodes']").addClass('active');
$('[data-toggle="tooltip"]').tooltip();
$('[data-toggle="popover"]').popover({
placement: 'auto'
});
$('#deleteNodeForm').submit(function (event) {
event.preventDefault();
swal({
type: 'warning',
title: 'Are You Sure?',
text: 'This will immediately delete this node, there is no undo.',
showCancelButton: true,
allowOutsideClick: true,
confirmButtonText: 'Delete',
confirmButtonColor: '#d9534f',
}, function () {
event.target.submit();
});
});
$('.cloneElement').on('click', function (event) {
event.preventDefault();
var cloned = $('#duplicate').clone();
var rnd = randomKey(10);
cloned.find('.allocationPillbox').removeClass('allocationPillbox').addClass('allocationPillbox_' + rnd);
cloned.find('.pillboxMain').removeClass('pillboxMain').addClass('pillbox_' + rnd);
cloned.find('.removeClone').removeClass('disabled');
cloned.find('.pillbox_ip').removeClass('pillbox_ip').addClass('pillbox_ip_' + rnd);
cloned.insertAfter('#duplicate');
$('.allocationPillbox_' + rnd).pillbox();
$('.allocationPillbox_' + rnd).on('added.fu.pillbox edited.fu.pillbox removed.fu.pillbox', function pillboxChanged() {
$('.pillbox_' + rnd).val(JSON.stringify($('.allocationPillbox_' + rnd).pillbox('items')));
});
$('.removeClone').on('click', function (event) {
event.preventDefault();
var element = $(this);
element.parent().parent().slideUp(function () {
element.remove();
$('.pillbox_' + rnd).remove();
$('.pillbox_ip_' + rnd).remove();
});
});
})
$('.allocationPillbox').pillbox();
$('.allocationComboBox').combobox();
$('.allocationPillbox').on('added.fu.pillbox edited.fu.pillbox removed.fu.pillbox', function pillboxChanged() {
$('.pillboxMain').val(JSON.stringify($('.allocationPillbox').pillbox('items')));
});
var notifySocketError = false;
var Status = {
0: 'Off',
1: 'On',
2: 'Starting',
3: 'Stopping'
};
// -----------------+
// Charting Methods |
// -----------------+
$(window).resize(function() {
$('#chart_memory').highcharts().setSize($('#col11_setter').width(), 250);
$('#chart_cpu').highcharts().setSize($('#col11_setter').width(), 250);
$('#chart_players').highcharts().setSize($('#col11_setter').width(), 250);
});
$('#chart_memory').highcharts({
chart: {
type: 'area',
animation: Highcharts.svg,
marginRight: 10,
renderTo: 'container',
width: $('#col11_setter').width()
},
colors: [
'#113F8C'
],
credits: {
enabled: false,
},
title: {
text: 'Memory Usage of All Servers',
},
tooltip: {
shared: true,
crosshairs: true,
formatter: function () {
var s = '<b>Memory Usage</b>';
$.each(this.points, function () {
s += '<br/>' + this.series.name + ': ' +
this.y + 'MB';
});
return s;
},
},
xAxis: {
visible: false,
},
yAxis: {
title: {
text: 'Memory Usage (MB)',
},
plotLines: [{
value: 0,
width: 1,
}],
},
plotOptions: {
area: {
fillOpacity: 0.10,
marker: {
enabled: false,
},
},
},
legend: {
enabled: false
},
series: [{
name: 'Total Memory',
data: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
}]
});
$('#chart_cpu').highcharts({
chart: {
type: 'area',
animation: Highcharts.svg,
marginRight: 10,
renderTo: 'container',
width: $('#col11_setter').width()
},
colors: [
'#00A1CB',
],
credits: {
enabled: false,
},
title: {
text: 'CPU Usage of all Servers',
},
tooltip: {
shared: true,
crosshairs: true,
formatter: function () {
var s = '<b>CPU Usage</b>';
$.each(this.points, function () {
s += '<br/>' + this.series.name + ': ' +
this.y + '%';
});
return s;
},
},
xAxis: {
visible: false,
},
yAxis: {
title: {
text: 'CPU Usage (%)',
},
plotLines: [{
value: 0,
width: 1,
}],
},
plotOptions: {
area: {
fillOpacity: 0.10,
marker: {
enabled: false,
},
},
},
legend: {
enabled: true
},
series: [{
name: 'Total CPU',
data: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
}]
});
$('#chart_players').highcharts({
chart: {
type: 'area',
animation: Highcharts.svg,
marginRight: 10,
renderTo: 'container',
width: $('#col11_setter').width()
},
colors: [
'#01A4A4',
],
credits: {
enabled: false,
},
title: {
text: 'Total Players on All Servers',
},
tooltip: {
shared: true,
crosshairs: true,
formatter: function () {
var s = '<b>Total Players</b>';
$.each(this.points, function () {
s += '<br/>' + this.series.name + ': ' + this.y;
});
return s;
},
},
xAxis: {
visible: false,
},
yAxis: {
title: {
text: 'Total Players',
},
plotLines: [{
value: 0,
width: 1,
}],
},
plotOptions: {
area: {
fillOpacity: 0.10,
marker: {
enabled: false,
},
},
},
legend: {
enabled: true
},
series: [{
name: 'Total Players',
data: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
}]
});
// Main Socket Object
var socket = io('{{ $node->scheme }}://{{ $node->fqdn }}:{{ $node->daemonListen }}/stats/', {
'query': 'token={{ $node->daemonSecret }}'
});
// Socket Failed to Connect
socket.io.on('connect_error', function (err) {
if(typeof notifySocketError !== 'object') {
notifySocketError = $.notify({
message: '{!! trans('server.ajax.socket_error') !!}'
}, {
type: 'danger',
delay: 0
});
}
});
// Connected to Socket Successfully
socket.on('connect', function () {
if (notifySocketError !== false) {
notifySocketError.close();
notifySocketError = false;
}
});
socket.on('error', function (err) {
console.error('There was an error while attemping to connect to the websocket: ' + err + '\n\nPlease try loading this page again.');
});
socket.on('live-stats', function (data) {
var CPUChart = $('#chart_cpu').highcharts();
var MemoryChart = $('#chart_memory').highcharts();
var PlayerChart = $('#chart_players').highcharts();
CPUChart.series[0].addPoint(data.stats.cpu, true, true);
MemoryChart.series[0].addPoint(parseInt(data.stats.memory / (1024 * 1024)), true, true);
PlayerChart.series[0].addPoint(data.stats.players, true, true);
$.each(data.servers, function (uuid, info) {
var element = $('tr[data-server="' + uuid + '"]');
element.find('[data-action="status"]').html(Status[info.status]);
if (info.status !== 0) {
var cpuMax = element.find('[data-action="cpu"]').data('cpumax');
var currentCpu = info.proc.cpu.total;
if (cpuMax !== 0) {
currentCpu = parseFloat(((info.proc.cpu.total / cpuMax) * 100).toFixed(2).toString());
}
element.find('[data-action="memory"]').html(parseInt(info.proc.memory.total / (1024 * 1024)));
element.find('[data-action="cpu"]').html(currentCpu);
} else {
element.find('[data-action="memory"]').html('--');
element.find('[data-action="cpu"]').html('--');
}
});
});
$('span[data-action="delete"]').hover(function() {
$(this).find('i').css('color', '#d9534f').removeClass('fa-square-o').addClass('fa-minus-square');
}, function () {
$(this).find('i').css('color', 'inherit').addClass('fa-square-o').removeClass('fa-minus-square');
});
$('span[data-action="delete"]').click(function (event) {
event.preventDefault();
var element = $(this);
var deleteIp = $(this).data('ip');
var deletePort = $(this).data('port');
swal({
title: '',
text: 'Are you sure you want to delete this port?',
type: 'warning',
showCancelButton: true,
allowOutsideClick: true,
closeOnConfirm: false,
confirmButtonText: 'Delete',
confirmButtonColor: '#d9534f',
showLoaderOnConfirm: true
}, function () {
$.ajax({
method: 'DELETE',
url: '{{ route('admin.nodes.view', $node->id) }}/allocation/' + deleteIp + '/' + deletePort,
headers: {
'X-CSRF-TOKEN': '{{ csrf_token() }}'
}
}).done(function (data) {
if (element.hasClass('is-ipblock')) {
var tMatched = 0;
element.parent().parent().find('*').each(function () {
if ($(this).attr('data-port') && $(this).attr('data-ip')) {
$(this).fadeOut();
tMatched++;
}
});
if (tMatched === element.data('total')) {
element.fadeOut();
$('li[data-action="alloc_dropdown_val"][data-value="' + deleteIp + '"]').remove();
element.parent().parent().slideUp().remove();
}
} else {
element.fadeOut();
}
swal({
type: 'success',
title: 'Port Deleted!',
});
}).fail(function (jqXHR) {
console.error(jqXHR);
swal({
title: 'Whoops!',
text: jqXHR.responseJSON.error,
type: 'error'
});
});
});
});
});
</script>
@endsection

View file

@ -1,64 +0,0 @@
{{-- 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.admin')
@section('title')
Server List
@endsection
@section('content')
<div class="col-md-12">
<ul class="breadcrumb">
<li><a href="/admin">Admin Control</a></li>
<li class="active">Servers</li>
</ul>
<h3>All Servers</h3><hr />
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>Server Name</th>
<th>Owner</th>
<th class="hidden-xs">Node</th>
<th>Default Connection</th>
<th class="hidden-xs">SFTP Username</th>
</tr>
</thead>
<tbody>
@foreach ($servers as $server)
<tr class="dynUpdate @if($server->active !== 1)active @endif" id="{{ $server->uuidShort }}">
<td><a href="/admin/servers/view/{{ $server->id }}">{{ $server->name }}</td>
<td><a href="/admin/accounts/view/{{ $server->owner }}">{{ $server->a_ownerEmail }}</a></td>
<td class="hidden-xs"><a href="/admin/nodes/view/{{ $server->node }}">{{ $server->a_nodeName }}</a></td>
<td><code>{{ $server->ip }}:{{ $server->port }}</code></td>
<td class="hidden-xs"><code>{{ $server->username }}</code></td>
</tr>
@endforeach
</tbody>
</table>
<div class="row">
<div class="col-md-12 text-center">{!! $servers->render() !!}</div>
</div>
</div>
<script>
$(document).ready(function () {
$('#sidebar_links').find("a[href='/admin/servers']").addClass('active');
});
</script>
@endsection

View file

@ -1,453 +0,0 @@
{{-- 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.admin')
@section('title')
Create New Server
@endsection
@section('content')
<div class="col-md-12">
<ul class="breadcrumb">
<li><a href="/admin">Admin Control</a></li>
<li><a href="/admin/servers">Servers</a></li>
<li class="active">Create New Server</li>
</ul>
<h3>Create New Server</h3><hr />
<form action="/admin/servers/new" method="POST">
<div class="well">
<div class="row">
<div class="form-group col-md-6">
<label for="name" class="control-label">Server Name</label>
<div>
<input type="text" autocomplete="off" name="name" class="form-control" value="{{ old('name') }}" />
<p class="text-muted"><small><em>Character limits: <code>a-zA-Z0-9_-</code> and <code>[Space]</code> (max 35 characters)</em></small></p>
</div>
</div>
<div class="form-group col-md-6">
<label for="owner" class="control-label">Owner Email</label>
<div>
<input type="text" autocomplete="off" name="owner" class="form-control" value="{{ old('owner', Input::get('email')) }}" />
</div>
</div>
</div>
</div>
<div id="load_settings">
<div class="well">
<div class="row">
<div class="ajax_loading_box" style="display:none;"><i class="fa fa-refresh fa-spin ajax_loading_position"></i></div>
<div class="form-group col-md-6">
<label for="location" class="control-label">Server Location</label>
<div>
<select name="location" id="getLocation" class="form-control">
<option disabled selected> -- Select a Location</option>
@foreach($locations as $location)
<option value="{{ $location->id }}">{{ $location->long }} ({{ $location->short }})</option>
@endforeach
</select>
<p class="text-muted"><small>The location in which this server will be deployed.</small></p>
</div>
</div>
<div class="form-group col-md-6 hidden">
<label for="node" class="control-label">Server Node</label>
<div>
<select name="node" id="getNode" class="form-control">
<option disabled selected> -- Select a Node</option>
</select>
<p class="text-muted"><small>The node which this server will be deployed to.</small></p>
</div>
</div>
</div>
<div class="row">
<div class="form-group col-md-6 hidden">
<label for="ip" class="control-label">Server IP</label>
<div>
<select name="ip" id="getIP" class="form-control">
<option disabled selected> -- Select an IP</option>
</select>
<p class="text-muted"><small>Select the main IP that this server will be listening on. You can assign additional open IPs and ports below.</small></p>
</div>
</div>
<div class="form-group col-md-6 hidden">
<label for="port" class="control-label">Server Port</label>
<div>
<select name="port" id="getPort" class="form-control"></select>
<p class="text-muted"><small>Select the main port that this server will be listening on.</small></p>
</div>
</div>
</div>
</div>
</div>
<div class="well">
<div class="row">
<div class="form-group col-md-4 col-xs-4">
<label for="memory" class="control-label">Memory</label>
<div class="input-group">
<input type="text" name="memory" class="form-control" value="{{ old('memory') }}"/>
<span class="input-group-addon">MB</span>
</div>
</div>
<div class="form-group col-md-4 col-xs-4">
<label for="memory" class="control-label">Swap</label>
<div class="input-group">
<input type="text" name="swap" class="form-control" value="{{ old('swap', 0) }}"/>
<span class="input-group-addon">MB</span>
</div>
</div>
<div class="form-group col-md-4 col-xs-4">
<label for="memory" class="control-label">OOM Killer</label>
<div>
<span class="input-group-addon" style="height:36px;">
<input type="checkbox" name="oom_disabled"/>
</span>
<span class="input-group-addon" style="height:36px;">
Disable OOM Killer
</span>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<p class="text-muted"><small>If you do not want to assign swap space to a server simply put <code>0</code> for the value. We suggest leaving OOM Killer enabled unless you know what you are doing, disabling it could cause your server to hang unexpectedly.</small><p>
</div>
</div>
<div class="row">
<div class="form-group col-md-4 col-xs-4">
<label for="disk" class="control-label">Disk Space</label>
<div class="input-group">
<input type="text" name="disk" class="form-control" value="{{ old('disk') }}"/>
<span class="input-group-addon">MB</span>
</div>
</div>
<div class="form-group col-md-4 col-xs-4">
<label for="cpu" class="control-label">CPU Limit</label>
<div class="input-group">
<input type="text" name="cpu" class="form-control" value="{{ old('cpu', 0) }}"/>
<span class="input-group-addon">%</span>
</div>
</div>
<div class="form-group col-md-4 col-xs-4">
<label for="io" class="control-label">Block I/O</label>
<div class="input-group">
<input type="text" name="io" class="form-control" value="{{ old('io', 500) }}"/>
<span class="input-group-addon">I/O</span>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<p class="text-muted"><small>If you do not want to limit CPU usage set the value to <code>0</code>. To determine a value, take the number <em>physical</em> cores and multiply it by 100. For example, on a quad core system <code>(4 * 100 = 400)</code> there is <code>400%</code> available. To limit a server to using half of a single core, you would set the value to <code>50</code>. To allow a server to use up to two physical cores, set the value to <code>200</code>. BlockIO should be a value between <code>10</code> and <code>1000</code>. Please see <a href="https://docs.docker.com/reference/run/#block-io-bandwidth-blkio-constraint" target="_blank">this documentation</a> for more information about it.</small><p>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6" id="load_services">
<div class="well">
<div class="row">
<div class="ajax_loading_box" style="display:none;"><i class="fa fa-refresh fa-spin ajax_loading_position"></i></div>
<div class="form-group col-md-12">
<label for="service" class="control-label">Service Type</label>
<div>
<select name="service" id="getService" class="form-control">
<option disabled selected> -- Select a Service</option>
@foreach($services as $service)
<option value="{{ $service->id }}">{{ $service->name }}</option>
@endforeach
</select>
<p class="text-muted"><small>Select the type of service that this server will be running.</small></p>
</div>
</div>
<div class="form-group col-md-12 hidden">
<label for="option" class="control-label">Service Option</label>
<div>
<select name="option" id="getOption" class="form-control">
<option disabled selected> -- Select a Service Option</option>
</select>
<p class="text-muted"><small>Select the type of service that this server will be running.</small></p>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="well">
<div class="row">
<div class="form-group col-md-12">
<label for="use_custom_image" class="control-label">Use Custom Docker Image</label>
<div class="input-group">
<span class="input-group-addon">
<input @if(old('use_custom_image') === 'use_custom_image')checked="checked"@endif type="checkbox" name="use_custom_image"/>
</span>
<input type="text" class="form-control" name="custom_image_name" value="{{ old('custom_image_name') }}" disabled />
</div>
<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>
</div>
</div>
</div>
</div>
</div>
<div class="well" id="serviceOptions" style="display:none;">
<div class="row">
<div class="form-group col-md-12">
<h3 class="nopad">Service Setup &amp; Options</h3>
<hr />
<label for="startup" class="control-label">Startup Command</label>
<div class="input-group">
<span class="input-group-addon" id="startupExec"></span>
<input type="text" class="form-control" name="startup" value="{{ old('startup') }}" />
</div>
<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>
</div>
</div>
<div class="row">
<div class="col-md-12">
<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>
</div>
</div>
<div class="row" id="serverVariables"></div>
</div>
<div class="well">
<div class="row">
<div class="col-md-12 text-center">
{!! csrf_field() !!}
<input type="submit" class="btn btn-primary btn-sm" value="Create New Server" />
</div>
</div>
</div>
</form>
</div>
<script>
$(document).ready(function () {
$('#sidebar_links').find("a[href='/admin/servers/new']").addClass('active');
$('input[name="use_custom_image"]').change(function () {
$('input[name="custom_image_name"]').val('').prop('disabled', !($(this).is(':checked')));
});
var nodeData = null;
var currentLocation = null;
var currentNode = null;
var currentService = null;
$('#getLocation').on('change', function (event) {
if ($('#getLocation').val() === '' || $('#getLocation').val() === currentLocation) {
return;
}
currentLocation = $('#getLocation').val();
currentNode = null;
// Hide Existing, and Reset contents
$('#getNode').html('<option disabled selected> -- Select a Node</option>').parent().parent().addClass('hidden');
$('#getIP').html('<option disabled selected> -- Select an IP</option>').parent().parent().addClass('hidden');
$('#getPort').html('').parent().parent().addClass('hidden');
handleLoader('#load_settings', true);
$.ajax({
method: 'POST',
url: '/admin/servers/new/get-nodes',
headers: {
'X-CSRF-TOKEN': '{{ csrf_token() }}'
},
data: {
location: $('#getLocation').val()
}
}).done(function (data) {
//var data = $.parseJSON(data);
$.each(data, function (i, item) {
var isPublic = (item.public !== 1) ? '(Private Node)' : '';
$('#getNode').append('<option value="' + item.id + '">' + item.name + ' ' + isPublic + '</option>');
});
$('#getNode').parent().parent().removeClass('hidden')
}).fail(function (jqXHR) {
alert('An error occured while attempting to load a list of nodes in this location.');
currentLocation = null;
console.error(jqXHR);
}).always(function () {
handleLoader('#load_settings');
})
});
$('#getNode').on('change', function (event) {
if ($('#getNode').val() === '' || $('#getNode').val() === currentNode) {
return;
}
currentNode = $('#getNode').val();
// Hide Existing, and Reset contents
$('#getIP').html('<option disabled selected> -- Select an IP</option>').parent().parent().addClass('hidden');
$('#getPort').html('').parent().parent().addClass('hidden');
handleLoader('#load_settings', true);
$.ajax({
method: 'POST',
url: '/admin/servers/new/get-ips',
headers: {
'X-CSRF-TOKEN': '{{ csrf_token() }}'
},
data: {
node: $('#getNode').val()
}
}).done(function (data) {
nodeData = data;
$.each(data, function (ip, ports) {
$('#getIP').append('<option value="' + ip + '">' + ip + '</option>');
});
$('#getIP').parent().parent().removeClass('hidden');
}).fail(function (jqXHR) {
alert('An error occured while attempting to get IPs and Ports avaliable on this node.');
currentNode = null;
console.error(jqXHR);
}).always(function () {
handleLoader('#load_settings');
});
});
$('#getIP').on('change', function (event) {
if ($('#getIP').val() === '') {
return;
}
$('#getPort').html('');
$.each(nodeData[$('#getIP').val()], function (i, port) {
$('#getPort').append('<option value="' + port +'">' + port + '</option>');
});
$('#getPort').parent().parent().removeClass('hidden');
});
$('#getService').on('change', function (event) {
if ($('#getService').val() === '' || $('#getService').val() === currentService) {
return;
}
currentService = $('#getService').val();
handleLoader('#load_services', true);
$('#serviceOptions').slideUp();
$('#getOption').html('<option disabled selected> -- Select a Service Option</option>');
$.ajax({
method: 'POST',
url: '/admin/servers/new/service-options',
headers: {
'X-CSRF-TOKEN': '{{ csrf_token() }}'
},
data: {
service: $('#getService').val()
}
}).done(function (data) {
$('#startupExec').html(data.exec);
$('input[name="startup"]').val(data.startup);
$.each(data.options, function (i, option) {
$('#getOption').append('<option value="' + option.id + '" data-image="' + option.docker_image + '">' + option.name + '</option>');
});
$('#getOption').parent().parent().removeClass('hidden');
}).fail(function (jqXHR) {
alert('An error occured while attempting to list options for this service.');
currentService = null;
console.error(jqXHR);
}).always(function () {
handleLoader('#load_services');
});
});
$('#getOption').on('change', function (event) {
handleLoader('#load_services', true);
handleLoader('#serviceOptions', true);
$('#serverVariables').html('');
$('input[name="custom_image_name"]').val($(this).find(':selected').data('image'));
$.ajax({
method: 'POST',
url: '/admin/servers/new/service-variables',
headers: {
'X-CSRF-TOKEN': '{{ csrf_token() }}'
},
data: {
option: $('#getOption').val()
}
}).done(function (data) {
$.each(data, function (i, item) {
var isRequired = (item.required === 1) ? '<span class="label label-primary">Required</span> ' : '';
var dataAppend = ' \
<div class="form-group col-md-12">\
<label for="var_ref_' + item.id + '" class="control-label">' + isRequired + item.name + '</label> \
<div>\
<input type="text" autocomplete="off" name="env_' + item.env_variable + '" class="form-control" value="' + item.default_value + '" />\
<p class="text-muted"><small>' + item.description + '</small></p>\
<p class="text-muted"><small>Regex Requirements for Input: <code>' + item.regex + '</code></small></p>\
<p class="text-muted"><small>Access in Startup: <code>@{{' + item.env_variable + '}}</code></small></p>\
</div>\
</div>\
';
$('#serverVariables').append(dataAppend);
});
$('#serviceOptions').slideDown();
}).fail(function (jqXHR) {
console.error(jqXHR);
}).always(function () {
handleLoader('#load_services');
handleLoader('#serviceOptions');
});
});
// Show Loading Animation
function handleLoader (element, show) {
var spinner = $(element).find('.ajax_loading_position');
var popover = $(element).find('.ajax_loading_box');
// Show Animation
if (typeof show !== 'undefined') {
var height = $(element).height();
var width = $(element).width();
var center_height = (height / 2) - 16;
var center_width = (width / 2) - 16;
spinner.css({
'top': center_height,
'left': center_width,
'font-size': '32px'
});
popover.css({
'height': height,
'margin': '-20px 0 0 -5px',
'width': width
}).fadeIn();
} else {
popover.hide();
}
}
});
</script>
@endsection

View file

@ -1,429 +0,0 @@
{{-- 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.admin')
@section('title')
Managing Server: {{ $server->name }} ({{ $server->uuidShort}})
@endsection
@section('content')
<div class="col-md-12">
<ul class="breadcrumb">
<li><a href="/admin">Admin Control</a></li>
<li><a href="/admin/servers">Servers</a></li>
<li class="active">{{ $server->name }} ({{ $server->uuidShort}})</li>
</ul>
@if($server->installed === 0)
<div class="alert alert-warning">
This server is still running through the install process and is not avaliable for use just yet. This message will disappear once this process is completed.
</div>
@elseif($server->installed === 2)
<div class="alert alert-danger">
This server <strong>failed</strong> to install properly. You should delete it and try to create it again or check the daemon logs.
</div>
@endif
<ul class="nav nav-tabs tabs_with_panel" id="config_tabs">
<li class="active"><a href="#tab_about" data-toggle="tab">About</a></li>
@if($server->installed === 1)
<li><a href="#tab_details" data-toggle="tab">Details</a></li>
<li><a href="#tab_build" data-toggle="tab">Build Configuration</a></li>
<li><a href="#tab_startup" data-toggle="tab">Startup</a></li>
@endif
@if($server->installed !== 2)
<li><a href="#tab_manage" data-toggle="tab">Manage</a></li>
@endif
<li><a href="#tab_delete" data-toggle="tab">Delete</a></li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="tab_about">
<div class="panel panel-default">
<div class="panel-heading"></div>
<div class="panel-body">
<table class="table table-striped" style="margin-bottom: 0;">
<tbody>
<tr>
<td>UUID</td>
<td>{{ $server->uuid }}</td>
</tr>
<tr>
<td>Owner</td>
<td><a href="{{ route('admin.accounts.view', $server->owner) }}">{{ $server->a_ownerEmail }}</a></td>
</tr>
<tr>
<td>Location</td>
<td><a href="{{ route('admin.locations') }}">{{ $server->a_locationName }}</a></td>
</tr>
<tr>
<td>Node</td>
<td><a href="{{ route('admin.nodes.view', $server->node) }}">{{ $server->a_nodeName }}</a></td>
</tr>
<tr>
<td>Service</td>
<td>{{ $server->a_serviceName }} :: {{ $server->a_servceOptionName }}</td>
</tr>
<tr>
<td>Name</td>
<td>{{ $server->name }}</td>
</tr>
<tr>
<td>Memory</td>
<td><code>{{ $server->memory }}MB</code> (Swap: {{ $server->swap }}MB) (OOM Killer: <strong>{{ ($server->oom_disabled === 0) ? 'enabled' : 'disabled' }}</strong>)</td>
</tr>
<tr>
<td>Disk Space</td>
<td><code>{{ $server->disk }}MB</code> (Enforced: <strong>no</strong>)</td>
</tr>
<tr>
<td>Block IO Weight</td>
<td><code>{{ $server->io }}</code></td>
</tr>
<tr>
<td>CPU Limit</td>
<td><code>{{ $server->cpu }}%</code></td>
</tr>
<tr>
<td>Default Connection</td>
<td><code>{{ $server->ip }}:{{ $server->port }}</code></td>
</tr>
<tr>
<td>Installed</td>
<td>{{ ($server->installed === 1) ? 'Yes' : 'No' }}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
@if($server->installed === 1)
<div class="tab-pane" id="tab_details">
<div class="panel panel-default">
<div class="panel-heading"></div>
<div class="panel-body">
<form method="POST" action="/admin/servers/view/{{ $server->id }}/details">
<div class="form-group {{ $errors->has('name') ? 'has-error' : '' }}">
<label for="name" class="control-label">Server Name</label>
<div>
<input type="text" name="name" value="{{ old('name', $server->name) }}" class="form-control" />
<p class="text-muted"><small>Character limits: <code>a-zA-Z0-9_-</code> and <code>[Space]</code> (max 35 characters).</small></p>
</div>
</div>
<div class="form-group {{ $errors->has('owner') ? 'has-error' : '' }}">
<label for="name" class="control-label">Server Owner</label>
<div>
<input type="text" name="owner" value="{{ old('owner', $server->a_ownerEmail) }}" class="form-control" />
<p class="text-muted"><small>You can change the owner of this server by changing this field to an email matching another use on this system. If you do this a new daemon security token will be generated automatically.</small></p>
</div>
</div>
<div class="form-group">
<label for="name" class="control-label">Daemon Secret Token</label>
<div>
<input type="text" disabled value="{{ $server->daemonSecret }}" class="form-control" />
<p class="text-muted"><small>This token should not be shared with anyone as it has full control over this server.</small></p>
</div>
</div>
<div class="form-group">
<div>
<input type="checkbox" name="reset_token"/> Yes, Reset Daemon Token
<p class="text-muted"><small>Resetting this token will cause any requests using the old token to fail.</small></p>
</div>
</div>
<div class="form-group">
{!! csrf_field() !!}
<input type="submit" class="btn btn-sm btn-primary" value="Update Details" />
</div>
</form>
</div>
</div>
</div>
<div class="tab-pane" id="tab_build">
<div class="panel panel-default">
<div class="panel-heading"></div>
<div class="panel-body">
<div class="row">
<div class="col-md-12">
<div class="alert alert-info">
After editing any of the options below you will need to restart the server for changes to take effect. If the server is currently off, you just need to start it and the container will be rebuilt with the new settings.
</div>
</div>
</div>
<form action="/admin/servers/view/{{ $server->id }}/build" method="POST">
<div class="row">
<div class="col-md-6 form-group {{ $errors->has('memory') ? 'has-error' : '' }}">
<label for="memory" class="control-label">Allocated Memory</label>
<div class="input-group">
<input type="text" name="memory" class="form-control" value="{{ old('memory', $server->memory) }}"/>
<span class="input-group-addon">MB</span>
</div>
</div>
<div class="col-md-6 form-group {{ $errors->has('swap') ? 'has-error' : '' }}">
<label for="swap" class="control-label">Allocated Swap</label>
<div class="input-group">
<input type="text" name="swap" class="form-control" value="{{ old('swap', $server->swap) }}"/>
<span class="input-group-addon">MB</span>
</div>
<p class="text-muted"><small>Setting this to <code>0</code> will disable swap space on this server.</small></p>
</div>
</div>
<div class="row">
<div class="col-md-6 form-group {{ $errors->has('cpu') ? 'has-error' : '' }}">
<label for="cpu" class="control-label">CPU Limit</label>
<div class="input-group">
<input type="text" name="cpu" class="form-control" value="{{ old('cpu', $server->cpu) }}"/>
<span class="input-group-addon">%</span>
</div>
<p class="text-muted"><small>Each <em>physical</em> core on the system is considered to be <code>100%</code>. Setting this value to <code>0</code> will allow a server to use CPU time without restrictions.</small></p>
</div>
<div class="col-md-6 form-group {{ $errors->has('io') ? 'has-error' : '' }}">
<label for="io" class="control-label">Block IO Proportion</label>
<div>
<input type="text" name="io" class="form-control" value="{{ old('io', $server->io) }}"/>
</div>
<p class="text-muted"><small>Changing this value can have negative effects on all containers on the system. We strongly recommend leaving this value as <code>500</code>.</small></p>
</div>
</div>
<hr />
<div class="row">
<div class="col-md-12">
<div class="alert alert-info">
Additional IPs and Ports can be assigned to this server for use by plugins or other software. The game port is what will show up for the user to use to connect to thier server, and what their configuration files will be forced to use for binding.
</div>
</div>
<div class="col-md-6 form-group">
<label for="default" class="control-label">Game Port</label>
@foreach ($assigned as $assignment)
<div class="input-group" style="margin:5px auto;">
<span class="input-group-addon">
<input type="radio" @if($assignment->ip == $server->ip && $assignment->port == $server->port) checked="checked" @endif name="default" value="{{ $assignment->ip }}:{{ $assignment->port }}"/>
</span>
<input type="text" class="form-control" value="{{ $assignment->ip }}:{{ $assignment->port }}" readonly />
</div>
@endforeach
</div>
<div class="col-md-6">
<div class="row">
<div class="col-md-12 form-group">
<label for="add_additional" class="control-label">Assign Additional Ports</label>
<div>
<select name="add_additional[]" class="form-control" multiple>
@foreach ($unassigned as $assignment)
<option value="{{ $assignment->ip }}:{{ $assignment->port }}">{{ $assignment->ip }}:{{ $assignment->port }}</option>
@endforeach
</select>
</div>
<p class="text-muted"><small>Please note that due to software limitations you cannot assign identical ports on different IPs to the same server. For example, you <strong>cannot</strong> assign both <code>192.168.0.5:25565</code> and <code>192.168.10.5:25565</code> to the same server.</small></p>
</div>
</div>
<div class="row">
<div class="col-md-12 form-group">
<label for="remove_additional" class="control-label">Remove Additional Ports</label>
<div>
<select name="remove_additional[]" class="form-control" multiple>
@foreach ($assigned as $assignment)
<option value="{{ $assignment->ip }}:{{ $assignment->port }}" @if($assignment->ip == $server->ip && $assignment->port == $server->port) disabled @endif>{{ $assignment->ip }}:{{ $assignment->port }}</option>
@endforeach
</select>
</div>
<p class="text-muted"><small>Simply select which ports you would like to remove from the list above. If you want to assign a port on a different IP that is already in use you can select it above and delete it down here.</small></p>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
{!! csrf_field() !!}
<input type="submit" class="btn btn-sm btn-primary" value="Update Build Configuration" />
</div>
</div>
</form>
</div>
</div>
</div>
<div class="tab-pane" id="tab_startup">
<form action="{{ route('admin.servers.post.startup', $server->id) }}" method="POST">
<div class="panel panel-default">
<div class="panel-heading"></div>
<div class="panel-body">
<div class="row">
<div class="col-md-12">
<div class="alert alert-info">Changing any of the values below will require a restart for them to take effect.</div>
<label class="control-label">Server Startup Command</label>
<div class="input-group">
<span class="input-group-addon">{{ $server->a_serviceExecutable }}</span>
<input type="text" class="form-control" name="startup" value="{{ old('startup', $server->startup) }}" />
</div>
<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>
</div>
</div>
</div>
<div class="panel-heading" style="border-top: 1px solid #ddd;"></div>
<div class="panel-body">
<div class="row">
@foreach($startup as $item)
<div class="form-group col-md-6">
<label class="control-label">
@if($item->required === 1)<span class="label label-primary">Required</span> @endif
@if($item->user_viewable === 0)<span data-toggle="tooltip" data-placement="top" title="Not Visible to Users" class="label label-danger"><i class="fa fa-eye-slash"></i></span> @endif
@if($item->user_editable === 0)<span data-toggle="tooltip" data-placement="top" title="Not Editable by Users" class="label label-danger"><i class="fa fa-edit"></i></span> @endif
{{ $item->name }}
</label>
<div>
<input type="text" name="{{ $item->env_variable }}" class="form-control" value="{{ old($item->env_variable, $item->a_serverValue) }}" data-action="matchRegex" data-regex="{{ $item->regex }}" />
</div>
<p class="text-muted"><small>{{ $item->description }}<br />Regex: <code>{{ $item->regex }}</code><br />Access as: <code>&#123;&#123;{{$item->env_variable}}&#125;&#125;</code></small></p>
</div>
@endforeach
</div>
</div>
<div class="panel-heading" style="border-top: 1px solid #ddd;"></div>
<div class="panel-body">
<div class="row">
<div class="col-md-12">
{!! csrf_field() !!}
<input type="submit" class="btn btn-primary btn-sm" value="Update Startup Arguments" />
</div>
</div>
</div>
</div>
</form>
</div>
@endif
@if($server->installed !== 2)
<div class="tab-pane" id="tab_manage">
<div class="panel panel-default">
<div class="panel-heading"></div>
<div class="panel-body">
<div class="row">
<div class="col-md-4 text-center">
<a href="/server/{{ $server->uuidShort }}/" target="_blank">
<button type="submit" class="btn btn-sm btn-primary">Manage Server</button>
</a>
</div>
<div class="col-md-8">
<p>This will take you to the server management page that users normally see and allow you to manage server files as well as check the console and data usage.</p>
</div>
</div>
</div>
<div class="panel-heading" style="border-top: 1px solid #ddd;"></div>
<div class="panel-body">
<div class="row">
<div class="col-md-4 text-center">
<form action="/admin/servers/view/{{ $server->id }}/installed" method="POST">
{!! csrf_field() !!}
<button type="submit" class="btn btn-sm btn-primary">Toggle Install Status</button>
</form>
</div>
<div class="col-md-8">
<p>This will toggle the install status for the server.</p>
<div class="alert alert-warning">If you have just created this server it is ill advised to perform this action as the daemon will contact the panel when finished which could cause the install status to be wrongly set.</div>
</div>
</div>
</div>
@if($server->installed === 1)
<div class="panel-heading" style="border-top: 1px solid #ddd;"></div>
<div class="panel-body">
<div class="row">
<div class="col-md-4 text-center">
<form action="/admin/servers/view/{{ $server->id }}/rebuild" method="POST">
{!! csrf_field() !!}
<button type="submit" class="btn btn-sm btn-primary">Rebuild Server Container</button>
</form>
</div>
<div class="col-md-8">
<p>This will trigger a rebuild of the server container when it next starts up. This is useful if you modified the server configuration file manually, or something just didn't work out correctly.</p>
<div class="alert alert-info">A rebuild will automatically occur whenever you edit build configuration settings for the server.</div>
</div>
</div>
</div>
@endif
</div>
</div>
@endif
<div class="tab-pane" id="tab_delete">
<div class="panel panel-default">
<div class="panel-heading"></div>
<div class="panel-body">
<div class="row">
<div class="col-md-4 text-center">
<form action="/admin/servers/view/{{ $server->id }}" method="POST" data-attr="deleteServer">
{!! csrf_field() !!}
{!! method_field('DELETE') !!}
<button type="submit" class="btn btn-sm btn-danger">Delete Server</button>
</form>
</div>
<div class="col-md-8">
<div class="alert alert-danger">Deleting a server is an irreversible action. <strong>All data will be immediately removed relating to this server.</strong></div>
</div>
</div>
</div>
<div class="panel-heading" style="border-top: 1px solid #ddd;"></div>
<div class="panel-body">
<div class="row">
<div class="col-md-4 text-center">
<form action="/admin/servers/view/{{ $server->id }}/force" method="POST" data-attr="deleteServer">
{!! csrf_field() !!}
{!! method_field('DELETE') !!}
<button type="submit" class="btn btn-sm btn-danger">Force Delete Server</button>
</form>
</div>
<div class="col-md-8">
<div class="alert alert-danger">This is the same as deleting a server, however, if an error is returned by the daemon it is ignored and the server is still removed from the panel.</strong></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function () {
$('[data-toggle="tooltip"]').tooltip();
$('#sidebar_links').find("a[href='/admin/servers']").addClass('active');
$('input[name="default"]').on('change', function (event) {
$('select[name="remove_additional[]"]').find('option:disabled').prop('disabled', false);
$('select[name="remove_additional[]"]').find('option[value="' + $(this).val() + '"]').prop('disabled', true).prop('selected', false);
});
$('[data-action="matchRegex"]').keyup(function (event) {
if (!$(this).data('regex')) return;
var input = $(this).val();
var regex = new RegExp(escapeRegExp($(this).data('regex')));
console.log(regex);
if (!regex.test(input)) {
$(this).parent().parent().removeClass('has-success').addClass('has-error');
} else {
$(this).parent().parent().removeClass('has-error').addClass('has-success');
}
});
$('form[data-attr="deleteServer"]').submit(function (event) {
event.preventDefault();
swal({
title: '',
type: 'warning',
text: 'Are you sure that you want to delete this server? There is no going back, all data will immediately be removed.',
showCancelButton: true,
confirmButtonText: 'Delete',
confirmButtonColor: '#d9534f',
closeOnConfirm: false
}, function () {
event.target.submit();
});
});
});
</script>
@endsection

View file

@ -1,97 +0,0 @@
{{-- 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.admin')
@section('title')
Administration
@endsection
@section('content')
<div class="col-md-12">
<ul class="breadcrumb">
<li><a href="/admin">Admin Control</a></li>
<li class="active">Settings</li>
</ul>
<h3 class="nopad">Panel Settings</h3><hr />
<form action="{{ route('admin.settings') }}" method="POST">
<div class="row">
<div class="form-group col-md-6">
<label class="control-label">Company Name:</label>
<div>
<input type="text" class="form-control" name="company" value="{{ old('company', Settings::get('company')) }}" />
<p class="text-muted"><small>This is the name that is used throughout the panel and in emails sent to clients.</small></p>
</div>
</div>
<div class="form-group col-md-6">
<label class="control-label">Default Language:</label>
<div>
<select name="default_language" class="form-control">
<option value="de" @if(Settings::get('default_language') === 'de')selected @endif>Deutsch</option>
<option value="en" @if(Settings::get('default_language') === 'en')selected @endif>English</option>
<option value="es" @if(Settings::get('default_language') === 'es')selected @endif>Espa&ntilde;ol</option>
<option value="fr" @if(Settings::get('default_language') === 'fr')selected @endif>Fran&ccedil;ais</option>
<option value="it" @if(Settings::get('default_language') === 'it')selected @endif>Italiano</option>
<option value="pl" @if(Settings::get('default_language') === 'pl')selected @endif>Polski</option>
<option value="pt" @if(Settings::get('default_language') === 'pt')selected @endif>Portugu&ecirc;s</option>
<option value="ru" @if(Settings::get('default_language') === 'ru')selected @endif>&#1088;&#1091;&#1089;&#1089;&#1082;&#1080;&#1081;</option>
<option value="se" @if(Settings::get('default_language') === 'se')selected @endif>Svenska</option>
<option value="zh" @if(Settings::get('default_language') === 'zh')selected @endif>&#20013;&#22269;&#30340;的</option>
</select>
<p class="text-muted"><small>This is the default language that all clients will use unless they manually change it.</small></p>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="alert alert-info">In order to modify your SMTP settings for sending mail you will need to edit the <code>.env</code> file in this project's root folder.</div>
</div>
</div>
<div class="row">
<div class="form-group col-md-6">
<label class="control-label">Send Emails From:</label>
<div>
<input type="text" class="form-control" name="email_from" value="{{ old('email_from', Settings::get('email_from', env('MAIL_FROM', 'you@example.com'))) }}" />
<p class="text-muted"><small>The email address that panel emails will be sent from. Note that some SMTP services require this to match for a given API key.</small></p>
</div>
</div>
<div class="form-group col-md-6">
<label class="control-label">Email Sender Name:</label>
<div>
<input type="text" class="form-control" name="email_sender_name" value="{{ old('email_sender_name', Settings::get('email_sender_name', env('MAIL_FROM_NAME', 'Pterodactyl Panel'))) }}" />
<p class="text-muted"><small>The name that emails will appear to come from.</small></p>
</div>
</div>
</div>
<div class="well well-sm">
<div class="row">
<div class="col-md-12">
{!! csrf_field() !!}
<input type="submit" class="btn btn-sm btn-primary" value="Modify Settings">
</div>
</div>
</div>
</form>
</div>
<script>
$(document).ready(function () {
$('#sidebar_links').find("a[href='/admin/settings']").addClass('active');
});
</script>
@endsection