Supporto alle foto utente

Miglioramento dei campi di tipo password.
This commit is contained in:
Thomas Zilio 2019-07-18 18:33:56 +02:00
parent 92070a0354
commit d09a001783
25 changed files with 671 additions and 323 deletions

View File

@ -198,6 +198,15 @@ gulp.task('colorpicker', function () {
.pipe(gulp.dest(config.production + '/' + config.paths.images + '/bootstrap-colorpicker'));
});
gulp.task('password-strength', function () {
gulp.src([
config.main.bowerDirectory + '/pwstrength-bootstrap/dist/*.js',
])
.pipe(concat('password.min.js'))
.pipe(minifyJS())
.pipe(gulp.dest(config.production + '/password-strength'));
});
gulp.task('chartjs', function () {
gulp.src([
config.main.bowerDirectory + '/chart.js/dist/Chart.min.js',
@ -368,6 +377,7 @@ gulp.task('bower', ['clean'], function () {
gulp.task('other', ['clean'], function () {
gulp.start('ckeditor');
gulp.start('colorpicker');
gulp.start('password-strength');
gulp.start('i18n');
gulp.start('pdfjs');

View File

@ -275,7 +275,7 @@ if (Auth::check()) {
<i class="fa fa-info"></i>
</a></li>
<li><a href="'.$rootdir.'/index.php?op=logout" class="bg-red tip" title="'.tr('Esci').'">
<li><a href="'.$rootdir.'/index.php?op=logout" onclick="sessionStorage.clear()" class="bg-red tip" title="'.tr('Esci').'">
<i class="fa fa-power-off"></i>
</a></li>
</ul>
@ -289,18 +289,27 @@ if (Auth::check()) {
<section class="sidebar">
<!-- Sidebar user panel -->
<div class="user-panel text-center info">
<div class="user-panel text-center info" style="height: 60px">
<div class="info">
<p><a href="'.$rootdir.'/modules/utenti/info.php">
<i class="fa fa-user"></i>
'.$user['username'].'
</a></p>
<p id="datetime"></p>
</div>
<div class="image">
<img src="'.$paths['img'].'/logo.png" class="img-circle img-responsive" alt="'.tr('OpenSTAManager').'" />
</div>
<a class="image" href="'.$rootdir.'/modules/utenti/info.php">';
$user_photo = $user->photo;
if ($user_photo) {
echo '
<img src="'.$user_photo.'" class="img-responsive" alt="'.$user['username'].'" />';
} else {
echo '
<i class="fa fa-user fa-3x pull-left" alt="'.tr('OpenSTAManager').'"></i>';
}
echo '
</a>
</div>
<!-- search form -->

View File

@ -3,8 +3,8 @@
include_once __DIR__.'/../../core.php';
use Modules\Anagrafiche\Anagrafica;
$name = get('name');
$value = get('value');
$name = filter('name');
$value = filter('value');
switch ($name) {
case 'codice':

View File

@ -4,8 +4,8 @@ include_once __DIR__.'/../../core.php';
use Modules\Articoli\Articolo;
$name = get('name');
$value = get('value');
$name = filter('name');
$value = filter('value');
switch ($name) {
case 'codice':

View File

@ -9,10 +9,12 @@ function submodules($list, $depth = 0)
$result = '';
foreach ($list as $sub) {
$locked = in_array($sub['name'], ['Utenti e permessi', 'Stato dei servizi']);
// STATO
if (!empty($sub['enabled'])) {
$text = tr('Abilitato');
$text .= ($sub['id'] != $id_module) ? '. '.tr('Clicca per disabilitarlo').'...' : '';
$text .= !$locked ? '. '.tr('Clicca per disabilitarlo').'...' : '';
$stato = '<i class="fa fa-cog fa-spin text-success tip" title="'.$text.'"></i>';
} else {
$stato = '<i class="fa fa-cog text-warning tip" title="'.tr('Non abilitato').'"></i>';
@ -20,7 +22,7 @@ function submodules($list, $depth = 0)
}
// Possibilità di disabilitare o abilitare i moduli tranne quello degli aggiornamenti
if ($sub['id'] != $id_module) {
if (!$locked) {
if ($sub['enabled']) {
$stato = "<a href='javascript:;' onclick=\"if( confirm('".tr('Disabilitare questo modulo?')."') ){ $.post( '".ROOTDIR.'/actions.php?id_module='.$id_module."', { op: 'disable', id: '".$sub['id']."' }, function(response){ location.href='".ROOTDIR.'/controller.php?id_module='.$id_module."'; }); }\">".$stato."</a>\n";
} else {

View File

@ -2,9 +2,25 @@
include_once __DIR__.'/../../core.php';
use Models\User;
$id_utente = filter('id_utente');
switch (filter('op')) {
// Aggiunta nuovo gruppo
case 'add':
$nome = filter('nome');
// Verifico che questo username non sia già stato usato
if ($dbo->fetchNum('SELECT nome FROM zz_groups WHERE nome='.prepare($nome)) == 0) {
$dbo->query('INSERT INTO zz_groups( nome, editable ) VALUES('.prepare($nome).', 1)');
flash()->info(tr('Gruppo aggiunto!'));
$id_record = $dbo->lastInsertedID();
} else {
flash()->error(tr('Gruppo già esistente!'));
}
break;
// Abilita utente
case 'enable':
if ($dbo->query('UPDATE zz_users SET enabled=1 WHERE id='.prepare($id_utente))) {
@ -20,114 +36,60 @@ switch (filter('op')) {
break;
// Cambio di password e username dell'utente
case 'change_pwd':
$id_utente = filter('id_utente');
$min_length = filter('min_length');
$min_length_username = filter('min_length_username');
$password = filter('password1');
$password_rep = filter('password2');
$email = filter('email');
// Verifico che la password sia di almeno x caratteri
if (strlen($password) < $min_length) {
flash()->error(tr('La password deve essere lunga almeno _MIN_ caratteri!', [
'_MIN_' => $min_length,
]));
} elseif ($password != $password_rep) {
flash()->error(tr('Le password non coincidono'));
} else {
$idanagrafica = filter('idanag');
$dbo->query('UPDATE zz_users SET password='.prepare(Auth::hashPassword($password)).', idanagrafica='.prepare($idanagrafica).', email='.prepare($email).' WHERE id='.prepare($id_utente));
$dbo->query('DELETE FROM zz_user_sedi WHERE id_user='.prepare($id_utente));
foreach (post('idsede') as $i => $idsede) {
$dbo->query('INSERT INTO `zz_user_sedi` (`id_user`,`idsede`) VALUES ('.prepare($id_utente).', '.prepare($idsede).')');
}
flash()->info(tr('Password aggiornata!'));
}
case 'update_user':
$username = filter('username');
$email = filter('email');
$password = filter('password');
// Se ho modificato l'username, verifico che questo non sia già stato usato
$rs = $dbo->fetchArray('SELECT username FROM zz_users WHERE id='.prepare($id_utente));
$id_utente = filter('id_utente');
if (!empty($id_utente)) {
$utente = User::find($id_utente);
if ($rs[0]['username'] != $username) {
$n = $dbo->fetchNum('SELECT id FROM zz_users WHERE username='.prepare($username));
if ($n == 0) {
$dbo->query('UPDATE zz_users SET username='.prepare($username).' WHERE id='.prepare($id_utente));
flash()->info(tr('Username aggiornato!'));
} else {
flash()->error(tr('Utente già esistente!'));
}
$utente->username = $username;
$utente->email = $email;
$utente->password = $password;
} else {
$utente = User::build($username, $email, $password);
}
if (empty($id_record)) {
redirect(ROOTDIR.'/modules/utenti/info.php');
// Foto
if (!empty($_FILES['photo']['tmp_name'])) {
$utente->photo = $_FILES['photo'];
}
// Anagrafica
$id_anagrafica = filter('idanag');
$utente->id_anagrafica = $id_anagrafica;
$utente->save();
$dbo->query('DELETE FROM zz_user_sedi WHERE id_user = '.prepare($id_utente));
foreach (post('idsede') as $i => $idsede) {
$dbo->query('INSERT INTO `zz_user_sedi` (`id_user`,`idsede`) VALUES ('.prepare($id_utente).', '.prepare($idsede).')');
}
break;
// Aggiunta di un nuovo utente
case 'adduser':
$username = filter('username');
$email = filter('email');
$min_length = filter('min_length');
$min_length_username = filter('min_length_username');
case 'self_update':
$password = filter('password');
$password = filter('password1');
$password_rep = filter('password2');
$utente = Auth::user();
$idanagrafica = filter('idanag');
// Verifico che questo username non sia già stato usato
$n = $dbo->fetchNum('SELECT * FROM zz_users WHERE username='.prepare($username));
if ($n == 0) {
// Verifico che la password sia di almeno x caratteri
if (strlen($password) < $min_length) {
flash()->error(tr('La password deve essere lunga almeno _MIN_ caratteri!', [
'_MIN_' => $min_length,
]));
} elseif ($password != $password_rep) {
flash()->error(tr('Le password non coincidono'));
} else {
if ($dbo->query('INSERT INTO zz_users(idgruppo, username, password, idanagrafica, enabled, email) VALUES('.prepare($id_record).', '.prepare($username).', '.prepare(Auth::hashPassword($password)).', '.prepare($idanagrafica).', 1, '.prepare($email).')')) {
$dbo->query('INSERT INTO `zz_tokens` (`id_utente`, `token`) VALUES ('.prepare($dbo->lastInsertedID()).', '.prepare(secure_random_string()).')');
flash()->info(tr('Utente aggiunto!'));
$id_utente = $dbo->lastInsertedID();
foreach (post('idsede') as $i => $idsede) {
$dbo->query('INSERT INTO `zz_user_sedi` (`id_user`,`idsede`) VALUES ('.prepare($id_utente).', '.prepare($idsede).')');
}
}
}
} else {
flash()->error(tr('Utente già esistente!'));
if (!empty($password)) {
$utente->password = $password;
} elseif (!empty($_FILES['photo']['tmp_name'])) {
$utente->photo = $_FILES['photo'];
}
break;
// Aggiunta nuovo gruppo
case 'add':
$nome = filter('nome');
$utente->save();
redirect(ROOTDIR.'/modules/utenti/info.php');
// Verifico che questo username non sia già stato usato
if ($dbo->fetchNum('SELECT nome FROM zz_groups WHERE nome='.prepare($nome)) == 0) {
$dbo->query('INSERT INTO zz_groups( nome, editable ) VALUES('.prepare($nome).', 1)');
flash()->info(tr('Gruppo aggiunto!'));
$id_record = $dbo->lastInsertedID();
} else {
flash()->error(tr('Gruppo già esistente!'));
}
break;
// Elimina utente
case 'delete':
case 'delete_user':
if ($dbo->query('DELETE FROM zz_users WHERE id='.prepare($id_utente))) {
flash()->info(tr('Utente eliminato!'));
}
@ -167,7 +129,6 @@ switch (filter('op')) {
// Impostazione/reimpostazione dei permessi di accesso di default
case 'restore_permission':
//Gruppo Tecnici
if ($dbo->fetchArray('SELECT `nome` FROM `zz_groups` WHERE `id` = '.prepare($id_record))[0]['nome'] == 'Tecnici') {
$permessi = [];

View File

@ -0,0 +1,45 @@
<?php
include_once __DIR__.'/../../core.php';
$_SESSION['superselect']['idanagrafica'] = $utente['id_anagrafica'];
echo '
<div class="row">
<div class="col-md-12">
{[ "type": "text", "label": "'.tr('Username').'", "name": "username", "required": 1, "value": "'.$utente['username'].'", "validation": "username" ]}
</div>
</div>';
echo '
<div class="row">
<div class="col-md-12">
{[ "type": "text", "label": "'.tr('Email').'", "name": "email", "required": 0, "value": "'.$utente['email'].'" ]}
</div>
</div>';
echo '
<div class="row">
<div class="col-md-12">
{[ "type": "select", "label": "'.tr('Collega ad una anagrafica').'", "name": "idanag", "required": 1, "ajax-source": "anagrafiche_utenti", "value": "'.$utente['id_anagrafica'].'", "icon-after": "add|'.Modules::get('Anagrafiche')['id'].(isset($gruppo) ? '|tipoanagrafica='.$gruppo : '').'" ]}
</div>
</div>
<div class="row">
<div class="col-md-12">
{[ "type": "select", "label": "'.tr('Sede').'", "name": "idsede[]", "ajax-source": "sedi", "multiple":"1", "value":"'.($sedi ?: '').'" ]}
</div>
</div>';
echo '
<script type="text/javascript">
$(document).ready(function(){
$("#idanag").change(function(){
session_set("superselect,idanagrafica", $(this).val(), 0);
$("#idsede").selectReset();
})
});
</script>';

View File

@ -0,0 +1,10 @@
<?php
include_once __DIR__.'/../../core.php';
echo '
<div class="row">
<div class="col-md-12">
{[ "type": "password", "label": "'.tr('Password').'", "name": "password", "required": 1, "strength": "#submit-button" ]}
</div>
</div>';

View File

@ -0,0 +1,10 @@
<?php
include_once __DIR__.'/../../core.php';
echo '
<div class="row">
<div class="col-md-12">
{[ "type": "file", "label": "'.tr('Foto').'", "name": "photo" ]}
</div>
</div>';

View File

@ -13,6 +13,7 @@ echo '
</div>
<div class="panel-body">';
if (!empty($utenti)) {
echo '
<div class="table-responsive">
@ -28,12 +29,11 @@ if (!empty($utenti)) {
foreach ($utenti as $utente) {
echo '
<tr>
<td';
if ($utente['enabled'] == 0) {
echo ' style="text-decoration:line-through;"';
}
echo '><i class="fa fa-user"></i> '.$utente['username'].'</td>';
if ($utente['idanagrafica'] != 0) {
<td '.(empty($utente['enabled']) ? ' style="text-decoration:line-through;"' : '').'>
<i class="fa fa-user"></i> '.$utente['username'].'
</td>';
if (!empty($utente['idanagrafica'])) {
echo '
<td>'.Modules::link('Anagrafiche', $utente['idanagrafica'], $utente['ragione_sociale']).'</td>
<td>'.$utente['tipo'].'</td>';
@ -48,51 +48,61 @@ if (!empty($utenti)) {
echo '
<td>'.$sedi.'</td>';
/*
* Funzioni per gli utenti
*/
echo '
<td>';
// Disabilitazione utente, se diverso da id_utente #1 (admin)
if ($utente['id'] != '1') {
if ($utente['enabled'] == 1) {
echo '
<a href="javascript:;" onclick="swal({ title: \''.tr('Disabilitare questo utente?').'\', type: \'info\', showCancelButton: true, confirmButtonText: \''.tr('Sì').'\' }).then(function (result) { location.href=\''.$rootdir.'/editor.php?id_module='.$id_module.'&id_record='.$id_record.'&op=disable&id_utente='.$utente['id'].'&idgruppo='.$record['id'].'\'; }) " title="Disabilita utente" class="text-danger tip"><i class="fa fa-2x fa-eye-slash"></i></a>';
} else {
echo '
<a href="javascript:;" onclick="swal({ title: \''.tr('Abilitare questo utente?').'\', type: \'info\', showCancelButton: true, confirmButtonText: \''.tr('Sì').'\' }).then(function (result) { location.href=\''.$rootdir.'/editor.php?id_module='.$id_module.'&id_record='.$id_record.'&op=enable&id_utente='.$utente['id'].'&idgruppo='.$record['id'].'\'; }) " title="Abilita utente" class="text-success tip"><i class="fa fa-2x fa-eye"></i></a>';
}
if ($utente['id'] == '1') {
echo '
<a title=""'.tr("Non è possibile disabilitare l'utente admin").'" class="text-muted tip">
<i class="fa fa-2x fa-eye-slash"></i>
</a>';
} elseif ($utente['enabled'] == 1) {
echo '
<a title="'.tr('Disabilita utente').'" class="text-danger clickable tip ask" data-msg="" data-backto="record-edit" data-title="'.tr('Disabilitare questo utente?').'" data-op="token_disable" data-id_utente="'.$utente['id'].'" data-button="'.tr('Disabilita').'">
<i class="fa fa-2x fa-eye-slash"></i>
</a>';
} else {
echo '
<a href="javascript:;" onclick="alert(\"'.tr("Non è possibile disabilitare l'utente admin").'\")" class="text-muted tip"><i class="fa fa-2x fa-eye-slash"></i></<>';
<a title="'.tr('Abilita utente').'" class="text-success clickable tip ask" data-msg="" data-backto="record-edit" data-title="'.tr('Abiltare questo utente?').'" data-op="token_disable" data-id_utente="'.$utente['id'].'" data-button="'.tr('Abilita').'" data-class="btn btn-lg btn-warning">
<i class="fa fa-2x fa-eye"></i>
</a>';
}
// Cambio password e nome utente
echo '
<a href="" data-href="'.$rootdir.'/modules/'.Modules::get($id_module)['directory'].'/user.php?id_utente='.$utente['id'].'&idgruppo='.$record['id'].'" class="text-warning tip" data-toggle="modal" title="Aggiorna dati utente" data-title="Aggiorna dati utente"><i class="fa fa-2x fa-unlock-alt"></i></a>';
<a href="" data-href="'.$structure->fileurl('user.php').'?id_module='.$id_module.'&id_record='.$id_record.'&id_utente='.$utente['id'].'" class="text-warning tip" data-toggle="modal" title="Aggiorna dati utente" data-msg="" data-backto="record-edit" data-title="Aggiorna dati utente"><i class="fa fa-2x fa-unlock-alt"></i></a>';
// Disabilitazione token API, se diverso da id_utente #1 (admin)
if ($utente['id'] != '1') {
$token = $dbo->fetchOne('SELECT `enabled` FROM `zz_tokens` WHERE `id_utente` = '.prepare($utente['id']));
if (!empty($token['enabled'])) {
echo '
<a href="javascript:;" onclick="swal({ title: \''.tr("Disabilitare l\'accesso API per questo utente?").'\', type: \'info\', showCancelButton: true, confirmButtonText: \''.tr('Sì').'\' }).then(function (result) { location.href=\''.$rootdir.'/editor.php?id_module='.$id_module.'&id_record='.$id_record.'&op=token_disable&id_utente='.$utente['id'].'&idgruppo='.$record['id'].'\'; }) " title="Disabilita API" class="text-danger tip"><i class="fa fa-2x fa-key"></i></a>';
} else {
echo '
<a href="javascript:;" onclick="swal({ title: \''.tr("Abilitare l\'accesso API per questo utente?").'\', type: \'info\', showCancelButton: true, confirmButtonText: \''.tr('Sì').'\' }).then(function (result) { location.href=\''.$rootdir.'/editor.php?id_module='.$id_module.'&id_record='.$id_record.'&op=token_enable&id_utente='.$utente['id'].'&idgruppo='.$record['id'].'\'; }) " title="Abilitare API" class="text-success tip"><i class="fa fa-2x fa-key"></i></a>';
}
$token = $dbo->fetchOne('SELECT `enabled` FROM `zz_tokens` WHERE `id_utente` = '.prepare($utente['id']));
if ($utente['id'] == '1') {
echo '
<span title="'.tr("Non è possibile gestire l'accesso API per l'utente admin").'" class="text-muted tip">
<i class="fa fa-2x fa-key "></i>
</span>';
} elseif (!empty($token['enabled'])) {
echo '
<a title="'.tr('Disabilita API').'" class="text-danger clickable tip ask" data-msg="" data-backto="record-edit" data-title="'.tr("Disabilitare l'accesso API per questo utente?").'" data-op="token_disable" data-id_utente="'.$utente['id'].'" data-button="'.tr('Disabilita').'">
<i class="fa fa-2x fa-key"></i>
</a>';
} else {
echo '
<span onclick="alert(\"'.tr("Non è possibile gestire l'accesso API per l'utente admin").'\")" class="text-muted tip"><i class="fa fa-2x fa-key "></i></span>';
<a title="'.tr('Abilitare API').'" class="text-success clickable tip ask" data-msg="" data-backto="record-edit" data-title="'.tr("Abilitare l'accesso API per questo utente?").'" data-op="token_enable" data-id_utente="'.$utente['id'].'" data-button="'.tr('Abilita').'" data-class="btn btn-lg btn-warning">
<i class="fa fa-2x fa-key"></i>
</a>';
}
// Eliminazione utente, se diverso da id_utente #1 (admin)
if ($utente['id'] != '1') {
if ($utente['id'] == '1') {
echo '
<a href="javascript:;" onclick="swal({ title: \''.tr('Eliminare questo utente?').'\', type: \'info\', showCancelButton: true, confirmButtonText: \''.tr('Sì').'\' }).then(function (result) { location.href=\''.$rootdir.'/editor.php?id_module='.$id_module.'&id_record='.$id_record.'&op=delete&id_utente='.$utente['id'].'&idgruppo='.$record['id'].'\'; }) " title="Elimina utente" class="text-danger tip"><i class="fa fa-2x fa-trash"></i></a>';
<span title="'.tr("Non è possibile eliminare l'utente admin").'" class="text-muted tip">
<i class="fa fa-2x fa-trash"></i>
</span>';
} else {
echo '
<span onclick="alert(\"'.tr("Non è possibile eliminare l'utente admin").'\")" class="text-muted tip"><i class="fa fa-2x fa-trash"></i></span>';
<a title="Elimina utente" class="text-danger clickable tip ask" data-msg="" data-backto="record-edit" data-title="'.tr('Eliminare questo utente?').'" data-op="delete_user" data-id_utente="'.$utente['id'].'">
<i class="fa fa-2x fa-trash"></i>
</a>';
}
echo '
@ -101,14 +111,19 @@ if (!empty($utenti)) {
}
echo '
</table>
</table>
</div>';
} else {
echo '
<div class=\'alert alert-info\' ><i class=\'fa fa-info-circle\'></i> '.tr('Non ci sono utenti in questo gruppo').'.</div>';
<div class="alert alert-info">
<i class="fa fa-info-circle"></i> '.tr('Non ci sono utenti in questo gruppo').'.
</div>';
}
echo '
<a data-toggle="modal" data-href="'.$rootdir.'/modules/utenti/user.php?idgruppo='.$record['id'].'" data-title="'.tr('Aggiungi utente').'" class="pull-right btn btn-primary"><i class="fa fa-plus"></i> '.tr('Aggiungi utente').'</a>
<a data-toggle="modal" data-href="'.$structure->fileurl('user.php').'?id_module='.$id_module.'&id_record='.$id_record.'" data-msg="" data-backto="record-edit" data-title="'.tr('Aggiungi utente').'" class="pull-right btn btn-primary">
<i class="fa fa-plus"></i> '.tr('Aggiungi utente').'
</a>
</div>
</div>';
@ -152,7 +167,9 @@ if ($record['nome'] != 'Amministratori') {
</div>';
} else {
echo '
<div class=\'alert alert-info\' ><i class=\'fa fa-info-circle\'></i> '.tr('Gli amministratori hanno accesso a qualsiasi modulo').'.</div>';
<div class="alert alert-info">
<i class="fa fa-info-circle"></i> '.tr('Gli amministratori hanno accesso a qualsiasi modulo').'.
</div>';
}
echo '
</div>
@ -177,6 +194,7 @@ echo '
$("#save").addClass("hide");
});
$("li.active.header button.btn-primary").attr("data-href", $("a.pull-right").attr("data-href") );
function update_permissions(id, value){
$.get(
globals.rootdir + "/actions.php?id_module='.$id_module.'&id_record='.$id_record.'&op=update_permission&idmodulo=" + id + "&permesso=" + value,

View File

@ -7,7 +7,7 @@ $pageTitle = tr('Utente');
include_once App::filepath('include|custom|', 'top.php');
if (post('op') == 'change_pwd') {
if (post('op') == 'self_update') {
include_once __DIR__.'/actions.php';
}
@ -32,22 +32,43 @@ echo '
// Cambio password e nome utente
echo '
<div>'.
'<p>'.tr('Utente').': <b>'.$user['username'].'</b></p>'.
'<p>'.tr('Gruppo').': <b>'.$user['gruppo'].'</b></p>';
<div class="row">
<div class="col-md-12">
<img src="'.$user->photo.'" class="img-responsive img-thumbnail pull-right">
<p>'.tr('Utente').': <b>'.$user['username'].'</b></p>
<p>'.tr('Gruppo').': <b>'.$user['gruppo'].'</b></p>';
if (!empty($anagrafica)) {
echo '
<p>'.tr('Anagrafica associata').': <b>'.$anagrafica['ragione_sociale'].'</b></p>';
<p>'.tr('Anagrafica associata').': <b>'.$anagrafica['ragione_sociale'].'</b></p>';
}
echo '
<a class="btn btn-info col-md-4 tip '.((!empty(Modules::get('Utenti e permessi'))) ? '' : 'disabled').'" data-href="'.$rootdir.'/modules/'.Modules::get('Utenti e permessi')['directory'].'/user.php" data-toggle="modal" data-title="Cambia password">
<i class="fa fa-unlock-alt"></i> '.tr('Cambia password').'
</a>
</div>
</div>';
$module = Modules::get('Utenti e permessi');
if (!empty($module)) {
echo '
<div class="row">
<div class="col-md-6">
<a class="btn btn-warning btn-block tip" data-href="'.$module->fileurl('self.php').'?id_module='.$module->id.'&resource=password" data-toggle="modal" data-title="'.tr('Cambia password').'">
<i class="fa fa-unlock-alt"></i> '.tr('Cambia password').'
</a>
</div>
<div class="col-md-6">
<a class="btn btn-info btn-block tip" data-href="'.$module->fileurl('self.php').'?id_module='.$module->id.'&resource=photo" data-toggle="modal" data-title="'.tr('Cambia foto').'">
<i class="fa fa-picture-o"></i> '.tr('Cambia foto').'
</a>
</div>
</div>';
}
echo '
</div>
</div>';

31
modules/utenti/self.php Normal file
View File

@ -0,0 +1,31 @@
<?php
include_once __DIR__.'/../../core.php';
$resource = filter('resource');
$user = Auth::user();
$utente = $user->toArray();
echo '
<form action="" method="post" enctype="multipart/form-data" id="user_update">
<input type="hidden" name="op" value="self_update">';
if ($resource == 'password') {
include $structure->filepath('components/password.php');
} elseif ($resource == 'photo') {
include $structure->filepath('components/photo.php');
}
echo '
<!-- PULSANTI -->
<div class="row">
<div class="col-md-12 text-right">
<button type="sumbit" onclick="submitCheck()" class="btn btn-primary" id="submit-button">
<i class="fa fa-edit"></i> '.tr('Modifica').'
</button>
</div>
</div>
</form>
<script src="'.$rootdir.'/lib/init.js"></script>';

View File

@ -2,166 +2,71 @@
include_once __DIR__.'/../../core.php';
// Lunghezza minima della password
$min_length_password = 8;
// Lunghezza minima del nome utente (username)
$min_length_username = 4;
use Models\Group;
use Models\User;
$self_edit = Modules::getPermission('Utenti e permessi') != 'rw' || (filter('id_utente') == null && filter('idgruppo') == null);
Permissions::check('rw');
if ($self_edit) {
$user = Auth::user();
$id_utente = filter('id_utente');
$user = User::find($id_utente);
$utente = $user ? $user->toArray() : [];
$id_utente = $user['id'];
} else {
$idgruppo = intval(filter('idgruppo'));
$id_utente = filter('id_utente');
// Gruppo della selezione
if (!empty($id_record)) {
$gruppo_utente = Group::find($id_record)->descrizione;
//gruppo della selezione
$nome_gruppo = $dbo->fetchArray('SELECT nome FROM zz_groups WHERE id='.prepare($idgruppo))[0]['nome'];
$gruppi = [
'Clienti' => 'Cliente',
'Tecnici' => 'Tecnico',
'Agenti' => 'Agente',
];
$nome_gruppo = $gruppi[$nome_gruppo];
$gruppo = $gruppi[$gruppo_utente];
}
if (!empty($id_utente)) {
$op = 'change_pwd';
$message = tr('Modifica');
$rs = $dbo->fetchArray('SELECT idanagrafica, username, email FROM zz_users WHERE id='.prepare($id_utente));
$username = $rs[0]['username'];
$email = $rs[0]['email'];
$id_anagrafica = $rs[0]['idanagrafica'];
// Lettura sedi dell'utente già impostate
// Lettura sedi dell'utente già impostate
if (!empty($user)) {
$sedi = $dbo->fetchOne('SELECT GROUP_CONCAT(idsede) as sedi FROM zz_user_sedi WHERE id_user='.prepare($id_utente).' GROUP BY id_user')['sedi'];
} else {
$op = 'adduser';
$message = tr('Aggiungi');
$username = '';
$email = '';
$id_anagrafica = '';
}
$_SESSION['superselect']['idanagrafica'] = $id_anagrafica;
echo '
<form action="" method="post" id="link_form">
<input type="hidden" name="op" value="'.$op.'">
<input type="hidden" name="min_length" value="'.$min_length_password.'">
<input type="hidden" name="min_length_username" value="'.$min_length_username.'">';
if (!empty($id_utente)) {
echo '
<input type="hidden" name="id_utente" value="'.$id_utente.'">';
}
if (!$self_edit) {
echo '
<form action="" method="post" enctype="multipart/form-data" id="user_update">
<input type="hidden" name="op" value="update_user">
<input type="hidden" name="backto" value="record-edit">
<input type="hidden" name="id_utente" value="'.$utente['id'].'">';
include $structure->filepath('components/photo.php');
include $structure->filepath('components/base.php');
include $structure->filepath('components/password.php');
echo '
<!-- PULSANTI -->
<div class="row">
<div class="col-md-12">
{[ "type": "text", "label": "'.tr('Username').'", "name": "username", "required": 1, "value": "'.$username.'" ]}
</div>
</div>
<div class="col-md-12 text-right">
<button type="button" onclick="submitCheck()" class="btn btn-primary" id="submit-button">';
<div class="row">
<div class="col-md-12">
{[ "type": "text", "label": "'.tr('Email').'", "name": "email", "required": 0, "value": "'.$email.'" ]}
</div>
</div>';
if (empty($user)) {
echo '
<i class="fa fa-plus"></i> '.tr('Aggiungi');
} else {
echo '
<input type="hidden" id="username" name="username" value="'.$username.'">
<input type="hidden" id="email" name="email" value="'.$email.'">';
<i class="fa fa-edit"></i> '.tr('Modifica');
}
echo '
<div class="row">
<div class="col-md-12">
{[ "type": "password", "label": "'.tr('Password').'", "name": "password1", "required": 1 ]}
</button>
</div>
</div>';
</div>
</form>
echo '
<div class="row">
<div class="col-md-12">
{[ "type": "password", "label": "'.tr('Ripeti la password').'", "name": "password2" ]}
</div>
</div>';
if (!$self_edit) {
echo '
<div class="row">
<div class="col-md-12">
{[ "type": "select", "label": "'.tr('Collega ad una anagrafica').'", "name": "idanag", "required": 1, "ajax-source": "anagrafiche_utenti", "value": "'.$id_anagrafica.'", "icon-after": "add|'.Modules::get('Anagrafiche')['id'].'|tipoanagrafica='.$nome_gruppo.'" ]}
</div>
</div>';
} else {
echo '
<input type="hidden" id="idanag" name="idanag" value="'.$id_anagrafica.'">';
<script>
function submitCheck() {
var username = parseInt($("#username").attr("valid"));
if(username) {
$("#user_update").submit();
}
}
echo '
<div class="row">
<div class="col-md-12">
{[ "type": "select", "label": "'.tr('Sede').'", "name": "idsede[]", "ajax-source": "sedi", "multiple":"1", "value":"'.$sedi.'" ]}
</div>
</div>';
echo '
<button type="button" onclick="do_submit()" class="btn btn-primary pull-right"><i class="fa fa-plus"></i> '.$message.'</button>
<div class="clearfix">&nbsp;</div>
</form>
<script type="text/javascript">
var min_length = '.$min_length_password.';
var min_length_username = '.$min_length_username.';
function do_submit(){
if( $("#password1").val() == "" || $("#password2").val() == "" )
swal({
title: "'.tr('Inserire una password valida.').'",
type: "error",
});
else if( $("#password1").val() != $("#password2").val() )
swal({
title: "'.tr('Le password non coincidono.').'",
type: "error",
});
else if( $("#password1").val().length < min_length )
swal({
title: "'.tr('La password deve essere lunga minimo _MIN_ caratteri!', [
'_MIN_' => $min_length_password,
]).'",
type: "error",
});
else if( $("#username").val().length < min_length_username )
swal({
title: "'.tr('L\'username deve essere lungo minimo _MIN_ caratteri.', [
'_MIN_' => $min_length_username,
]).'",
type: "error",
});
else
$("#link_form").submit();
}
$(document).ready(function(){
$("#idanag").change(function(){
session_set("superselect,idanagrafica", $(this).val(), 0);
$("#idsede").selectReset();
})
});
</script>
<script src="'.$rootdir.'/lib/init.js"></script>';

View File

@ -0,0 +1,33 @@
<?php
include_once __DIR__.'/../../core.php';
use Models\User;
$name = filter('name');
$value = filter('value');
switch ($name) {
case 'username':
$disponibile = User::where([
['username', $value],
['idanagrafica', '<>', $id_record],
])->count() == 0;
$message = $disponibile ? tr("L'username è disponbile") : tr("L'username è già utilizzato");
$result = $disponibile;
// Lunghezza minima del nome utente (username)
$min_length_username = 4;
if (strlen($value) < $min_length_username) {
$message .= '. '.tr("Lunghezza dell'username non sufficiente").'.';
$result = false;
}
$response = [
'result' => $result,
'message' => $message,
];
break;
}

View File

@ -29,6 +29,7 @@
"parsleyjs": "^2.7.2",
"pdf": "git://github.com/mozilla/pdf.js#gh-pages",
"pdf.js": "git://github.com/mozilla/pdf.js#gh-pages",
"pwstrength-bootstrap": "^3.0.4",
"select2": "4.0.3",
"select2-bootstrap-theme": "^0.1.0-beta.10",
"signature_pad": "^2.1.1",
@ -80,6 +81,9 @@
"chart.js": {
"ignore": true
},
"pwstrength-bootstrap": {
"ignore": true
},
"admin-lte": {
"main": [
"dist/css/AdminLTE.css",

View File

@ -95,7 +95,7 @@ class Ricevuta
];
// Registrazione XML come allegato
$filename = Uploads::upload($this->file, array_merge($info, [
Uploads::upload($this->file, array_merge($info, [
'name' => tr('Ricevuta _TYPE_', [
'_TYPE_' => $codice,
]),

View File

@ -116,14 +116,14 @@ if (empty($token)) {
<p>'.tr('Inserisci la nuova password per il tuo account').':</p>
{[ "type": "password", "label": "'.tr('Password').'", "name": "password", "icon-before": "<i class=\"fa fa-lock\"></i>" ]}';
{[ "type": "password", "label": "'.tr('Password').'", "name": "password", "required": 1, "strength": "#submit-button", "icon-before": "<i class=\"fa fa-lock\"></i>" ]}';
}
echo '
</div>
<div class="box-footer">
<button type="submit" id="login" class="btn btn-success btn-block">
<button type="submit" id="submit-button" class="btn btn-success btn-block">
<i class="fa fa-arrow-right"></i> '.tr('Procedi').'
</button>
</div>

View File

@ -464,16 +464,6 @@ class Auth extends \Util\Singleton
if (!empty($results)) {
$this->user = User::with('group')->find($user_id);
// Estraggo le sedi dell'utente loggato
$sedi = $database->fetchArray('SELECT idsede FROM zz_user_sedi WHERE id_user='.prepare($user_id));
// Se l'utente non ha sedi, è come se ce le avesse tutte disponibili per retrocompatibilità
if (empty($sedi)) {
$sedi = $database->fetchArray('SELECT "0" AS idsede UNION SELECT id AS idsede FROM an_sedi WHERE idanagrafica='.prepare($results[0]['idanagrafica']));
}
$this->user['sedi'] = array_column($sedi, 'idsede');
}
} catch (PDOException $e) {
$this->destory();

View File

@ -106,6 +106,43 @@ class DefaultHandler implements HandlerInterface
});
</script>';
if (!empty($values['strength'])) {
$result .= '
<div id="'.$values['id'].'_viewport_progress"></div>
<script src="'.ROOTDIR.'/assets/dist/password-strength/password.min.js"></script>
<script>
$(document).ready(function(){
$("#'.$values['id'].'").pwstrength({
ui: {
bootstrap3: true,
showVerdictsInsideProgressBar: true,
viewports: {
progress: "#'.$values['id'].'_viewport_progress",
},
progressBarExtraCssClasses: "progress-bar-striped active",
showPopover: true,
showErrors: true,
},
common: {
minChar: 6,
onKeyUp: function(event, data) {
var len = $("#'.$values['id'].'").val().length;
if(len < 6) {
$("'.$values['strength'].'").attr("disabled", true).addClass("disabled");
} else {
$("'.$values['strength'].'").attr("disabled", false).removeClass("disabled");
}
}
},
});
$("#'.$values['id'].'_viewport_progress").insertAfter($("#'.$values['id'].'").closest(".form-group").find("div[id$=-errors]")).css("margin-top", "5px");
});
</script>';
}
// Delega al metodo "text", per la generazione del codice HTML
$result .= $this->text($values, $extras);

View File

@ -85,27 +85,35 @@ class HTMLWrapper implements WrapperInterface
}
if (!empty($values['validation'])) {
$values['valid'] = '1';
$value = explode('|', $values['validation']);
$name = $value[0];
$id_module = $value[1] ?: '$id_module$';
$id_record = $value[2] ?: '$id_record$';
$result .= '
<script>
var container = $("#'.$pseudo_id.'_validation");
container.closest(".input-group").find("input").on("change", function(){
value = $(this).val();
var input = $(this);
var value = input.val();
container = $("#'.$pseudo_id.'_validation");
parent = container.closest(".input-group");
message = container.find("span");
icon = container.find("i");
var container = $("#'.$pseudo_id.'_validation");
var parent = container.closest(".input-group");
var message = container.find("span");
var icon = container.find("i");
icon.attr("class", "fa fa-spinner fa-spin");
$.ajax({
url: globals.rootdir + "/actions.php",
type: "get",
type: "post",
data: {
id_module: "$id_module$",
id_record: "$id_record$",
name: "'.$values['validation'].'",
id_module: "'.$id_module.'",
id_record: "'.$id_record.'",
name: "'.$name.'",
value: value,
op: "validate",
},
@ -121,6 +129,7 @@ class HTMLWrapper implements WrapperInterface
}
message.tooltipster("content", data.message);
input.attr("valid", +(data.result));
if (data.fields) {
fields = data.fields;

View File

@ -3,30 +3,96 @@
namespace Models;
use Common\Model;
use Intervention\Image\ImageManagerStatic;
class Upload extends Model
{
protected $table = 'zz_files';
protected $file_info;
public function getCategoryAttribute()
{
return $this->attributes['category'] ?: 'Generale';
}
/**
* Crea un nuovo upload.
*
* @param array $source
* @param array $data
*
* @return self
*/
public static function build($source, $data, $name = null, $category = null)
{
$original_name = isset($source['name']) ? $source['name'] : basename($source);
$model = parent::build();
// Informazioni di base
$model->attributes['original'] = $original_name; // Fix per original di Eloquent
$model->size = $source['size'];
$model->name = !empty($name) ? $name : $original_name;
$model->category = $category;
// Informazioni aggiuntive
foreach ($data as $key => $value) {
$model->{$key} = $value;
}
// Nome fisico del file
$directory = DOCROOT.'/'.$model->directory;
$filename = self::getNextName($original_name, $directory);
$model->filename = $filename;
// Creazione file fisico
if (
(is_uploaded_file($source['tmp_name']) && !move_uploaded_file($source['tmp_name'], $directory.'/'.$filename)) ||
(is_string($source) && !copy($source, $directory.'/'.$filename))
) {
return null;
}
$model->size = \Util\FileSystem::fileSize($directory.'/'.$filename);
$model->save();
return $model;
}
/**
* @return array
*/
public function getInfoAttribute()
{
if (!isset($this->file_info)) {
$filepath = $this->filepath;
$infos = self::getInfo($filepath);
$this->file_info = $infos;
}
return $this->file_info;
}
/**
* @return string|null
*/
public function getExtensionAttribute()
{
$pos = strrpos($this->filename, '.');
return strtolower($this->info['extension']);
}
if (!$pos) {
return null;
}
/**
* @return string
*/
public function getDirectoryAttribute()
{
$parent = $this->plugin ?: $this->module;
$extension = substr($this->filename, $pos + 1);
return strtolower($extension);
return $parent->upload_directory;
}
/**
@ -34,9 +100,7 @@ class Upload extends Model
*/
public function getFilepathAttribute()
{
$parent = $this->plugin ?: $this->module;
return $parent->upload_directory.'/'.$this->filename;
return $this->directory.'/'.$this->filename;
}
/**
@ -84,4 +148,90 @@ class Upload extends Model
{
return $this->belongsTo(Plugin::class, 'id_plugin');
}
public function delete()
{
$info = $this->info;
$directory = DOCROOT.'/'.$this->directory;
$files = [
$directory.'/'.$info['basename'],
$directory.'/'.$info['filename'].'_thumb600.'.$info['extension'],
$directory.'/'.$info['filename'].'_thumb100.'.$info['extension'],
$directory.'/'.$info['filename'].'_thumb250.'.$info['extension'],
];
delete($files);
return parent::delete();
}
public function save(array $options = [])
{
if ($this->isImage()) {
//self::generateThumbnails($this);
}
return parent::save($options);
}
public function copia($data)
{
$result = self::build(DOCROOT.'/'.$this->filepath, $data, $this->name, $this->category);
return $result;
}
public static function getInfo($file)
{
return pathinfo($file);
}
/**
* Genera casualmente il nome fisico per il file.
*
* @return string
*/
protected static function getNextName($file, $directory)
{
$extension = self::getInfo($file)['extension'];
$extension = strtolower($extension);
do {
$filename = random_string().'.'.$extension;
} while (file_exists($directory.'/'.$filename));
return $filename;
}
/**
* Genera le thumbnails per le immagini.
*/
protected static function generateThumbnails($upload)
{
$info = $upload->info;
$directory = $upload->directory;
$filepath = $upload->filepath;
$driver = extension_loaded('gd') ? 'gd' : 'imagick';
ImageManagerStatic::configure(['driver' => $driver]);
$img = ImageManagerStatic::make($filepath);
$img->resize(600, null, function ($constraint) {
$constraint->aspectRatio();
});
$img->save(slashes($directory.'/'.$info['filename'].'_thumb600.'.$info['extension']));
$img->resize(250, null, function ($constraint) {
$constraint->aspectRatio();
});
$img->save(slashes($directory.'/'.$info['filename'].'_thumb250.'.$info['extension']));
$img->resize(100, null, function ($constraint) {
$constraint->aspectRatio();
});
$img->save(slashes($directory.'/'.$info['filename'].'_thumb100.'.$info['extension']));
}
}

View File

@ -3,6 +3,7 @@
namespace Models;
use Common\Model;
use Intervention\Image\ImageManagerStatic;
class User extends Model
{
@ -11,6 +12,7 @@ class User extends Model
protected $appends = [
'is_admin',
'gruppo',
'id_anagrafica',
];
/**
@ -34,6 +36,30 @@ class User extends Model
'password', 'remember_token',
];
/**
* Crea un nuovo utente.
*
* @param string $username
* @param string $email
* @param string $password
*
* @return self
*/
public static function build(Group $gruppo, $username, $email, $password)
{
$model = parent::build();
$model->group()->associate($gruppo);
$model->username = $username;
$model->email = $email;
$model->password = $password;
$model->save();
return $model;
}
public function getIsAdminAttribute()
{
if (!isset($this->is_admin)) {
@ -43,6 +69,16 @@ class User extends Model
return $this->is_admin;
}
public function getIdAnagraficaAttribute()
{
return $this->attributes['idanagrafica'];
}
public function setIdAnagraficaAttribute($value)
{
$this->attributes['idanagrafica'] = $value;
}
public function getGruppoAttribute()
{
if (!isset($this->gruppo)) {
@ -52,11 +88,77 @@ class User extends Model
return $this->gruppo;
}
public function getSediAttribute()
{
$database = database();
// Estraggo le sedi dell'utente loggato
$sedi = $database->fetchArray('SELECT idsede FROM zz_user_sedi WHERE id_user='.prepare($this->id));
// Se l'utente non ha sedi, è come se ce le avesse tutte disponibili per retrocompatibilità
if (empty($sedi)) {
$sedi = $database->fetchArray('SELECT "0" AS idsede UNION SELECT id AS idsede FROM an_sedi WHERE idanagrafica='.prepare($this->idanagrafica));
}
return array_column($sedi, 'idsede');
}
public function setPasswordAttribute($value)
{
$this->attributes['password'] = \Auth::hashPassword($value);
}
public function getPhotoAttribute()
{
if (empty($this->image_file_id)) {
return null;
}
$image = Upload::find($this->image_file_id);
return ROOTDIR.'/'.$image->filepath;
}
public function setPhotoAttribute($value)
{
$module = \Modules::get('Utenti e permessi');
$data = [
'id_module' => $module->id,
'id_record' => $this->id,
];
// Foto precedenti
$old_photo = Upload::where($data)->get();
// Informazioni sull'immagine
$filepath = is_array($value) ? $value['tmp_name'] : $value;
$info = Upload::getInfo(is_array($value) ? $value['name'] : $value);
$file = DOCROOT.'/files/temp_photo.'.$info['extension'];
// Ridimensionamento
$driver = extension_loaded('gd') ? 'gd' : 'imagick';
ImageManagerStatic::configure(['driver' => $driver]);
$img = ImageManagerStatic::make($filepath)->resize(100, 100, function ($constraint) {
$constraint->aspectRatio();
});
$img->save(slashes($file));
// Aggiunta nuova foto
$upload = Upload::build($file, $data);
// Rimozione foto precedenti
delete($file);
if (!empty($upload)) {
foreach ($old_photo as $old) {
$old->delete();
}
}
$this->image_file_id = $upload->id;
}
/* Relazioni Eloquent */
public function group()

View File

@ -17,7 +17,10 @@ trait UploadTrait
{
$directory = $this->directory ?: 'common';
return $this->uploads_directory.'/'.$directory;
$result = $this->uploads_directory.'/'.$directory;
directory($result);
return $result;
}
public function uploads($id_record)

View File

@ -151,18 +151,12 @@ class Uploads
public static function getDirectory($id_module, $id_plugin = null)
{
if (empty($id_plugin)) {
$directory = Modules::get($id_module)['directory'];
$structure = Modules::get($id_module);
} else {
$info = Plugins::get($id_plugin);
if (!empty($info['script'])) {
$directory = self::fileInfo($info['script'])['filename'];
} else {
$directory = $info['directory'];
}
$structure = Plugins::get($id_plugin);
}
return 'files/'.$directory;
return $structure->upload_directory;
}
/**

View File

@ -66,3 +66,7 @@ UPDATE `co_righe_documenti` INNER JOIN `dt_righe_ddt` ON `co_righe_documenti`.`i
UPDATE `co_righe_documenti` INNER JOIN `co_righe_contratti` ON `co_righe_documenti`.`idcontratto` = `co_righe_contratti`.`idcontratto` AND `co_righe_documenti`.`descrizione` = `co_righe_contratti`.`descrizione` AND `co_righe_documenti`.`idarticolo` = `co_righe_contratti`.`idarticolo` SET `co_righe_documenti`.`original_id` = `co_righe_contratti`.`id`, `original_type` = 'Modules\\Contratti\\Components\\Riga' WHERE `co_righe_documenti`.`original_id` IS NULL;
UPDATE `co_righe_documenti` INNER JOIN `co_righe_preventivi` ON `co_righe_documenti`.`idpreventivo` = `co_righe_preventivi`.`idpreventivo` AND `co_righe_documenti`.`descrizione` = `co_righe_preventivi`.`descrizione` AND `co_righe_documenti`.`idarticolo` = `co_righe_preventivi`.`idarticolo` SET `co_righe_documenti`.`original_id` = `co_righe_preventivi`.`id`, `original_type` = 'Modules\\Preventivi\\Components\\Riga' WHERE `co_righe_documenti`.`original_id` IS NULL;
-- Aggiunta foto utente
ALTER TABLE `zz_users` ADD `image_file_id` int(11);
UPDATE `zz_modules` SET `enabled` = 1 WHERE `name` = 'Utenti e permessi';