Add Admin Configuration Editor

This commit is contained in:
Daniel Supernault 2019-06-20 20:01:16 -06:00
parent cd7ecd11a6
commit 94bef4c74c
No known key found for this signature in database
GPG key ID: 0DEF1C662C9033F7
4 changed files with 179 additions and 65 deletions

View file

@ -11,41 +11,79 @@ use App\Util\Lexer\PrettyNumber;
trait AdminSettingsController trait AdminSettingsController
{ {
public function settings(Request $request) public function settings(Request $request)
{ {
return view('admin.settings.home'); return view('admin.settings.home');
} }
public function settingsBackups(Request $request) public function settingsBackups(Request $request)
{ {
$path = storage_path('app/'.config('app.name')); $path = storage_path('app/'.config('app.name'));
$files = is_dir($path) ? new \DirectoryIterator($path) : []; $files = is_dir($path) ? new \DirectoryIterator($path) : [];
return view('admin.settings.backups', compact('files')); return view('admin.settings.backups', compact('files'));
} }
public function settingsConfig(Request $request) public function settingsConfig(Request $request)
{ {
$editor = []; $editor = config('pixelfed.admin.env_editor');
$config = file_get_contents(base_path('.env')); $config = !$editor ? false : file_get_contents(base_path('.env'));
return view('admin.settings.config', compact('editor', 'config')); $backup = !$editor ? false : file_get_contents(base_path('.env.backup'));
} return view('admin.settings.config', compact('editor', 'config', 'backup'));
}
public function settingsMaintenance(Request $request) public function settingsConfigStore(Request $request)
{ {
return view('admin.settings.maintenance'); if(config('pixelfed.admin.env_editor') !== true) {
} abort(400);
}
$res = $request->input('res');
public function settingsStorage(Request $request) $old = file_get_contents(app()->environmentFilePath());
{ if(empty($old) || $old != $res) {
$storage = []; $oldFile = fopen(app()->environmentFilePath().'.backup', 'w');
return view('admin.settings.storage', compact('storage')); fwrite($oldFile, $old);
} fclose($oldFile);
}
$file = fopen(app()->environmentFilePath(), 'w');
fwrite($file, $res);
fclose($file);
Artisan::call('config:cache');
return ['msg' => 200];
}
public function settingsConfigRestore(Request $request)
{
if(config('pixelfed.admin.env_editor') !== true) {
abort(400);
}
$res = file_get_contents(app()->environmentFilePath().'.backup');
if(empty($res)) {
abort(400, 'No backup exists.');
}
$file = fopen(app()->environmentFilePath(), 'w');
fwrite($file, $res);
fclose($file);
Artisan::call('config:cache');
return ['msg' => 200];
}
public function settingsMaintenance(Request $request)
{
return view('admin.settings.maintenance');
}
public function settingsStorage(Request $request)
{
$storage = [];
return view('admin.settings.storage', compact('storage'));
}
public function settingsFeatures(Request $request)
{
return view('admin.settings.features');
}
public function settingsFeatures(Request $request)
{
return view('admin.settings.features');
}
public function settingsHomeStore(Request $request) public function settingsHomeStore(Request $request)
{ {
$this->validate($request, [ $this->validate($request, [
@ -57,7 +95,7 @@ trait AdminSettingsController
public function settingsPages(Request $request) public function settingsPages(Request $request)
{ {
$pages = Page::orderByDesc('updated_at')->paginate(10); $pages = Page::orderByDesc('updated_at')->paginate(10);
return view('admin.pages.home', compact('pages')); return view('admin.pages.home', compact('pages'));
} }
@ -66,35 +104,35 @@ trait AdminSettingsController
return view('admin.pages.edit'); return view('admin.pages.edit');
} }
public function settingsSystem(Request $request) public function settingsSystem(Request $request)
{ {
$sys = [ $sys = [
'pixelfed' => config('pixelfed.version'), 'pixelfed' => config('pixelfed.version'),
'php' => phpversion(), 'php' => phpversion(),
'laravel' => app()->version(), 'laravel' => app()->version(),
]; ];
switch (config('database.default')) { switch (config('database.default')) {
case 'pgsql': case 'pgsql':
$sys['database'] = [ $sys['database'] = [
'name' => 'Postgres', 'name' => 'Postgres',
'version' => explode(' ', DB::select(DB::raw('select version();'))[0]->version)[1] 'version' => explode(' ', DB::select(DB::raw('select version();'))[0]->version)[1]
]; ];
break; break;
case 'mysql': case 'mysql':
$sys['database'] = [ $sys['database'] = [
'name' => 'MySQL', 'name' => 'MySQL',
'version' => DB::select( DB::raw("select version()") )[0]->{'version()'} 'version' => DB::select( DB::raw("select version()") )[0]->{'version()'}
]; ];
break; break;
default: default:
$sys['database'] = [ $sys['database'] = [
'name' => 'Unknown', 'name' => 'Unknown',
'version' => '?' 'version' => '?'
]; ];
break; break;
} }
return view('admin.settings.system', compact('sys')); return view('admin.settings.system', compact('sys'));
} }
} }

View file

@ -274,4 +274,8 @@ return [
'sanitizer' => [ 'sanitizer' => [
'restrict_html_types' => env('RESTRICT_HTML_TYPES', true) 'restrict_html_types' => env('RESTRICT_HTML_TYPES', true)
], ],
'admin' => [
'env_editor' => env('ADMIN_ENV_EDITOR', false)
],
]; ];

View file

@ -5,10 +5,80 @@
@section('section') @section('section')
<div class="title"> <div class="title">
<h3 class="font-weight-bold">Configuration Settings</h3> <h3 class="font-weight-bold">Configuration Settings</h3>
@if($editor == false)
<hr>
<div class="card bg-light shadow-none rounded-0">
<div class="card-body text-center py-5">
<p class="lead text-muted font-weight-bold">Configuration Editor is disabled</p>
<p class="mb-0">To enable it, add <code>ADMIN_ENV_EDITOR=true</code> to <code>.env</code><br>then run <code>php artisan config:cache</code></p>
</div>
</div>
@else
<p class="lead">Edit configuration settings</p> <p class="lead">Edit configuration settings</p>
<p class="alert alert-warning">
<strong>Warning:</strong> Editing the .env file may cause issues if you change the wrong setting or set the wrong value.
</p>
</div> </div>
<hr> <hr>
<p class="alert alert-warning"> <div>
<strong>Feature Unavailable:</strong> This feature will be released in a future version. <div id="editor">{{$config}}</div>
</p> <hr>
@endsection <div class="d-flex justify-content-between px-3">
<button class="btn btn-outline-secondary font-weight-bold py-1 btn-restore">Restore backup .env</button>
<button class="btn btn-primary font-weight-bold py-1 btn-save">Save</button>
</div>
</div>
@endif
@endsection
@if($editor == true)
@push('scripts')
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.4/ace.js"></script>
<script>
let editor = ace.edit("editor");
editor.session.setUseWrapMode(true);
editor.setTheme("ace/theme/monokai");
editor.session.setMode("ace/mode/javascript");
$('.btn-restore').on('click', function(e) {
e.preventDefault();
let confirm = window.confirm('Are you sure you want to restore your backup .env?');
if(!confirm) {
swal('Cancelled', 'You have cancelled the .env backup restore.', 'warning');
return;
}
axios.post('/i/admin/settings/config/restore', {
}).then(res => {
window.location.href = window.location.href;
});
})
$('.btn-save').on('click', function(e) {
e.preventDefault();
let confirm = window.confirm('Are you sure you want to overwrite your current .env?');
if(!confirm) {
swal('Cancelled', 'You have cancelled the .env update.', 'warning');
return;
}
axios.post('/i/admin/settings/config', {
res: editor.getValue()
}).then(res => {
window.location.href = window.location.href;
});
})
</script>
@endpush
@push('styles')
<style type="text/css" media="screen">
#editor {
display: block;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 100%;
min-height: 400px;
}
</style>
@endpush
@endif

View file

@ -23,6 +23,8 @@ Route::domain(config('pixelfed.domain.admin'))->prefix('i/admin')->group(functio
Route::get('settings', 'AdminController@settings')->name('admin.settings'); Route::get('settings', 'AdminController@settings')->name('admin.settings');
Route::post('settings', 'AdminController@settingsHomeStore'); Route::post('settings', 'AdminController@settingsHomeStore');
Route::get('settings/config', 'AdminController@settingsConfig')->name('admin.settings.config'); Route::get('settings/config', 'AdminController@settingsConfig')->name('admin.settings.config');
Route::post('settings/config', 'AdminController@settingsConfigStore');
Route::post('settings/config/restore', 'AdminController@settingsConfigRestore');
Route::get('settings/features', 'AdminController@settingsFeatures')->name('admin.settings.features'); Route::get('settings/features', 'AdminController@settingsFeatures')->name('admin.settings.features');
Route::get('settings/pages', 'AdminController@settingsPages')->name('admin.settings.pages'); Route::get('settings/pages', 'AdminController@settingsPages')->name('admin.settings.pages');
Route::get('settings/pages/edit', 'PageController@edit')->name('admin.settings.pages.edit'); Route::get('settings/pages/edit', 'PageController@edit')->name('admin.settings.pages.edit');