Miglioramento procedura configurazione iniziale

This commit is contained in:
Dasc3er 2021-07-07 14:50:55 +02:00
parent a12b21ad51
commit 3f46f85751
8 changed files with 278 additions and 94 deletions

View File

@ -6,8 +6,16 @@ use Illuminate\Http\Request;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\DB;
/**
* Controller dedicato alla gestione della configurazione di base del gestionale per la piattaforma in utilizzo.
*/
class ConfigurationController extends Controller
{
/**
* Verifica se la configurazione del gestionale per la piattaforma corrente è stata completata correttamente.
*
* @return bool
*/
public static function isConfigured()
{
try {
@ -52,6 +60,11 @@ class ConfigurationController extends Controller
return view('config.configuration', $args);
}
/**
* Metodo per la gestione della validazione della configurazione indicata.
*
* @return \Illuminate\Http\JsonResponse
*/
public function test(Request $request)
{
$requirements = $this->checkConnection($request);
@ -70,9 +83,37 @@ class ConfigurationController extends Controller
$state = 2;
}
return $state;
return response()->json(['test' => $state]);
}
/**
* Metodo per l'esecuzione della pulizia automatica per la cache della configurazione.
*/
public function cache(Request $request)
{
// Refresh della cache sulla configurazione
Artisan::call('config:cache');
return redirect(route('configuration'));
}
/**
* Metodo per la gestione del messaggio di errore alla scrittura fisica della configurazione.
*/
public function write(Request $request)
{
$params = $request->old();
$env = $this->buildEnvFrom($params);
return view('config.configuration-writing', [
'config' => $env,
'params' => $params,
]);
}
/**
* Metodo indirizzato al salvataggio della configurazione.
*/
public function save(Request $request)
{
// Controllo sullo stato della connessione
@ -81,39 +122,19 @@ class ConfigurationController extends Controller
return redirect(route('configuration'));
}
// Individuazione parametri aggiuntivi
$decimals = $request->input('decimal_separator');
$thousands = $request->input('thousand_separator');
$decimals = $decimals == 'dot' ? '.' : ',';
$thousands = $thousands == 'dot' ? '.' : $thousands;
$thousands = $thousands == 'comma' ? ',' : $thousands;
$env = $this->buildEnvFrom($request->all());
// Completamento configurazione
$pairs = [
'APP_LOCALE' => $request->input('language'),
// Scrittura fisica della configurazione
$path = base_path('.env');
$result = file_put_contents($path, $env);
'DB_HOST' => $request->input('host'),
'DB_USERNAME' => $request->input('username'),
'DB_PASSWORD' => $request->input('password'),
'DB_DATABASE' => $request->input('database_name'),
/*
'|timestamp|' => post('timestamp_format'),
'|date|' => post('date_format'),
'|time|' => post('time_format'),
'|decimals|' => $decimals,
'|thousands|' => $thousands,
*/
];
foreach ($pairs as $key => $value) {
$this->updateEnv($key, $value);
// Redirect in caso di fallimento
if ($result === false) {
return redirect(route('configuration-write'))
->withInput();
}
// Refresh della cache sulla configurazione
Artisan::call('config:clear');
return redirect(route('configuration'));
return redirect(route('configuration-cache'));
}
/**
@ -184,10 +205,75 @@ class ConfigurationController extends Controller
return $requirements;
}
protected function updateEnv($key, $value)
/**
* Definisce i nuovi contenuti per il file .env sulla base dell'input utente.
*
* @param array $params
*/
protected function buildEnvFrom($params): string
{
$path = base_path('.env');
/*
// Individuazione parametri aggiuntivi
$decimals = $params['decimal_separator'];
$thousands = $params['thousand_separator'];
$decimals = $decimals == 'dot' ? '.' : ',';
$thousands = $thousands == 'dot' ? '.' : $thousands;
$thousands = $thousands == 'comma' ? ',' : $thousands;
*/
// Completamento configurazione
$pairs = [
'APP_LOCALE' => $params['language'],
'DB_HOST' => $params['host'],
'DB_USERNAME' => $params['username'],
'DB_PASSWORD' => $params['password'],
'DB_DATABASE' => $params['database_name'],
/*
'|timestamp|' => post('timestamp_format'),
'|date|' => post('date_format'),
'|time|' => post('time_format'),
'|decimals|' => $decimals,
'|thousands|' => $thousands,
*/
];
$env = $this->buildEnv($pairs);
return $env;
}
/**
* Definisce i nuovi contenuti per il file .env sulla base della configurazione indicata.
*
* @param $config
*/
protected function buildEnv($config): string
{
$file = base_path('.env');
$content = file_get_contents($file);
foreach ($config as $key => $value) {
$content = str_replace(
"$key=".$this->getCurrentEnvValue($key),
"$key=".$value,
$content
);
}
return $content;
}
/**
* Restituisce il valore (fisico) corrente per una chiave del file .env.
*
* @param $key
*
* @return mixed|string
*/
protected function getCurrentEnvValue($key)
{
if (is_bool(env($key))) {
$old = env($key) ? 'true' : 'false';
} elseif (env($key) === null) {
@ -196,12 +282,6 @@ class ConfigurationController extends Controller
$old = env($key);
}
if (file_exists($path)) {
file_put_contents($path, str_replace(
"$key=".$old,
"$key=".$value,
file_get_contents($path)
));
}
return $old;
}
}

View File

@ -3,6 +3,7 @@
namespace App\Http\Controllers;
use App\Models\User;
use Filter;
use Illuminate\Database\QueryException;
use Illuminate\Http\Request;
use Models\Group;
@ -101,6 +102,7 @@ class InitializationController extends Controller
$idtipoanagrafica = $database->fetchOne("SELECT idtipoanagrafica AS id FROM an_tipianagrafiche WHERE descrizione='Azienda'")['id'];
$readonly_tipo = true;
$skip_permissions = true;
$api_request = false;
include base_path('legacy').'/modules/anagrafiche/add.php';
$anagrafica = ob_get_clean();
@ -166,8 +168,14 @@ class InitializationController extends Controller
{
$dbo = $database = database();
$this->filter->set('post', 'op', 'add');
// Inizializzazione forzata per Filter
Filter::getPOST();
Filter::set('post', 'op', 'add');
// Salvataggio anagrafica tramite modulo Anagrafiche
$id_module = module('Anagrafiche')['id'];
$skip_permissions = true;
$api_request = false;
include base_path('legacy').'/modules/anagrafiche/actions.php';
// Logo stampe

View File

@ -97,7 +97,7 @@ class EnsureConfiguration
*/
protected function checkConfiguration($route)
{
$configuration_paths = ['configuration', 'configuration-save', 'configuration-test'];
$configuration_paths = ['configuration', 'configuration-save', 'configuration-write', 'configuration-test'];
$configuration_completed = ConfigurationController::isConfigured();
if ($configuration_completed) {

View File

@ -0,0 +1,49 @@
@extends('layouts.guest')
@section('title', tr('Errore di configurazione'))
@section('box_class', 'box-danger')
@section('box_header')
<h3 class="box-title">{{ tr('Permessi di scrittura mancanti') }}</h3>
@endsection
@section('content')
<p>{!! tr('Sembra che non ci siano i permessi di scrittura sul file _FILE_', ['_FILE_' => '<b>.env</b>']) !!}. {{ tr('Per completare la configurazione del gestionale, è necessario inserire provare nuovamente attraverso il pulsante "Riprova" oppure inserire manualmente il contenuto sottostante nel file indicato') }}.</p>
<form action="{{ route('configuration-save') }}" method="post">
@foreach($params as $key => $value)
<input type="hidden" name="{{ $key }}" value="{{ $value }}">
@endforeach
<a class="btn btn-warning" href="{{ route('login') }}">
<i class="fa fa-arrow-left"></i> {{ tr('Torna indietro') }}
</a>
<button type="submit" class="btn btn-info pull-right">
<i class="fa fa-repeat"></i> {{ tr('Riprova') }}
</button>
</form>
<hr>
<div class="box box-outline box-default collapsable collapsed-box">
<div class="box-header with-border">
<h4 class="box-title"><a class="clickable" data-widget="collapse">{{ tr('Creazione manuale') }}</a></h4>
<div class="box-tools pull-right">
<button type="button" class="btn btn-box-tool" data-widget="collapse">
<i class="fa fa-plus"></i>
</button>
</div>
</div>
<div class="box-body">
<p>{!! tr('Inserire il seguente testo nel file _FILE_', ['_FILE_' => '<b>.env</b>']) !!}.</p>
<p><strong>{{ tr('Attenzione!') }}</strong> {!! tr('A seguito del completamento manuale della configurazione, è necessario utilizzare il pulsante dedicato "Completa inserimento" oppure eseguire da riga di comando _CMD_', ['_CMD_' => "<kbd>php artisan config:cache</kbd>"]) !!}.</p>
<a class="btn btn-success" href="{{ route('configuration-cache') }}">
<i class="fa fa-download"></i> {{ tr('Completa inserimento') }}
</a>
<pre class="text-left">{{ $config }}</pre>
</div>
</div>
@endsection

View File

@ -96,11 +96,13 @@
<div class="col-md-4">
<span>*<small><small>{{ tr('Campi obbligatori') }}</small></small></span>
</div>
<div class="col-md-4 text-right">
<button type="button" id="test" class="btn btn-warning btn-block">
<i class="fa fa-file-text"></i> {{ tr('Testa il database') }}
</button>
</div>
<div class="col-md-4 text-right">
<button type="submit" id="install" class="btn btn-success btn-block">
<i class="fa fa-check"></i> {{ tr('Installa') }}
@ -148,47 +150,67 @@
});
$("#install").on("click", function() {
if ($(this).closest("form").parsley().validate()) {
let restore = buttonLoading("#install");
$("#config-form").submit();
testConnection(this).then(function (response){
const result = response['test'];
//buttonRestore("#install", restore);
}
if (result !== 0 && result !== 1){
$("#config-form").submit();
}
});
});
$("#test").on("click", function() {
if ($(this).closest("form").parsley().validate()) {
let restore = buttonLoading("#test");
$("#install").prop('disabled', true);
testConnection(this).then(function (response) {
const result = response['test'];
$(this).closest("form").ajaxSubmit({
url: globals.configuration.test_url,
data: {
test: 1,
},
type: "get",
success: function (data) {
data = parseFloat(data.trim());
buttonRestore("#test", restore);
$("#install").prop('disabled', false);
if (data === 0) {
swal(globals.configuration.translations.error, globals.configuration.translations.errorMessage, "error");
} else if (data === 1) {
swal(globals.configuration.translations.permissions, globals.configuration.translations.permissionsMessage, "error");
} else {
swal(globals.configuration.translations.success, globals.configuration.translations.successMessage, "success");
}
},
error: function (xhr, error, thrown) {
ajaxError(xhr, error, thrown);
}
});
}
if (result === 0) {
swal(globals.configuration.translations.error, globals.configuration.translations.errorMessage, "error");
} else if (result === 1) {
swal(globals.configuration.translations.permissions, globals.configuration.translations.permissionsMessage, "error");
} else {
swal(globals.configuration.translations.success, globals.configuration.translations.successMessage, "success");
}
});
});
});
/**
*
* @param button
* @returns Promise
*/
function testConnection(button) {
const form = $(button).closest("form");
// Validazione form
if (!form.parsley().validate()) {
return new Promise((resolve, reject) => {
reject()
});
}
// Impostazione dei button utilizzati
let restore = buttonLoading(button);
$("#install").prop('disabled', true);
// Lettura della configurazione inserita
let data = getInputsData(form);
// Tentativo di validazione della configurazione
return $.ajax({
url: globals.configuration.test_url,
type: "GET",
data: data,
dataType: "JSON",
success: function (response) {
// Ripristino button utilizzati
buttonRestore(button, restore);
$("#install").prop('disabled', false);
},
error: ajaxError
});
}
function languageFlag(item) {
if (!item.id) {
return item.text;

View File

@ -64,7 +64,7 @@
</div>
<div class="box-body">
{!! azienda_form !!}
{!! $azienda_form !!}
<div class="box box-outline box-success collapsed-box">
<div class="box-header with-border">

View File

@ -25,11 +25,13 @@
<div id="update-info" class="hidden">
<div class="progress">
<div class="progress-bar bg-warning progress-bar-striped progress-bar-animated" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width:0%">
<div class="progress-bar progress-bar-warning bg-warning progress-bar-striped progress-bar-animated" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width:0%">
<span>0%</span>
</div>
</div>
<hr>
<div class="box box-outline box-info text-center collapsed-box">
<div class="box-header with-border">
<h3 class="box-title"><a class="clickable" data-widget="collapse">{{ tr('Log') }}</a></h3>
@ -40,16 +42,21 @@
<div class="box-body info text-left"></div>
</div>
</div>
<div id="result"></div>
<!-- Eventuale fallimento durante l'aggiornamento -->
<div class="alert alert-danger hidden" id="error">
<i class="fa fa-times"></i> <strong id="error-type"></strong>: <span id="error-message"></span>
<br>
<button type="button" class="btn btn-warning" onclick="location.reload()">
<i class="fa fa-refresh"></i> {{ tr('Riprova') }}
</button>
</div>
<div style="display: none;" id="completed">
<p><strong>{{ tr('Aggiornamento completato') }}</strong> <i class="fa fa-smile-o"></i></p>
@if($installing)
<!-- Istruzioni per la prima installazione -->
<p class="text-danger">{{ tr("E' fortemente consigliato rimuovere i permessi di scrittura dal file _FILE_", ['_FILE_' => '<b>config.inc.php</b>']) }}.</p>
@endif
<a class="btn btn-success btn-block" href="{{ route('login') }}">
<i class="fa fa-check"></i> {{ tr('Continua') }}
</a>
@ -95,9 +102,20 @@
if (!response['completed']) {
executeUpdate();
} else {
$("#completed").show();
}
},
error: ajaxError
error: function(xhr, error, thrown){
ajaxError(xhr, error, thrown);
// Messaggio informativo fisso
if (xhr.responseJSON){
$("#error").removeClass("hidden");
$("#error-type").html(xhr.responseJSON.exception);
$("#error-message").html(xhr.responseJSON.message);
}
}
});
}
@ -114,10 +132,6 @@
function setPercent(percent) {
$("#update-info .progress-bar").width(percent + "%");
$("#update-info .progress-bar span").text(percent + "%");
if (percent >= 100) {
$("#completed").show();
}
}
function addVersion(version) {

View File

@ -30,7 +30,7 @@ require __DIR__.'/auth.php';
Route::get('/', function () {
$module = auth()->user()->getFirstAvailableModule();
return redirect('controller.php?id_module='.$module->id);
return redirect('legacy/controller.php?id_module='.$module->id);
})
->middleware(['auth']);
@ -39,12 +39,23 @@ Route::get('/requirements', [RequirementsController::class, 'index'])
->name('requirements');
// Sezione di configurazione
Route::get('/config', [ConfigurationController::class, 'index'])
->name('configuration');
Route::get('/config-test', [ConfigurationController::class, 'test'])
->name('configuration-test');
Route::post('/config', [ConfigurationController::class, 'save'])
->name('configuration-save');
Route::prefix('config')
->group(function () {
Route::get('/', [ConfigurationController::class, 'index'])
->name('configuration');
Route::get('/test', [ConfigurationController::class, 'test'])
->name('configuration-test');
Route::get('/cache', [ConfigurationController::class, 'cache'])
->name('configuration-cache');
Route::get('/write', [ConfigurationController::class, 'write'])
->name('configuration-write');
Route::post('/save', [ConfigurationController::class, 'save'])
->name('configuration-save');
});
// Installazione aggiornamenti del gestionale
Route::get('/update', [UpdateController::class, 'index'])