Merge branch 'develop' of git+ssh://git@github.com/Dolibarr/dolibarr.git
into develop Conflicts: htdocs/user/index.php htdocs/user/info.php htdocs/user/note.php htdocs/user/param_ihm.php
This commit is contained in:
commit
0c8e4b8f1b
@ -99,8 +99,8 @@ class modMyModule extends DolibarrModules
|
||||
$this->const = array();
|
||||
|
||||
// Array to add new pages in new tabs
|
||||
// Example: $this->tabs = array('objecttype:+tabname1:Title1:@mymodule:$user->rights->mymodule->read:/mymodule/mynewtab1.php?id=__ID__', // To add a new tab identified by code tabname1
|
||||
// 'objecttype:+tabname2:Title2:@mymodule:$user->rights->othermodule->read:/mymodule/mynewtab2.php?id=__ID__', // To add another new tab identified by code tabname2
|
||||
// Example: $this->tabs = array('objecttype:+tabname1:Title1:langfile@mymodule:$user->rights->mymodule->read:/mymodule/mynewtab1.php?id=__ID__', // To add a new tab identified by code tabname1
|
||||
// 'objecttype:+tabname2:Title2:langfile@mymodule:$user->rights->othermodule->read:/mymodule/mynewtab2.php?id=__ID__', // To add another new tab identified by code tabname2
|
||||
// 'objecttype:-tabname'); // To remove an existing tab identified by code tabname
|
||||
// where objecttype can be
|
||||
// 'thirdparty' to add a tab in third party view
|
||||
|
||||
@ -215,10 +215,10 @@ else
|
||||
print '<td>';
|
||||
$filelib=preg_replace('/.php$/i','',(empty($conf->global->MAIN_MENU_SMARTPHONE_FORCED)?$conf->global->MAIN_MENU_SMARTPHONE:$conf->global->MAIN_MENU_SMARTPHONE_FORCED));
|
||||
print $filelib;
|
||||
if (preg_match('/smartphone/',$conf->global->MAIN_MENU_SMARTPHONE_FORCED)
|
||||
if (preg_match('/smartphone/',$conf->global->MAIN_MENU_SMARTPHONE_FORCED)
|
||||
|| (empty($conf->global->MAIN_MENU_SMARTPHONE_FORCED) && preg_match('/smartphone/',$conf->global->MAIN_MENU_SMARTPHONE)))
|
||||
{
|
||||
print ' '.img_warning($langs->trans("ThisForceAlsoTheme"));
|
||||
print ' '.img_warning($langs->transnoentitiesnoconv("ThisForceAlsoTheme"));
|
||||
}
|
||||
print '</td>';
|
||||
print '<td>';
|
||||
@ -227,7 +227,7 @@ else
|
||||
if (preg_match('/smartphone/',$conf->global->MAIN_MENUFRONT_SMARTPHONE_FORCED)
|
||||
|| (empty($conf->global->MAIN_MENUFRONT_SMARTPHONE_FORCED) && preg_match('/smartphone/',$conf->global->MAIN_MENUFRONT_SMARTPHONE)))
|
||||
{
|
||||
print ' '.img_warning($langs->trans("ThisForceAlsoTheme"));
|
||||
print ' '.img_warning($langs->transnoentitiesnoconv("ThisForceAlsoTheme"));
|
||||
}
|
||||
print '</td>';
|
||||
print '</tr>';
|
||||
|
||||
@ -86,9 +86,9 @@ $j = 0; // j is module number. Automatically affected if module number not defin
|
||||
foreach ($conf->file->dol_document_root as $type => $dirroot)
|
||||
{
|
||||
$modulesdir[] = $dirroot . "/core/modules/";
|
||||
|
||||
|
||||
if ($type == 'alt')
|
||||
{
|
||||
{
|
||||
$handle=@opendir($dirroot);
|
||||
if (is_resource($handle))
|
||||
{
|
||||
@ -106,6 +106,7 @@ foreach ($conf->file->dol_document_root as $type => $dirroot)
|
||||
}
|
||||
}
|
||||
}
|
||||
//var_dump($modulesdir);
|
||||
|
||||
foreach ($modulesdir as $dir)
|
||||
{
|
||||
@ -124,38 +125,45 @@ foreach ($modulesdir as $dir)
|
||||
|
||||
if ($modName)
|
||||
{
|
||||
include_once($dir.$file);
|
||||
$objMod = new $modName($db);
|
||||
|
||||
if ($objMod->numero > 0)
|
||||
try
|
||||
{
|
||||
$j = $objMod->numero;
|
||||
$res=include_once($dir.$file);
|
||||
$objMod = new $modName($db);
|
||||
|
||||
if ($objMod->numero > 0)
|
||||
{
|
||||
$j = $objMod->numero;
|
||||
}
|
||||
else
|
||||
{
|
||||
$j = 1000 + $i;
|
||||
}
|
||||
|
||||
$modulequalified=1;
|
||||
|
||||
// We discard modules according to features level (PS: if module is activated we always show it)
|
||||
$const_name = 'MAIN_MODULE_'.strtoupper(preg_replace('/^mod/i','',get_class($objMod)));
|
||||
if ($objMod->version == 'development' && $conf->global->MAIN_FEATURES_LEVEL < 2 && ! $conf->global->$const_name) $modulequalified=0;
|
||||
if ($objMod->version == 'experimental' && $conf->global->MAIN_FEATURES_LEVEL < 1 && ! $conf->global->$const_name) $modulequalified=0;
|
||||
|
||||
if ($modulequalified)
|
||||
{
|
||||
$modules[$i] = $objMod;
|
||||
$filename[$i]= $modName;
|
||||
$orders[$i] = $objMod->family."_".$j; // Tri par famille puis numero module
|
||||
//print "x".$modName." ".$orders[$i]."\n<br>";
|
||||
if (isset($categ[$objMod->special])) $categ[$objMod->special]++; // Array of all different modules categories
|
||||
else $categ[$objMod->special]=1;
|
||||
$dirmod[$i] = $dirroot;
|
||||
$j++;
|
||||
$i++;
|
||||
}
|
||||
else dol_syslog("Module ".get_class($objMod)." not qualified");
|
||||
}
|
||||
else
|
||||
catch(Exception $e)
|
||||
{
|
||||
$j = 1000 + $i;
|
||||
dol_syslog("Failed to load ".$dir.$file." ".$e->getMessage(), LOG_ERR);
|
||||
}
|
||||
|
||||
$modulequalified=1;
|
||||
|
||||
// We discard modules according to features level (PS: if module is activated we always show it)
|
||||
$const_name = 'MAIN_MODULE_'.strtoupper(preg_replace('/^mod/i','',get_class($objMod)));
|
||||
if ($objMod->version == 'development' && $conf->global->MAIN_FEATURES_LEVEL < 2 && ! $conf->global->$const_name) $modulequalified=0;
|
||||
if ($objMod->version == 'experimental' && $conf->global->MAIN_FEATURES_LEVEL < 1 && ! $conf->global->$const_name) $modulequalified=0;
|
||||
|
||||
if ($modulequalified)
|
||||
{
|
||||
$modules[$i] = $objMod;
|
||||
$filename[$i]= $modName;
|
||||
$orders[$i] = $objMod->family."_".$j; // Tri par famille puis numero module
|
||||
//print "x".$modName." ".$orders[$i]."\n<br>";
|
||||
if (isset($categ[$objMod->special])) $categ[$objMod->special]++; // Array of all different modules categories
|
||||
else $categ[$objMod->special]=1;
|
||||
$dirmod[$i] = $dirroot;
|
||||
$j++;
|
||||
$i++;
|
||||
}
|
||||
else dol_syslog("Module ".get_class($objMod)." not qualified");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -317,7 +325,7 @@ if ($mode != 4)
|
||||
//print $familytext;
|
||||
$oldfamily=$family;
|
||||
}
|
||||
|
||||
|
||||
$var=!$var;
|
||||
print '<tr height="18" '.$bc[$var].">\n";
|
||||
|
||||
|
||||
@ -528,8 +528,8 @@ class DoliDBMssql
|
||||
if (! $return) $return.=' ORDER BY ';
|
||||
else $return.=',';
|
||||
|
||||
$return.=$val;
|
||||
if ($sortorder) $return.=' '.$sortorder;
|
||||
$return.=preg_replace('/[^0-9a-z_\.]/i','',$val);
|
||||
if ($sortorder) $return.=' '.preg_replace('/[^0-9a-z]/i','',$sortorder);
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
@ -509,8 +509,8 @@ class DoliDBMysql
|
||||
if (! $return) $return.=' ORDER BY ';
|
||||
else $return.=',';
|
||||
|
||||
$return.=$val;
|
||||
if ($sortorder) $return.=' '.$sortorder;
|
||||
$return.=preg_replace('/[^0-9a-z_\.]/i','',$val);
|
||||
if ($sortorder) $return.=' '.preg_replace('/[^0-9a-z]/i','',$sortorder);
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
@ -522,8 +522,8 @@ class DoliDBMysqli
|
||||
if (! $return) $return.=' ORDER BY ';
|
||||
else $return.=',';
|
||||
|
||||
$return.=$val;
|
||||
if ($sortorder) $return.=' '.$sortorder;
|
||||
$return.=preg_replace('/[^0-9a-z_\.]/i','',$val);
|
||||
if ($sortorder) $return.=' '.preg_replace('/[^0-9a-z]/i','',$sortorder);
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
@ -666,8 +666,8 @@ class DoliDBPgsql
|
||||
if (! $return) $return.=' ORDER BY ';
|
||||
else $return.=',';
|
||||
|
||||
$return.=$val;
|
||||
if ($sortorder) $return.=' '.$sortorder;
|
||||
$return.=preg_replace('/[^0-9a-z_\.]/i','',$val);
|
||||
if ($sortorder) $return.=' '.preg_replace('/[^0-9a-z]/i','',$sortorder);
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
@ -2662,6 +2662,7 @@ function dol_print_error_email()
|
||||
|
||||
/**
|
||||
* Show title line of an array
|
||||
*
|
||||
* @param name Label of field
|
||||
* @param file Url used when we click on sort picto
|
||||
* @param field Field to use for new sorting
|
||||
@ -4275,24 +4276,26 @@ function picto_from_langcode($codelang)
|
||||
/**
|
||||
* Complete or removed entries into a head array (used to build tabs) with value added by external modules
|
||||
*
|
||||
* @param conf Object conf
|
||||
* @param langs Object langs
|
||||
* @param object Object object
|
||||
* @param head Object head
|
||||
* @param h New position to fill
|
||||
* @param type Value for object where objectvalue can be
|
||||
* 'thirdparty' to add a tab in third party view
|
||||
* 'intervention' to add a tab in intervention view
|
||||
* 'supplier_order' to add a tab in supplier order view
|
||||
* 'supplier_invoice' to add a tab in supplier invoice view
|
||||
* 'invoice' to add a tab in customer invoice view
|
||||
* 'order' to add a tab in customer order view
|
||||
* 'product' to add a tab in product view
|
||||
* 'propal' to add a tab in propal view
|
||||
* 'member' to add a tab in fundation member view
|
||||
* 'categories_x' to add a tab in category view ('x': type of category (0=product, 1=supplier, 2=customer, 3=member)
|
||||
* @param mode 'add' to complete head, 'remove' to remove entries
|
||||
* @return void
|
||||
* @param Conf $conf Object conf
|
||||
* @param Translate $langs Object langs
|
||||
* @param Object $object Object object
|
||||
* @param array $head Object head
|
||||
* @param int $h New position to fill
|
||||
* @param string $type Value for object where objectvalue can be
|
||||
* 'thirdparty' to add a tab in third party view
|
||||
* 'intervention' to add a tab in intervention view
|
||||
* 'supplier_order' to add a tab in supplier order view
|
||||
* 'supplier_invoice' to add a tab in supplier invoice view
|
||||
* 'invoice' to add a tab in customer invoice view
|
||||
* 'order' to add a tab in customer order view
|
||||
* 'product' to add a tab in product view
|
||||
* 'propal' to add a tab in propal view
|
||||
* 'user' to add a tab in user view
|
||||
* 'group' to add a tab in group view
|
||||
* 'member' to add a tab in fundation member view
|
||||
* 'categories_x' to add a tab in category view ('x': type of category (0=product, 1=supplier, 2=customer, 3=member)
|
||||
* @param string $mode 'add' to complete head, 'remove' to remove entries
|
||||
* @return void
|
||||
*/
|
||||
function complete_head_from_modules($conf,$langs,$object,&$head,&$h,$type,$mode='add')
|
||||
{
|
||||
@ -4301,11 +4304,13 @@ function complete_head_from_modules($conf,$langs,$object,&$head,&$h,$type,$mode=
|
||||
foreach ($conf->tabs_modules[$type] as $value)
|
||||
{
|
||||
$values=explode(':',$value);
|
||||
|
||||
if ($mode == 'add')
|
||||
{
|
||||
if (count($values) == 6) // new declaration with permissions
|
||||
{
|
||||
if ($values[0] != $type) continue;
|
||||
//print 'ee'.$values[4];
|
||||
if (verifCond($values[4]))
|
||||
{
|
||||
if ($values[3]) $langs->load($values[3]);
|
||||
|
||||
@ -74,8 +74,8 @@ function user_prepare_head($object)
|
||||
|
||||
// Show more tabs from modules
|
||||
// Entries must be declared in modules descriptor with line
|
||||
// $this->tabs = array('entity:+tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to add new tab
|
||||
// $this->tabs = array('entity:-tabname:Title:@mymodule:/mymodule/mypage.php?id=__ID__'); to remove a tab
|
||||
// $this->tabs = array('entity:+tabname:Title:@mymodule:conditiontoshow:/mymodule/mypage.php?id=__ID__'); to add new tab
|
||||
// $this->tabs = array('entity:-tabname:Title:@mymodule:conditiontoshow:/mymodule/mypage.php?id=__ID__'); to remove a tab
|
||||
complete_head_from_modules($conf,$langs,$object,$head,$h,'user');
|
||||
|
||||
if (! $user->societe_id)
|
||||
|
||||
@ -488,3 +488,16 @@ ALTER TABLE llx_element_element MODIFY targettype varchar(32) NOT NULL;
|
||||
|
||||
ALTER TABLE llx_societe_prices MODIFY tms timestamp NULL;
|
||||
-- ALTER TABLE llx_societe_prices ALTER COLUMN tms DROP NOT NULL;
|
||||
|
||||
-- Fix: It seems this is missing for some users
|
||||
insert into llx_c_actioncomm (id, code, type, libelle, module, position) values ( 1, 'AC_TEL', 'system', 'Phone call' ,NULL, 2);
|
||||
insert into llx_c_actioncomm (id, code, type, libelle, module, position) values ( 2, 'AC_FAX', 'system', 'Send Fax' ,NULL, 3);
|
||||
insert into llx_c_actioncomm (id, code, type, libelle, module, position) values ( 3, 'AC_PROP', 'system', 'Send commercial proposal by email' ,'propal', 10);
|
||||
insert into llx_c_actioncomm (id, code, type, libelle, module, position) values ( 4, 'AC_EMAIL', 'system', 'Send Email' ,NULL, 4);
|
||||
insert into llx_c_actioncomm (id, code, type, libelle, module, position) values ( 5, 'AC_RDV', 'system', 'Rendez-vous' ,NULL, 1);
|
||||
insert into llx_c_actioncomm (id, code, type, libelle, module, position) values ( 8, 'AC_COM', 'system', 'Send customer order by email' ,'order', 8);
|
||||
insert into llx_c_actioncomm (id, code, type, libelle, module, position) values ( 9, 'AC_FAC', 'system', 'Send customer invoice by email' ,'invoice', 6);
|
||||
insert into llx_c_actioncomm (id, code, type, libelle, module, position) values ( 10, 'AC_SHIP', 'system', 'Send shipping by email' ,'shipping', 11);
|
||||
insert into llx_c_actioncomm (id, code, type, libelle, module, position) values ( 30, 'AC_SUP_ORD', 'system', 'Send supplier order by email' ,'order_supplier', 9);
|
||||
insert into llx_c_actioncomm (id, code, type, libelle, module, position) values (31, 'AC_SUP_INV', 'system', 'Send supplier invoice by email' ,'invoice_supplier', 7);
|
||||
insert into llx_c_actioncomm (id, code, type, libelle, module, position) values ( 50, 'AC_OTH', 'system', 'Other' ,NULL, 5);
|
||||
|
||||
@ -1247,7 +1247,9 @@ class User extends CommonObject
|
||||
// Mise a jour
|
||||
if (! $changelater)
|
||||
{
|
||||
$sql = "UPDATE ".MAIN_DB_PREFIX."user";
|
||||
if (! is_object($this->oldcopy)) $this->oldcopy=dol_clone($this);
|
||||
|
||||
$sql = "UPDATE ".MAIN_DB_PREFIX."user";
|
||||
$sql.= " SET pass_crypted = '".$this->db->escape($password_crypted)."',";
|
||||
$sql.= " pass_temp = null";
|
||||
if (! empty($conf->global->DATABASE_PWD_ENCRYPTED))
|
||||
|
||||
@ -36,6 +36,11 @@ if ($conf->ldap->enabled) require_once(DOL_DOCUMENT_ROOT."/core/class/ldap.class
|
||||
if ($conf->adherent->enabled) require_once(DOL_DOCUMENT_ROOT."/adherents/class/adherent.class.php");
|
||||
if (! empty($conf->multicompany->enabled)) dol_include_once("/multicompany/class/actions_multicompany.class.php");
|
||||
|
||||
$id = GETPOST('id','int');
|
||||
$action = GETPOST("action");
|
||||
$group = GETPOST("group","int",3);
|
||||
$confirm = GETPOST("confirm");
|
||||
|
||||
// Define value to know what current user can do on users
|
||||
$canadduser=($user->admin || $user->rights->user->user->creer);
|
||||
$canreaduser=($user->admin || $user->rights->user->user->lire);
|
||||
@ -48,18 +53,6 @@ if (! empty($conf->global->MAIN_USE_ADVANCED_PERMS))
|
||||
$canreadgroup=($user->admin || $user->rights->user->group_advance->read);
|
||||
$caneditgroup=($user->admin || $user->rights->user->group_advance->write);
|
||||
}
|
||||
|
||||
//Multicompany in mode transversal
|
||||
if(! empty($conf->multicompany->enabled) && $conf->entity > 1 && $conf->global->MULTICOMPANY_TRANSVERSE_MODE)
|
||||
{
|
||||
accessforbidden();
|
||||
}
|
||||
|
||||
$id = GETPOST("id");
|
||||
$action = GETPOST("action");
|
||||
$group = GETPOST("group","int",3);
|
||||
$confirm = GETPOST("confirm");
|
||||
|
||||
// Define value to know what current user can do on properties of edited user
|
||||
if ($id)
|
||||
{
|
||||
@ -70,6 +63,12 @@ if ($id)
|
||||
|| (($user->id != $id) && $user->rights->user->user->password) );
|
||||
}
|
||||
|
||||
//Multicompany in mode transversal
|
||||
if(! empty($conf->multicompany->enabled) && $conf->entity > 1 && $conf->global->MULTICOMPANY_TRANSVERSE_MODE)
|
||||
{
|
||||
accessforbidden();
|
||||
}
|
||||
|
||||
// Security check
|
||||
$socid=0;
|
||||
if ($user->societe_id > 0) $socid = $user->societe_id;
|
||||
@ -337,7 +336,7 @@ if ($action == 'update' && ! $_POST["cancel"])
|
||||
{
|
||||
$edituser->entity = (empty($_POST["entity"]) ? 0 : $_POST["entity"]);
|
||||
}
|
||||
|
||||
|
||||
if (GETPOST('deletephoto')) $edituser->photo='';
|
||||
if (! empty($_FILES['photo']['name'])) $edituser->photo = dol_sanitizeFileName($_FILES['photo']['name']);
|
||||
|
||||
@ -410,6 +409,8 @@ if ($action == 'update' && ! $_POST["cancel"])
|
||||
$edituser = new User($db);
|
||||
$edituser->fetch($id);
|
||||
|
||||
$edituser->oldcopy=dol_clone($edituser);
|
||||
|
||||
$ret=$edituser->setPassword($user,$_POST["password"]);
|
||||
if ($ret < 0)
|
||||
{
|
||||
@ -509,7 +510,7 @@ if ($action == 'adduserldap')
|
||||
|
||||
|
||||
/*
|
||||
* Affichage page
|
||||
* View
|
||||
*/
|
||||
|
||||
llxHeader('',$langs->trans("UserCard"));
|
||||
@ -860,9 +861,9 @@ if (($action == 'create') || ($action == 'adduserldap'))
|
||||
print '<td><input size="30" type="text" name="phenix_pass" value="'.$_POST["phenix_pass"].'"></td></tr>';
|
||||
}
|
||||
print "</table>\n";
|
||||
|
||||
|
||||
print '<center><br><input class="button" value="'.$langs->trans("CreateUser").'" name="create" type="submit"></center>';
|
||||
|
||||
|
||||
print "</form>";
|
||||
}
|
||||
else
|
||||
@ -923,9 +924,7 @@ else
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Affichage onglets
|
||||
*/
|
||||
// Show tabs
|
||||
$head = user_prepare_head($fuser);
|
||||
|
||||
$title = $langs->trans("User");
|
||||
|
||||
@ -52,6 +52,7 @@ if (! $sortorder) $sortorder="ASC";
|
||||
$userstatic=new User($db);
|
||||
$companystatic = new Societe($db);
|
||||
|
||||
|
||||
/*
|
||||
* View
|
||||
*/
|
||||
@ -81,8 +82,8 @@ if ($_POST["search_user"])
|
||||
{
|
||||
$sql.= " AND (u.login like '%".$_POST["search_user"]."%' OR u.name like '%".$_POST["search_user"]."%' OR u.firstname like '%".$_POST["search_user"]."%')";
|
||||
}
|
||||
if ($sall) $sql.= " AND (u.login like '%".$sall."%' OR u.name like '%".$sall."%' OR u.firstname like '%".$sall."%' OR u.email like '%".$sall."%' OR u.note like '%".$sall."%')";
|
||||
if ($sortfield) $sql.=" ORDER BY $sortfield $sortorder";
|
||||
if ($sall) $sql.= " AND (u.login like '%".$db->escape($sall)."%' OR u.name like '%".$db->escape($sall)."%' OR u.firstname like '%".$db->escape($sall)."%' OR u.email like '%".$db->escape($sall)."%' OR u.note like '%".$db->escape($sall)."%')";
|
||||
$sql.=$db->order($sortfield,$sortorder);
|
||||
|
||||
$result = $db->query($sql);
|
||||
if ($result)
|
||||
|
||||
@ -29,7 +29,7 @@ require_once(DOL_DOCUMENT_ROOT."/user/class/user.class.php");
|
||||
$langs->load("users");
|
||||
|
||||
// Security check
|
||||
$id = GETPOST('id');
|
||||
$id = GETPOST('id','int');
|
||||
$fuser = new User($db);
|
||||
$fuser->fetch($id);
|
||||
|
||||
|
||||
@ -26,7 +26,7 @@ require("../main.inc.php");
|
||||
require_once(DOL_DOCUMENT_ROOT.'/core/lib/usergroups.lib.php');
|
||||
require_once(DOL_DOCUMENT_ROOT.'/user/class/user.class.php');
|
||||
|
||||
$id = GETPOST('id');
|
||||
$id = GETPOST('id','int');
|
||||
$action = GETPOST('action');
|
||||
|
||||
$langs->load("companies");
|
||||
|
||||
@ -35,7 +35,7 @@ $langs->load("languages");
|
||||
// Defini si peux lire/modifier permisssions
|
||||
$canreaduser=($user->admin || $user->rights->user->user->lire);
|
||||
|
||||
$id = GETPOST('id');
|
||||
$id = GETPOST('id','int');
|
||||
$action = GETPOST('action');
|
||||
|
||||
if ($id)
|
||||
|
||||
@ -30,7 +30,7 @@ require_once(DOL_DOCUMENT_ROOT."/core/lib/usergroups.lib.php");
|
||||
$langs->load("users");
|
||||
$langs->load("admin");
|
||||
|
||||
$id=GETPOST("id");
|
||||
$id=GETPOST('id','int');
|
||||
$action=GETPOST("action");
|
||||
$confirm=GETPOST("confirm");
|
||||
$module=GETPOST("module");
|
||||
|
||||
Loading…
Reference in New Issue
Block a user