Introduzione pagine di base

Aggiornamento pagine di segnalazione bug, informazioni utente e log degli accessi.
This commit is contained in:
Dasc3er 2021-02-20 17:37:57 +01:00
parent 14a09053a1
commit 04ff4439ed
9 changed files with 348 additions and 112 deletions

View File

@ -2,107 +2,34 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use Backup;
use Illuminate\Http\Request;
use Modules\Emails\Account;
use Notifications\EmailNotification;
use Update;
class InfoController extends Controller class InfoController extends Controller
{ {
/** @var int Lunghezza minima della password */
public static $min_length_password = 8;
protected static $bugEmail = 'info@openstamanager.com'; protected static $bugEmail = 'info@openstamanager.com';
public function info() public function info()
{ {
return view('info.info'); return view('info');
}
public function logs()
{
$user = auth()->getUser();
$query = 'SELECT * FROM `zz_logs`';
if (!Auth::admin()) {
$query .= ' WHERE `id_utente`='.prepare($user['id']);
}
$query .= ' ORDER BY `created_at` DESC LIMIT 0, 100';
$results = $this->database->fetchArray($query);
$status = Auth::getStatus();
$data = [];
foreach ($status as $state) {
$color = 'warning';
$color = $state['code'] == $status['success']['code'] ? 'success' : $color;
$color = $state['code'] == $status['failed']['code'] ? 'danger' : $color;
$data[$state['code']] = [
'message' => $state['message'],
'color' => $color,
];
}
$args['status'] = $data;
$args['results'] = $results;
$response = $this->twig->render($response, '@resources/info/logs.twig', $args);
return $response;
}
public function user()
{
$user = auth()->user();
$tokens = $user->getApiTokens();
$token = $tokens[0]['token'];
$api = BASEURL.'/api/?token='.$token;
$args['api'] = $api;
$args['token'] = $token;
$args['sync_link'] = $api.'&resource=sync';
$response = $this->twig->render($response, '@resources/user/user.twig', $args);
return $response;
}
public function password()
{
$args['min_length_password'] = self::$min_length_password;
$response = $this->twig->render($response, '@resources/user/password.twig', $args);
return $response;
}
public function passwordPost()
{
$user = auth()->getUser();
$password = post('password');
$user->password = $password;
$user->save();
flash()->info(tr('Password aggiornata!'));
$response = $response->withRedirect($this->router->urlFor('user'));
return $response;
} }
public function bug() public function bug()
{ {
$args['mail'] = Account::where('predefined', true)->first(); $account = Account::where('predefined', true)->first();
$args['bug_email'] = self::$bugEmail;
$response = $this->twig->render($response, '@resources/info/bug.twig', $args); return view('bug', [
'mail' => $account,
return $response; 'bug_email' => self::$bugEmail,
]);
} }
public function bugSend() public function send(Request $request)
{ {
$user = auth()->getUser(); $user = auth()->user();
$bug_email = self::$bugEmail; $bug_email = self::$bugEmail;
// Preparazione email // Preparazione email
@ -112,16 +39,17 @@ class InfoController extends Controller
$mail->AddAddress($bug_email); $mail->AddAddress($bug_email);
// Oggetto // Oggetto
$mail->Subject = 'Segnalazione bug OSM '.$args['version']; $mail->Subject = 'Segnalazione bug OSM '.Update::getVersion();
// Aggiunta dei file di log (facoltativo) // Aggiunta dei file di log (facoltativo)
if (!empty(post('log')) && file_exists(DOCROOT.'/logs/error.log')) { $log_file = base_path('/logs/error.log');
$mail->AddAttachment(DOCROOT.'/logs/error.log'); if (!empty($request->input('log')) && file_exists($log_file)) {
$mail->AddAttachment($log_file);
} }
// Aggiunta della copia del database (facoltativo) // Aggiunta della copia del database (facoltativo)
if (!empty(post('sql'))) { if (!empty($request->input('sql'))) {
$backup_file = DOCROOT.'/Backup OSM '.date('Y-m-d').' '.date('H_i_s').'.sql'; $backup_file = base_path('backup/Backup OSM '.date('Y-m-d').' '.date('H_i_s').'.sql');
Backup::database($backup_file); Backup::database($backup_file);
$mail->AddAttachment($backup_file); $mail->AddAttachment($backup_file);
@ -133,17 +61,17 @@ class InfoController extends Controller
$infos = [ $infos = [
'Utente' => $user['username'], 'Utente' => $user['username'],
'IP' => get_client_ip(), 'IP' => get_client_ip(),
'Versione OSM' => $args['version'].' ('.($args['revision'] ? $args['revision'] : 'In sviluppo').')', 'Versione OSM' => Update::getVersion().' ('.(Update::getRevision() ?: tr('In sviluppo')).')',
'PHP' => phpversion(), 'PHP' => phpversion(),
]; ];
// Aggiunta delle informazioni sul sistema (facoltativo) // Aggiunta delle informazioni sul sistema (facoltativo)
if (!empty(post('info'))) { if (!empty($request->input('info'))) {
$infos['Sistema'] = $_SERVER['HTTP_USER_AGENT'].' - '.getOS(); $infos['Sistema'] = $_SERVER['HTTP_USER_AGENT'].' - '.getOS();
} }
// Completamento del body // Completamento del body
$body = post('body').'<hr>'; $body = $request->input('body').'<hr>';
foreach ($infos as $key => $value) { foreach ($infos as $key => $value) {
$body .= '<p>'.$key.': '.$value.'</p>'; $body .= '<p>'.$key.': '.$value.'</p>';
} }
@ -160,12 +88,10 @@ class InfoController extends Controller
} }
// Rimozione del dump del database // Rimozione del dump del database
if (!empty(post('sql'))) { if (!empty($request->input('sql'))) {
delete($backup_file); delete($backup_file);
} }
$response = $response->withRedirect($this->router->urlFor('bug')); return redirect(route('bug'));
return $response;
} }
} }

View File

@ -0,0 +1,67 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Models\Log;
class UserController extends Controller
{
/** @var int Lunghezza minima della password */
public static $min_length_password = 8;
public function index()
{
$user = auth()->user();
$tokens = $user->getApiTokens();
$token = $tokens[0]['token'];
$api = base_url().'/api/?token='.$token;
$args = [
'user' => $user,
'api' => $api,
'token' => $token,
'sync_link' => $api.'&resource=sync',
];
return view('user.info', $args);
}
public function password()
{
$args['min_length_password'] = self::$min_length_password;
return view('user.password', $args);
}
public function save(Request $request)
{
$user = auth()->user();
$password = $request->input('password');
$user->password = $password;
$user->save();
flash()->info(tr('Password aggiornata!'));
return redirect(route('user-info'));
}
public function logs()
{
$user = auth()->user();
$logs = Log::orderBy('created_at')->limit(100);
if (!$user->isAdmin()) {
$logs = $logs->where('id_utente', '=', $user->id);
}
$logs = $logs->get();
return view('user.logs', [
'logs' => $logs,
]);
}
}

2
legacy

@ -1 +1 @@
Subproject commit 0b21ecf084f81a8c4178fce4808c4026d937d12c Subproject commit a4c7c2c560cc34d7d48b81158db3795650968c8b

View File

@ -0,0 +1,107 @@
@extends('layouts.app')
@section('title', tr("Bug"))
@section('content')
@if(empty($mail['from_address']) or empty($mail['server']))
<div class="alert alert-warning">
<i class="fa fa-warning"></i>
<b>{{ tr('Attenzione!') }}</b> {{ tr('Per utilizzare correttamente il modulo di segnalazione bug devi configurare alcuni parametri riguardanti le impostazione delle email') }}.
{!! module('Account email')->link($mail['id'], tr('Correggi account'), null, 'class="btn btn-warning pull-right"') !!}
<div class="clearfix"></div>
</div>
@endif
<div class="box box-outline box-primary">
<div class="box-header">
<h3 class="box-title"><i class="fa fa-bug"></i> {{ tr('Segnalazione bug') }}</h3>
</div>
<div class="box-body">
<form method="post" action="{{ route('bug-send') }}">
@csrf
<table class="table table-bordered table-condensed table-striped table-hover">
<tr>
<th width="150" class="text-right">{{ tr('Da') }}:</th>
<td>{{ $mail['from_address'] }}</td>
</tr>
<!-- A -->
<tr>
<th class="text-right">{{ tr('A') }}:</th>
<td>{{ $bug_email }}</td>
</tr>
<!-- Versione -->
<tr>
<th class="text-right">{{ tr('Versione OSM') }}:</th>
<td>{{ Update::getVersion() }} ({{ Update::getRevision() ?: tr('In sviluppo') }})</td>
</tr>
</table>
<div class="row">
<div class="col-md-4">
{[ "type": "checkbox", "label": "{{ tr('Allega file di log') }}", "name": "log", "value": "1" ]}
</div>
<div class="col-md-4">
{[ "type": "checkbox", "label": "{{ tr('Allega copia del database') }}", "name": "sql" ]}
</div>
<div class="col-md-4">
{[ "type": "checkbox", "label": "{{ tr('Allega informazioni sul PC') }}", "name": "info", "value": "1" ]}
</div>
</div>
<div class="clearfix"></div>
<br>
{[ "type": "ckeditor", "label": "{{ tr('Descrizione del bug') }}", "name": "body" ]}
<!-- PULSANTI -->
<div class="row">
<div class="col-md-12 text-right">
<button type="submit" class="btn btn-primary" id="send" disabled>
<i class="fa fa-envelope"></i> {{ tr('Invia segnalazione') }}
</button>
</div>
</div>
</form>
</div>
</div>
<script>
$(document).ready(function() {
init();
// Impostazione del messaggio
var html = `<p>{{ tr('Se hai riscontrato un bug ricordati di specificare') }}:</p>
<ul>
<li>{{ tr('Modulo esatto (o pagina relativa) in cui questi si è verificato') }};</li>
<li>{{ tr('Dopo quali specifiche operazioni hai notato il malfunzionamento') }}.</li>
</ul>
<p>{{ tr("Assicurati inoltre di controllare che il checkbox relativo ai file di log sia contrassegnato, oppure riporta qui l'errore visualizzato") }}.</p>
<p>{{ tr('Ti ringraziamo per il tuo contributo') }},<br>
{{ tr('Lo staff di OSM') }}</p>`;
let editor = input("body");
var firstFocus = true;
/*
editor.set(html);
editor.on("key", function() {
setTimeout(function(){
$("#send").prop("disabled", editor.get() === "");
}, 10);
});
editor.on("focus", function() {
if (firstFocus) {
editor.set("");
firstFocus = 0;
}
});*/
});
</script>
@endsection

View File

@ -5,6 +5,8 @@
$module = \Models\Module::getCurrent(); $module = \Models\Module::getCurrent();
$id_module = $module ? $module->id : null; $id_module = $module ? $module->id : null;
$id_record = isset($id_record) ? $id_record : null; $id_record = isset($id_record) ? $id_record : null;
$user = auth()->user();
@endphp @endphp
@section('js') @section('js')
@ -70,7 +72,7 @@
'hookMultiple': "{{ tr('Hai _NUM_ notifiche') }}", 'hookMultiple': "{{ tr('Hai _NUM_ notifiche') }}",
'hookSingle': "{{ tr('Hai 1 notifica') }}", 'hookSingle': "{{ tr('Hai 1 notifica') }}",
'hookNone': "{{ tr('Nessuna notifica') }}", 'hookNone': "{{ tr('Nessuna notifica') }}",
'singleCalendar': {{ tr("E' presente un solo periodo!") }}", 'singleCalendar': "{{ tr("E' presente un solo periodo!") }}",
ajax: { ajax: {
"missing": { "missing": {
"title": "{{ tr('Errore') }}", "title": "{{ tr('Errore') }}",
@ -239,17 +241,17 @@
<aside class="main-sidebar"><!-- sidebar-dark-primary elevation-4 --> <aside class="main-sidebar"><!-- sidebar-dark-primary elevation-4 -->
<section class="sidebar"> <section class="sidebar">
<!-- Sidebar user panel --> <!-- Sidebar user panel -->
<a href="{{ route('user') }}" class="user-panel text-center info" style="height: 60px"> <a href="{{ route('user-info') }}" class="user-panel text-center info" style="height: 60px">
<div class="text-center mt-2"> <div class="text-center mt-2">
@if (auth()->user()->photo) @if ($user->photo)
<img src="{{ base_url() }}{{ auth()->user()->photo }}" class="profile-user-img img-fluid img-circle" alt="{{ auth()->user()->username }}" /> <img src="{{ base_url() }}{{ $user->photo }}" class="profile-user-img img-fluid img-circle" alt="{{ $user->username }}" />
@else @else
<i class="fa fa-user-circle-o fa-5x"></i> <i class="fa fa-user-circle-o fa-5x"></i>
@endif @endif
</div> </div>
<h3 class="profile-username text-center" style="width: 100%; padding-top: 10px;"> <h3 class="profile-username text-center" style="width: 100%; padding-top: 10px;">
{{ auth()->user()->username }} {{ $user->username }}
</h3> </h3>
<p class="text-center" id="datetime"></p> <p class="text-center" id="datetime"></p>
</a> </a>

View File

@ -0,0 +1,95 @@
@extends('layouts.app')
@section('title', tr("Utenza corrente"))
@section('content')
<div class="box box-widget widget-user">
<div class="widget-user-header bg-primary">
<h3 class="widget-user-username">{{ $user->username }}</h3>
<h5 class="widget-user-desc">{{ $user->gruppo }}</h5>
</div>
<div class="widget-user-image">
@if($user->photo)
<img src="{{ $user->photo }}" class="img-circle" alt="{{ $user->username }}" />
@else
<i class="fa fa-user-circle-o fa-4x pull-left"></i>
@endif
</div>
<div class="box-footer">
<div class="row">
<div class="col-sm-4 border-right">
<div class="description-block">
<h5 class="description-header">{{ tr('Anagrafica associata') }}</h5>
<span class="description-text">{{ $user->anagrafica['ragione_sociale'] ? $user->anagrafica['ragione_sociale'] : tr('Nessuna') }}</span>
</div>
</div>
<div class="col-sm-4 border-right">
<div class="description-block">
<a class="btn btn-info btn-block tip" data-href="" data-toggle="modal" data-title="{{ tr('Cambia foto utente') }}">
<i class="fa fa-picture-o"></i> {{ tr('Cambia foto utente') }}
</a>
</div>
</div>
<div class="col-sm-4 border-right">
<div class="description-block">
<a class="btn btn-warning btn-block tip" data-href="{{ route('user-password') }}" data-toggle="modal" data-title="{{ tr('Cambia password') }}">
<i class="fa fa-unlock-alt"></i> {{ tr('Cambia password') }}
</a>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="box box-outline box-success">
<div class="box-header">
<h3 class="box-title">{{ tr('API') }}</h3>
</div>
<div class="box-body">
<p>{{ tr("Puoi utilizzare il token per accedere all'API del gestionale e per visualizzare il calendario su applicazioni esterne") }}.</p>
<p>{{ tr('Token personale') }}: <b>{{ $token }}</b></p>
<p>{{ tr("URL dell'API") }}: <a href="{{ $api }}" target="_blank">{{ $api }}</a></p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="box box-outline box-info">
<div class="box-header">
<h3 class="box-title">{{ tr('Calendario interventi') }}</h3>
</div>
<div class="box-body">
<p>{{ tr("Per accedere al calendario eventi attraverso l'API, accedi al seguente link") }}:</p>
<a href="{{ $sync_link }}" target="_blank">{{ $sync_link }}</a>
<hr>
<h5>{{ tr('Configurazione') }}</h5>
<p>{!! tr("Per _ANDROID_, scarica un'applicazione dedicata dal _LINK_", [
'_ANDROID_' => '<b>'.tr('Android').'</b>',
'_LINK_' => '<a href="https://play.google.com/store/search?q=iCalSync&c=apps" target="_blank">'.tr('Play Store').'</a>',
]) !!}.</p>
<p>{!! tr("Per _APPLE_, puoi configurare un nuovo calendario dall'app standard del calendario", [
'_APPLE_' => '<b>'.tr('Apple').'</b>',
]) !!}.</p>
<p>{!! tr('Per _PC_ e altri client di posta, considerare le relative funzionalità o eventuali plugin', [
'_PC_' => '<b>'.tr('PC').'</b>',
]) !!}.</p>
</div>
</div>
</div>
</div>
<script>$(document).ready(init)</script>
@endsection

View File

@ -0,0 +1,36 @@
@extends('layouts.app')
@section('title', tr("Accessi"))
@section('content')
<div class="box box-outline box-primary">
<div class="box-header">
<h3 class="box-title"><i class="fa fa-book"></i> {{ tr('Ultimi 100 accessi') }}</h3>
</div>
<div class="box-body table-responsive">
<table class="datatables table table-hover">
<thead>
<tr>
<th>{{ tr('Username') }}</th>
<th>{{ tr('Data') }}</th>
<th>{{ tr('Stato') }}</th>
<th>{{ tr('Indirizzo IP') }}</th>
</tr>
</thead>
<tbody>
@foreach($logs as $log)
<tr class="bg-{{ $log->color }}">
<td>{{ $log->username }}</td>
<td>{{ timestampFormat($log->created_at) }}</td>
<td><span class="label label-{{ $log->color }}">{{ $log->message }}</span></td>
<td>{{ $log->ip }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
@endsection

View File

@ -4,6 +4,7 @@ use App\Http\Controllers\ConfigurationController;
use App\Http\Controllers\InfoController; use App\Http\Controllers\InfoController;
use App\Http\Controllers\InitializationController; use App\Http\Controllers\InitializationController;
use App\Http\Controllers\Test; use App\Http\Controllers\Test;
use App\Http\Controllers\UserController;
use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Route;
/* /*
@ -91,18 +92,20 @@ Route::get('/info', [InfoController::class, 'info'])
->name('info'); ->name('info');
// Segnalazione bug // Segnalazione bug
Route::get('/bug', [Test::class, 'index']) Route::get('/bug', [InfoController::class, 'bug'])
->name('bug'); ->name('bug');
Route::post('/bug', [Test::class, 'index']); Route::post('/bug', [InfoController::class, 'send'])
->name('bug-send');
// Log di accesso // Log di accesso
Route::get('/logs', [Test::class, 'index']) Route::get('/logs', [UserController::class, 'logs'])
->name('logs'); ->name('logs');
// Informazioni sull'utente // Informazioni sull'utente
Route::get('/user', [Test::class, 'index']) Route::get('/user', [UserController::class, 'index'])
->name('user'); ->name('user-info');
Route::get('/password', [Test::class, 'index']) Route::get('/password', [UserController::class, 'password'])
->name('user-password'); ->name('user-password');
Route::post('/password', [Test::class, 'index']); Route::post('/password', [UserController::class, 'save'])
->name('user-password-save');;