diff --git a/htdocs/admin/modules.php b/htdocs/admin/modules.php index 49526696157..18546d67dc1 100644 --- a/htdocs/admin/modules.php +++ b/htdocs/admin/modules.php @@ -79,9 +79,9 @@ $familyinfo=array( $param=''; if ($search_keyword) $param.='&search_keyword='.urlencode($search_keyword); -if ($search_status) $param.='&search_status='.urlencode($search_status); -if ($search_nature) $param.='&search_nature='.urlencode($search_nature); -if ($search_version) $param.='&search_version='.urlencode($search_version); +if ($search_status > -1) $param.='&search_status='.urlencode($search_status); +if ($search_nature > -1) $param.='&search_nature='.urlencode($search_nature); +if ($search_version > -1) $param.='&search_version='.urlencode($search_version); $dirins=DOL_DOCUMENT_ROOT.'/custom'; $urldolibarrmodules='https://www.dolistore.com/'; @@ -691,7 +691,8 @@ if ($mode == 'common') } else if (! empty($objMod->always_enabled) || ((! empty($conf->multicompany->enabled) && $objMod->core_enabled) && ($user->entity || $conf->entity!=1))) { - print $langs->trans("Required"); + if ($objMod->alreadyUsed()) print $langs->trans("Used"); + else print $langs->trans("Required"); if (! empty($conf->multicompany->enabled) && $user->entity) $disableSetup++; } else diff --git a/htdocs/blockedlog/admin/blockedlog.php b/htdocs/blockedlog/admin/blockedlog.php index 5aa202e2806..091e520c333 100644 --- a/htdocs/blockedlog/admin/blockedlog.php +++ b/htdocs/blockedlog/admin/blockedlog.php @@ -30,7 +30,7 @@ $langs->load("admin"); $langs->load("other"); $langs->load("blockedlog"); -if (! $user->admin) accessforbidden(); +if (! $user->admin || empty($conf->blockedlog->enabled)) accessforbidden(); $action = GETPOST('action','alpha'); $backtopage = GETPOST('backtopage', 'alpha'); @@ -76,9 +76,8 @@ if (preg_match('/del_(.*)/',$action,$reg)) * View */ -$block_static = new BlockedLog($db); - $form=new Form($db); +$block_static = new BlockedLog($db); llxHeader('',$langs->trans("BlockedLogSetup")); @@ -107,8 +106,7 @@ print ''; if (!empty($conf->global->BLOCKEDLOG_USE_REMOTE_AUTHORITY)) { // Example with a yes / no select - $var=!$var; - print ''; + print ''; print ''.$langs->trans("BlockedLogAuthorityUrl").img_info($langs->trans('BlockedLogAuthorityNeededToStoreYouFingerprintsInNonAlterableRemote')).''; print ''; print '
'; diff --git a/htdocs/blockedlog/admin/blockedlog_list.php b/htdocs/blockedlog/admin/blockedlog_list.php index ee54f18348d..5caf9ef501c 100644 --- a/htdocs/blockedlog/admin/blockedlog_list.php +++ b/htdocs/blockedlog/admin/blockedlog_list.php @@ -59,12 +59,12 @@ $pagenext = $page + 1; if (empty($sortfield)) $sortfield='rowid'; if (empty($sortorder)) $sortorder='DESC'; - - - $block_static = new BlockedLog($db); +$result = restrictedArea($user, 'blockedlog', 0, ''); + + /* * Actions */ @@ -335,8 +335,10 @@ jQuery(document).ready(function () { for(x in data) { value = data[x]; - $("#pop-info table tbody").append(""+prefix+x+""+value+""); - if( (typeof value === "object") && (value !== null) ) { + if (typeof value != "object") { + $("#pop-info table tbody").append(""+prefix+x+""+value+""); + } + if ((typeof value === "object") && (value !== null)) { drawData(value, prefix+x+" >> "); } } diff --git a/htdocs/blockedlog/ajax/block-add.php b/htdocs/blockedlog/ajax/block-add.php index c82eac81e7b..24fd71f0514 100644 --- a/htdocs/blockedlog/ajax/block-add.php +++ b/htdocs/blockedlog/ajax/block-add.php @@ -19,7 +19,7 @@ /** * \file htdocs/blockedlog/ajax/block-add.php * \ingroup blockedlog - * \brief Block-add + * \brief block-add */ diff --git a/htdocs/blockedlog/ajax/block-info.php b/htdocs/blockedlog/ajax/block-info.php index 83317f33d57..888f9385630 100644 --- a/htdocs/blockedlog/ajax/block-info.php +++ b/htdocs/blockedlog/ajax/block-info.php @@ -39,7 +39,7 @@ require_once DOL_DOCUMENT_ROOT.'/blockedlog/class/blockedlog.class.php'; $id = GETPOST('id'); $block = new BlockedLog($db); -if($block->fetch($id)>0) { +if ($block->fetch($id)>0) { echo json_encode($block->object_data); } else { diff --git a/htdocs/blockedlog/class/blockedlog.class.php b/htdocs/blockedlog/class/blockedlog.class.php index 621ee254a48..bf9f59f14e2 100644 --- a/htdocs/blockedlog/class/blockedlog.class.php +++ b/htdocs/blockedlog/class/blockedlog.class.php @@ -29,6 +29,11 @@ class BlockedLog * @var int */ public $id; + /** + * Entity + * @var int + */ + public $entity; public $error = ''; public $errors = array(); @@ -147,6 +152,21 @@ class BlockedLog $this->error++; } } + else if ($this->action == 'MODULE_SET') + { + return 'System to track events into unalterable logs were enabled'; + } + else if ($this->action == 'MODULE_RESET') + { + if ($this->signature == '0000000000') + { + return 'System to track events into unalterable logs were disabled after some recording were done. We saved a special Fingerprint to track the chain as broken.'; + } + else + { + return 'System to track events into unalterable logs were disabled. This is possible because no record were done yet.'; + } + } return ''.$langs->trans('ImpossibleToReloadObject', $this->element, $this->fk_object).''; @@ -178,9 +198,10 @@ class BlockedLog /** * Populate properties of log from object data * - * @param Object $object object to store - * @param string $action action - * @param string $amounts amounts + * @param Object $object object to store + * @param string $action action + * @param string $amounts amounts + * @return int >0 if OK, <0 if KO */ public function setObjectData(&$object, $action, $amounts) { @@ -214,9 +235,7 @@ class BlockedLog $this->object_data=new stdClass(); // Add thirdparty info - if (empty($object->thirdparty) && method_exists($object, 'fetch_thirdparty')) $object->fetch_thirdparty(); - if (! empty($object->thirdparty)) { $this->object_data->thirdparty = new stdClass(); @@ -249,7 +268,6 @@ class BlockedLog } // Add user info - $this->fk_user = $user->id; $this->user_fullname = $user->getFullName($langs); @@ -257,42 +275,97 @@ class BlockedLog if ($this->element == 'facture') { - $this->object_data->total_ht = (double) $object->total_ht; - $this->object_data->total_tva = (double) $object->total_tva; - $this->object_data->total_ttc = (double) $object->total_ttc; - $this->object_data->total_localtax1 = (double) $object->total_localtax1; - $this->object_data->total_localtax2 = (double) $object->total_localtax2; - - $this->object_data->revenue_stamp = (double) $object->revenue_stamp; - $this->object_data->date_pointoftax = (double) $object->date_pointoftax; - $this->object_data->note_public = (double) $object->note_public; - } - if($this->element == 'invoice_supplier') { - if(empty($object->thirdparty))$object->fetch_thirdparty(); - $this->object_data->thirdparty = new stdClass(); - - foreach($object->thirdparty as $key=>$value) { - if(!is_object($value)) $this->object_data->thirdparty->{$key} = $value; + foreach($object as $key=>$value) + { + if (in_array($key, array('fields'))) continue; // Discard some properties + if (! in_array($key, array( + 'ref','facnumber','ref_client','ref_supplier','datef','type','total_ht','total_tva','total_ttc','localtax1','localtax2','revenuestamp','datepointoftax','note_public' + ))) continue; // Discard if not into a dedicated list + if (!is_object($value)) $this->object_data->{$key} = $value; + } + } + elseif ($this->element == 'invoice_supplier') + { + foreach($object as $key=>$value) + { + if (in_array($key, array('fields'))) continue; // Discard some properties + if (! in_array($key, array( + 'ref','facnumber','ref_client','ref_supplier','datef','type','total_ht','total_tva','total_ttc','localtax1','localtax2','revenuestamp','datepointoftax','note_public' + ))) continue; // Discard if not into a dedicated list + if (!is_object($value)) $this->object_data->{$key} = $value; } - - $this->object_data->total_ht = (double) $object->total_ht; - $this->object_data->total_tva = (double) $object->total_tva; - $this->object_data->total_ttc = (double) $object->total_ttc; - $this->object_data->total_localtax1 = (double) $object->total_localtax1; - $this->object_data->total_localtax2 = (double) $object->total_localtax2; - - $this->object_data->revenue_stamp = (double) $object->revenue_stamp; - $this->object_data->date_pointoftax = (double) $object->date_pointoftax; - $this->object_data->note_public = (double) $object->note_public; } elseif ($this->element == 'payment'|| $object->element == 'payment_supplier') { - $this->object_data->amounts = $object->amounts; + //var_dump($object); + $this->object_data->ref = $object->ref; + $this->object_data->date = $object->datepaye; + $this->object_data->type_code = dol_getIdFromCode($this->db, $object->paiementid, 'c_paiement', 'id', 'code'); + $this->object_data->payment_num = $object->num_paiement; + //$this->object_data->fk_account = $object->fk_account; + $this->object_data->note = $object->note; + //var_dump($this->object_data);exit; + + $paymentpartnumber=0; + foreach($object->amounts as $invoiceid => $amount) + { + if ($this->element == 'payment_supplier') + { + $tmpinvoice = new FactureFournisseur($this->db); + } + else + { + $tmpinvoice = new Facture($this->db); + } + $result = $tmpinvoice->fetch($invoiceid); + if ($result <= 0) + { + $this->error = $tmpinvoice->error; + $this->errors = $tmpinvoice->errors; + return -1; + } + $result = $tmpinvoice->fetch_thirdparty(); + if ($result <= 0) + { + $this->error = $tmpinvoice->error; + $this->errors = $tmpinvoice->errors; + return -1; + } + + $paymentpart = new stdClass(); + $paymentpart->amount = $amount; + + $paymentpart->thirdparty = new stdClass(); + foreach($tmpinvoice->thirdparty as $key=>$value) + { + if (in_array($key, array('fields'))) continue; // Discard some properties + if (! in_array($key, array( + 'name','name_alias','ref_ext','address','zip','town','state_code','country_code','idprof1','idprof2','idprof3','idprof4','idprof5','idprof6','phone','fax','email','barcode', + 'tva_intra', 'localtax1_assuj', 'localtax1_value', 'localtax2_assuj', 'localtax2_value', 'managers', 'capital', 'typent_code', 'forme_juridique_code', 'code_client', 'code_fournisseur' + ))) continue; // Discard if not into a dedicated list + if (!is_object($value)) $paymentpart->thirdparty->{$key} = $value; + } + + $paymentpart->invoice = new stdClass(); + foreach($tmpinvoice as $key=>$value) + { + if (in_array($key, array('fields'))) continue; // Discard some properties + if (! in_array($key, array( + 'ref','facnumber','ref_client','ref_supplier','datef','type','total_ht','total_tva','total_ttc','localtax1','localtax2','revenuestamp','datepointoftax','note_public' + ))) continue; // Discard if not into a dedicated list + if (!is_object($value)) $paymentpart->invoice->{$key} = $value; + } + + $paymentpartnumber++; + $this->object_data->payment_part[$paymentpartnumber] = $paymentpart; + } } elseif($this->element == 'payment_salary') { $this->object_data->amounts = array($object->amount); } + + return 1; } /** @@ -315,7 +388,8 @@ class BlockedLog $langs->load("blockedlog"); - $sql = "SELECT b.rowid, b.date_creation, b.signature, b.signature_line, b.amounts, b.action, b.element, b.fk_object, b.certified, b.tms, b.fk_user, b.user_fullname, b.date_object, b.ref_object, b.object_data"; + $sql = "SELECT b.rowid, b.date_creation, b.signature, b.signature_line, b.amounts, b.action, b.element, b.fk_object, b.entity,"; + $sql.= " b.certified, b.tms, b.fk_user, b.user_fullname, b.date_object, b.ref_object, b.object_data"; $sql.= " FROM ".MAIN_DB_PREFIX."blockedlog as b"; if ($id) $sql.= " WHERE b.rowid = ". $id; @@ -327,6 +401,7 @@ class BlockedLog $obj = $this->db->fetch_object($resql); $this->id = $obj->rowid; + $this->entity = $obj->entity; $this->ref = $obj->rowid; $this->date_creation = $this->db->jdate($obj->date_creation); @@ -383,10 +458,11 @@ class BlockedLog /** * Create blocked log in database. * - * @param User $user Object user that create - * @return int <0 if KO, >0 if OK + * @param User $user Object user that create + * @param int $forcesignature Force signature (for example '0000000000' when we disabled the module) + * @return int <0 if KO, >0 if OK */ - public function create($user) { + public function create($user, $forcesignature='') { global $conf,$langs,$hookmanager; @@ -400,14 +476,14 @@ class BlockedLog dol_syslog(get_class($this).'::create action='.$this->action.' fk_user='.$this->fk_user.' user_fullname='.$this->user_fullname, LOG_DEBUG); // Check parameters/properties - if (is_null($this->amounts)) + if (! isset($this->amounts)) // amount can be 0 for some events (like when module is disabled) { $this->error=$langs->trans("BlockLogNeedAmountsValue"); dol_syslog($this->error, LOG_WARNING); return -1; } - if(empty($this->element)) { + if (empty($this->element)) { $this->error=$langs->trans("BlockLogNeedElement"); dol_syslog($this->error, LOG_WARNING); return -2; @@ -429,6 +505,7 @@ class BlockedLog $this->signature_line = dol_hash($keyforsignature, '5'); // Not really usefull $this->signature = dol_hash($previoushash . $keyforsignature, '5'); + if ($forcesignature) $this->signature = $forcesignature; //var_dump($keyforsignature);var_dump($previoushash);var_dump($this->signature_line);var_dump($this->signature); $sql = "INSERT INTO ".MAIN_DB_PREFIX."blockedlog ("; @@ -460,7 +537,7 @@ class BlockedLog $sql.= "0,"; $sql.= $this->fk_user.","; $sql.= "'".$this->db->escape($this->user_fullname)."',"; - $sql.= $conf->entity; + $sql.= ($this->entity ? $this->entity : $conf->entity); $sql.= ")"; $res = $this->db->query($sql); @@ -544,7 +621,8 @@ class BlockedLog $previoussignature=''; - $sql="SELECT rowid, signature FROM ".MAIN_DB_PREFIX."blockedlog WHERE entity=".$conf->entity; + $sql = "SELECT rowid, signature FROM ".MAIN_DB_PREFIX."blockedlog"; + $sql.= " WHERE entity=".$conf->entity; if ($beforeid) $sql.= " AND rowid < ".(int) $beforeid; $sql.=" ORDER BY rowid DESC LIMIT 1"; $sql.=($withlock ? " FOR UPDATE ": ""); @@ -611,7 +689,7 @@ class BlockedLog } else{ $sql="SELECT rowid FROM ".MAIN_DB_PREFIX."blockedlog - WHERE element='".$element."' AND fk_object=".(int) $fk_object; + WHERE entity=".$conf->entity." AND element='".$element."' AND fk_object=".(int) $fk_object; } if ($search_start > 0) $sql.=" AND date_creation >= '".$this->db->idate($search_start)."'"; @@ -649,7 +727,7 @@ class BlockedLog } /** - * Return the signature (hash) of the "genesis-block" (Block 0) + * Return the signature (hash) of the "genesis-block" (Block 0). * * @return string Signature of genesis-block for current conf->entity */ @@ -671,5 +749,35 @@ class BlockedLog return $conf->global->BLOCKEDLOG_ENTITY_FINGERPRINT; } + + /** + * Check if module was already used or not for at least one recording. + * + * @param int $ignoresystem Ignore system events for the test + */ + function alreadyUsed($ignoresystem=0) + { + global $conf; + + $result = false; + + $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."blockedlog"; + $sql.= " WHERE entity = ".$conf->entity; + if ($ignoresystem) $sql.=" AND action not in ('MODULE_SET','MODULE_RESET')"; + $sql.= $this->db->plimit(1); + + $res = $this->db->query($sql); + if ($res!==false) + { + $obj = $this->db->fetch_object($res); + if ($obj) $result = true; + } + else dol_print_error($this->db); + + dol_syslog("Module Blockedlog alreadyUsed with ignoresystem=".$ignoresystem." is ".$result); + + return $result; + } + } diff --git a/htdocs/blockedlog/lib/blockedlog.lib.php b/htdocs/blockedlog/lib/blockedlog.lib.php index d377384f1c4..130ce9d19e0 100644 --- a/htdocs/blockedlog/lib/blockedlog.lib.php +++ b/htdocs/blockedlog/lib/blockedlog.lib.php @@ -28,7 +28,7 @@ */ function blockedlogadmin_prepare_head() { - global $langs, $conf; + global $db, $langs, $conf; $h = 0; $head = array(); @@ -40,6 +40,13 @@ function blockedlogadmin_prepare_head() $head[$h][0] = DOL_URL_ROOT."/blockedlog/admin/blockedlog_list.php"; $head[$h][1] = $langs->trans("Fingerprints"); + + require_once DOL_DOCUMENT_ROOT.'/blockedlog/class/blockedlog.class.php'; + $b=new BlockedLog($db); + if ($b->alreadyUsed()) + { + $head[$h][1].=' ...'; + } $head[$h][2] = 'fingerprints'; $h++; diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 61f85b88a12..01f064c3934 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -6127,15 +6127,15 @@ function dol_osencode($str) * Store also Code-Id into a cache to speed up next request on same key. * * @param DoliDB $db Database handler - * @param string $key Code or Id to get Id or Code + * @param string $key Code or Id to get Id or Code * @param string $tablename Table name without prefix - * @param string $fieldkey Field for code - * @param string $fieldid Field for id + * @param string $fieldkey Field to search the key into + * @param string $fieldid Field to get * @param int $entityfilter Filter by entity * @return int <0 if KO, Id of code if OK * @see $langs->getLabelFromKey */ -function dol_getIdFromCode($db,$key,$tablename,$fieldkey='code',$fieldid='id',$entityfilter=0) +function dol_getIdFromCode($db, $key, $tablename, $fieldkey='code', $fieldid='id', $entityfilter=0) { global $cache_codes; diff --git a/htdocs/core/lib/usergroups.lib.php b/htdocs/core/lib/usergroups.lib.php index 6fe236d6b41..b8833e42543 100644 --- a/htdocs/core/lib/usergroups.lib.php +++ b/htdocs/core/lib/usergroups.lib.php @@ -224,7 +224,7 @@ function group_prepare_head($object) if ($canreadperms) { $head[$h][0] = DOL_URL_ROOT.'/user/group/perms.php?id='.$object->id; - $head[$h][1] = $langs->trans("GroupRights"); + $head[$h][1] = $langs->trans("GroupRights"). ' '.($object->nb_rights).''; $head[$h][2] = 'rights'; $h++; } @@ -267,7 +267,7 @@ function user_admin_prepare_head() $head[$h][2] = 'attributes'; $h++; - $head[$h][0] = DOL_URL_ROOT.'/user/admin/group_extrafields.php'; + $head[$h][0] = DOL_URL_ROOT.'/user/admin/group_extrafields.php'; $head[$h][1] = $langs->trans("ExtraFields")." ".$langs->trans("Groups"); $head[$h][2] = 'attributes_group'; $h++; diff --git a/htdocs/core/modules/DolibarrModules.class.php b/htdocs/core/modules/DolibarrModules.class.php index 0155634ed25..c8fd99339e7 100644 --- a/htdocs/core/modules/DolibarrModules.class.php +++ b/htdocs/core/modules/DolibarrModules.class.php @@ -1666,7 +1666,7 @@ class DolibarrModules // Can not be abstract, because we need to insta $r_def = $this->rights[$key][3]; $r_perms = $this->rights[$key][4]; $r_subperms = isset($this->rights[$key][5])?$this->rights[$key][5]:''; - $r_modul = $this->rights_class; + $r_modul = empty($this->rights_class)?strtolower($this->name):$this->rights_class; if (empty($r_type)) $r_type='w'; diff --git a/htdocs/core/modules/modBlockedLog.class.php b/htdocs/core/modules/modBlockedLog.class.php index 95d1933cc89..56a9191866f 100644 --- a/htdocs/core/modules/modBlockedLog.class.php +++ b/htdocs/core/modules/modBlockedLog.class.php @@ -36,10 +36,12 @@ class modBlockedLog extends DolibarrModules */ function __construct($db) { - global $langs,$conf,$mysoc; + global $langs, $conf, $mysoc; $this->db = $db; $this->numero = 3200; + // Key text used to identify module (for permissions, menus, etc...) + $this->rights_class = 'blockedlog'; // Family can be 'crm','financial','hr','projects','products','ecm','technic','other' // It is used to group modules in module setup page @@ -77,17 +79,27 @@ class modBlockedLog extends DolibarrModules // Currently, activation is not automatic because only companies (in France) making invoices to non business customers must // enable this module. - // It is automatic only if $conf->global->BLOCKEDLOG_DISABLE_NOT_ALLOWED_FOR_COUNTRY is on. - if (! empty($conf->global->BLOCKEDLOG_DISABLE_NOT_ALLOWED_FOR_COUNTRY)) + /*if (! empty($conf->global->BLOCKEDLOG_DISABLE_NOT_ALLOWED_FOR_COUNTRY)) { - $this->automatic_activation = array('FR'=>'BlockedLogActivatedBecauseRequiredByYourCountryLegislation'); - } + $tmp=explode(',', $conf->global->BLOCKEDLOG_DISABLE_NOT_ALLOWED_FOR_COUNTRY); + $this->automatic_activation = array(); + foreach($tmp as $key) + { + $this->automatic_activation[$key]='BlockedLogActivatedBecauseRequiredByYourCountryLegislation'; + } + }*/ + //var_dump($this->automatic_activation); - $this->always_enabled = !empty($conf->blockedlog->enabled) && !empty($conf->global->BLOCKEDLOG_DISABLE_NOT_ALLOWED_FOR_COUNTRY) && in_array($mysoc->country_code, explode(',', $conf->global->BLOCKEDLOG_DISABLE_NOT_ALLOWED_FOR_COUNTRY)); + $this->always_enabled = (!empty($conf->blockedlog->enabled) + && !empty($conf->global->BLOCKEDLOG_DISABLE_NOT_ALLOWED_FOR_COUNTRY) + && in_array($mysoc->country_code, explode(',', $conf->global->BLOCKEDLOG_DISABLE_NOT_ALLOWED_FOR_COUNTRY)) + && $this->alreadyUsed(1)); // Constants //----------- - $this->const = array(); + $this->const = array( + 1=>array('BLOCKEDLOG_DISABLE_NOT_ALLOWED_FOR_COUNTRY', 'chaine', 'FR', 'This is list of country code where the module may be mandatory', 0, 'current', 0) + ); // New pages on tabs // ----------------- @@ -97,23 +109,76 @@ class modBlockedLog extends DolibarrModules //------ $this->boxes = array(); + // Permissions + $this->rights = array(); // Permission array used by this module + + $r=0; + $this->rights[$r][0] = $this->numero + $r; // Permission id (must not be already used) + $this->rights[$r][1] = 'Read archived events and fingerprints'; // Permission label + $this->rights[$r][3] = 0; // Permission by default for new user (0/1) + $this->rights[$r][4] = 'read'; // In php code, permission will be checked by test if ($user->rights->mymodule->level1->level2) + $this->rights[$r][5] = ''; + // Main menu entries //------------------ $this->menu = array(); } + /** * Check if module was already used before unactivation linked to warnings_unactivation property + * + * @return boolean True if already used, otherwise False */ function alreadyUsed() { - $res = $this->db->query("SELECT count(*) as nb FROM ".MAIN_DB_PREFIX."blockedlog"); - if($res!==false) { - $obj = $this->db->fetch_object($res); - return ($obj->nb > 0); + require_once DOL_DOCUMENT_ROOT.'/blockedlog/class/blockedlog.class.php'; + $b=new BlockedLog($this->db); + return $b->alreadyUsed(1); + } + + + /** + * Function called when module is enabled. + * The init function add constants, boxes, permissions and menus (defined in constructor) into Dolibarr database. + * It also creates data directories. + * + * @param string $options Options when enabling module ('', 'noboxes') + * @return int 1 if OK, 0 if KO + */ + function init($options='') + { + global $conf, $user; + + $sql = array(); + + // If already used, we add an entry to show we enable module + require_once DOL_DOCUMENT_ROOT.'/blockedlog/class/blockedlog.class.php'; + + $object=new stdClass; + $object->id = 1; + $object->element = 'module'; + $object->ref = 'systemevent'; + $object->entity = $conf->entity; + $object->date = dol_now(); + + $b=new BlockedLog($this->db); + $result = $b->setObjectData($object, 'MODULE_SET', 0); + if ($result < 0) + { + $this->error = $b->error; + $this->errors = $b->erros; + return 0; } - return false; + $res = $b->create($user); + if ($res<=0) { + $this->error = $b->error; + $this->errors = $b->errors; + return $res; + } + + return $this->_init($sql, $options); } /** @@ -126,26 +191,43 @@ class modBlockedLog extends DolibarrModules */ function remove($options = '') { - global $user; + global $conf, $user; - require_once DOL_DOCUMENT_ROOT.'/blockedlog/class/blockedlog.class.php'; + $sql = array(); - $object=new stdClass; + // If already used, we add an entry to show we enable module + require_once DOL_DOCUMENT_ROOT.'/blockedlog/class/blockedlog.class.php'; + + $object=new stdClass; $object->id = 1; $object->element = 'module'; - $object->ref = 'module'; + $object->ref = 'systemevent'; + $object->entity = $conf->entity; $object->date = dol_now(); $b=new BlockedLog($this->db); - $b->setObjectData($object, 'MODULE_RESET', -1); - - $res = $b->create($user); - if($res<=0) { + $result = $b->setObjectData($object, 'MODULE_RESET', 0); + if ($result < 0) + { $this->error = $b->error; - return $res; + $this->errors = $b->erros; + return 0; } - return $this->_remove(array(), $options); + if ($b->alreadyUsed(1)) + { + $res = $b->create($user, '0000000000'); // If already used for something else than SET or UNSET, we log with error + } + else + { + $res = $b->create($user); + } + if ($res<=0) { + $this->error = $b->error; + $this->errors = $b->errors; + return $res; + } + return $this->_remove($sql, $options); } } diff --git a/htdocs/core/triggers/interface_50_modBlockedlog_ActionsBlockedLog.class.php b/htdocs/core/triggers/interface_50_modBlockedlog_ActionsBlockedLog.class.php index 48ed23aba32..edb7772eb9c 100644 --- a/htdocs/core/triggers/interface_50_modBlockedlog_ActionsBlockedLog.class.php +++ b/htdocs/core/triggers/interface_50_modBlockedlog_ActionsBlockedLog.class.php @@ -56,15 +56,24 @@ class InterfaceActionsBlockedLog extends DolibarrTriggers dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); // Event/record is qualified - if ($action==='BILL_VALIDATE' || $action === 'BILL_PAYED' || $action==='BILL_UNPAYED' || $action==='BILL_DELETE' - || $action === 'BILL_SENTBYMAIL' || $action === 'DOC_DOWNLOAD' || $action === 'DOC_PREVIEW' - || $action === 'BILL_SUPPLIER_PAYED') + $qualified = 0; + if ($action==='BILL_VALIDATE' || $action==='BILL_DELETE' || $action === 'BILL_SENTBYMAIL' + || (in_array($object->element, array('facture','suplier_invoice')) && $action === 'DOC_DOWNLOAD') || (in_array($object->element, array('facture','suplier_invoice')) && $action === 'DOC_PREVIEW') + ) { + $qualified++; $amounts= (double) $object->total_ttc; } - else if ($action === 'PAYMENT_CUSTOMER_CREATE' || $action === 'PAYMENT_SUPPLIER_CREATE' + /*if ($action === 'BILL_PAYED' || $action==='BILL_UNPAYED' + || $action === 'BILL_SUPPLIER_PAYED' || $action === 'BILL_SUPPLIER_UNPAYED') + { + $qualified++; + $amounts= (double) $object->total_ttc; + }*/ + if ($action === 'PAYMENT_CUSTOMER_CREATE' || $action === 'PAYMENT_SUPPLIER_CREATE' || $action === 'PAYMENT_CUSTOMER_DELETE' || $action === 'PAYMENT_SUPPLIER_DELETE') // 'PAYMENT_ADD_TO_BANK' { + $qualified++; $amounts = 0; if(!empty($object->amounts)) { foreach($object->amounts as $amount) { @@ -72,22 +81,32 @@ class InterfaceActionsBlockedLog extends DolibarrTriggers } } } - else if (strpos($action,'PAYMENT')!==false && ! in_array($action, array('PAYMENT_ADD_TO_BANK'))) { + if (strpos($action,'PAYMENT')!==false && ! in_array($action, array('PAYMENT_ADD_TO_BANK'))) + { + $qualified++; $amounts= (double) $object->amount; } - else { + + if (! $qualified) + { return 0; // not implemented action log } $b=new BlockedLog($this->db); - $b->setObjectData($object, $action, $amounts); // Set field date_object, ref_object, fk_object, element, object_data + $result = $b->setObjectData($object, $action, $amounts); // Set field date_object, ref_object, fk_object, element, object_data + if ($result < 0) + { + $this->error = $b->error; + $this->errors = $b->erros; + return -1; + } $res = $b->create($user); if ($res<0) { - setEventMessage($b->error,'errors'); + setEventMessages($b->error, $b->errors, 'errors'); return -1; } else diff --git a/htdocs/install/upgrade2.php b/htdocs/install/upgrade2.php index 1a486cb34af..4e4269e3699 100644 --- a/htdocs/install/upgrade2.php +++ b/htdocs/install/upgrade2.php @@ -380,7 +380,9 @@ if (! GETPOST('action','aZ09') || preg_match('/upgrade/i',GETPOST('action','aZ09 if (versioncompare($versiontoarray,$afterversionarray) >= 0 && versioncompare($versiontoarray,$beforeversionarray) <= 0) { // Migrate contact association - migrate_event_assignement_contact($db,$langs,$conf); + migrate_event_assignement_contact($db,$langs,$conf); + + migrate_reset_blocked_log($db,$langs,$conf); } } @@ -3872,6 +3874,125 @@ function migrate_event_assignement_contact($db,$langs,$conf) print ''; } + +/** + * Migrate to reset the blocked log for V7+ algorithm + * + * @param DoliDB $db Database handler + * @param Translate $langs Object langs + * @param Conf $conf Object conf + * @return void + */ +function migrate_reset_blocked_log($db,$langs,$conf) +{ + require_once DOL_DOCUMENT_ROOT.'/blockedlog/class/blockedlog.class.php'; + + print ''; + + print '
'; + print ''.$langs->trans('MigrationResetBlockedLog')."
\n"; + + $error = 0; + + dolibarr_install_syslog("upgrade2::migrate_reset_blocked_log"); + + $db->begin(); + + $sqlSelect = "SELECT DISTINCT entity"; + $sqlSelect.= " FROM ".MAIN_DB_PREFIX."blockedlog"; + + //print $sqlSelect; + + $resql = $db->query($sqlSelect); + if ($resql) + { + $i = 0; + $num = $db->num_rows($resql); + + if ($num) + { + while ($i < $num) + { + $obj = $db->fetch_object($resql); + + print 'Process entity '.$obj->entity; + + $sqlSearch = "SELECT count(rowid) as nb FROM ".MAIN_DB_PREFIX."blockedlog WHERE action = 'MODULE_SET' and entity = ".$obj->entity; + $resqlSearch = $db->query($sqlSearch); + if ($resqlSearch) + { + $objSearch = $db->fetch_object($resqlSearch); + //var_dump($objSearch); + if ($objSearch && $objSearch->nb == 0) + { + print ' - Record for entity must be reset...'; + + $sqlUpdate = "DELETE FROM ".MAIN_DB_PREFIX."blockedlog"; + $sqlUpdate.= " WHERE entity = " . $obj->entity; + $resqlUpdate=$db->query($sqlUpdate); + if (! $resqlUpdate) + { + $error++; + dol_print_error($db); + } + else + { + // Add set line + $object=new stdClass; + $object->id = 1; + $object->element = 'module'; + $object->ref = 'systemevent'; + $object->entity = $obj->entity; + $object->date = dol_now(); + + $b=new BlockedLog($this->db); + $b->setObjectData($object, 'MODULE_SET', 0); + + $res = $b->create($user); + if ($res<=0) { + $this->error = $b->error; + $this->errors = $b->errors; + $error++; + } + } + } + else + { + print ' - '.$langs->trans('AlreadyInV7'); + } + } + else + { + dol_print_error($db); + } + + $i++; + } + } + else + { + print $langs->trans('NothingToDo')."
\n"; + } + + if (! $error) + { + $db->commit(); + } + else + { + $db->rollback(); + } + } + else + { + dol_print_error($db); + $db->rollback(); + } + + print ''; +} + + /** * Migrate to add entity value into llx_societe_remise * @@ -3946,7 +4067,6 @@ function migrate_remise_entity($db,$langs,$conf) $db->rollback(); } - print ''; } diff --git a/htdocs/langs/en_US/blockedlog.lang b/htdocs/langs/en_US/blockedlog.lang index 5b455fdd7b4..ca99d42a6bf 100644 --- a/htdocs/langs/en_US/blockedlog.lang +++ b/htdocs/langs/en_US/blockedlog.lang @@ -2,7 +2,7 @@ BlockedLog=Unalterable Logs Field=Field BlockedLogDesc=This module tracks some events into an unalterable log (that you can't modify once recorded) into a block chain, in real time. This module provides compatibility with requirements of laws of some countries (like France with the law Fincance 2016 - Norme NF535). Fingerprints=Archived events and fingerprints -FingerprintsDesc=Archived business events and fingerprints +FingerprintsDesc=This is the tool to browser the unalterable logs CompanyInitialKey=Company initial key (hash of genesis block) ShowAllFingerPrintsMightBeTooLong=Show all archived logs (might be long) ShowAllFingerPrintsErrorsMightBeTooLong=Show all archive logs with error (might be long) @@ -21,6 +21,8 @@ logBILL_UNPAYED=Customer bill set unpayed logBILL_VALIDATE=Customer bill validated logBILL_SENTBYMAIL=Customer bill send by mail logBILL_DELETE=Customer bill deleted +logMODULE_RESET=Module BlockedLog was disabled +logMODULE_SET=Module BlockedLog was enabled BlockedlogInfoDialog=Log Details Fingerprint=Fingerprint DownloadLogCSV=Download archive logs (CSV) @@ -30,4 +32,4 @@ DataOfArchivedEvent=Full datas of archived event ImpossibleToReloadObject=Object (type %s, id %s) removed (see 'Full data' link for unerasable saved data) BlockedLogAreRequiredByYourCountryLegislation=Unalterable Logs module may be required by the legislation of your country. Disabling this module may render any future transactions invalid with respect to the law and the use of legal software as they can not be validated by a tax audit. BlockedLogActivatedBecauseRequiredByYourCountryLegislation=Unalterable Logs module was activated because of the legislation of your country. Disabling this module may render any future transactions invalid with respect to the law and the use of legal software as they can not be validated by a tax audit. -BlockedLogDisableNotAllowedForCountry=Disable not allowed for this countries (just to prevent to disable the module by error, if your country is...) \ No newline at end of file +BlockedLogDisableNotAllowedForCountry=List of countries where usage of this module is mandatory (just to prevent to disable the module by error, if your country is in this list, disable of module is not possible without editing this list first) \ No newline at end of file diff --git a/htdocs/langs/en_US/install.lang b/htdocs/langs/en_US/install.lang index 7204938098b..87ef7d79b13 100644 --- a/htdocs/langs/en_US/install.lang +++ b/htdocs/langs/en_US/install.lang @@ -141,6 +141,7 @@ KeepDefaultValuesProxmox=You use the Dolibarr setup wizard from a Proxmox virtua UpgradeExternalModule=Run dedicated upgrade process of external modules SetAtLeastOneOptionAsUrlParameter=Set at least one option as a parameter in URL. For example: '...repair.php?standard=confirmed' NothingToDelete=Nothing to clean/delete +NothingToDo=Nothing to do ######### # upgrade MigrationFixData=Fix for denormalized data @@ -196,6 +197,7 @@ MigrationEventsContact=Migration of events to add event contact into assignement MigrationRemiseEntity=Update entity field value of llx_societe_remise MigrationRemiseExceptEntity=Update entity field value of llx_societe_remise_except MigrationReloadModule=Reload module %s +MigrationResetBlockedLog=Reset module BlockedLog for v7 algorithm ShowNotAvailableOptions=Show not available options HideNotAvailableOptions=Hide not available options ErrorFoundDuringMigration=Error were reported during migration process so next step is not available. To ignore errors, you can click here, but application or some features may not work correctly until fixed. diff --git a/htdocs/modulebuilder/template/core/modules/modMyModule.class.php b/htdocs/modulebuilder/template/core/modules/modMyModule.class.php index dd489b5b491..0dba5024136 100644 --- a/htdocs/modulebuilder/template/core/modules/modMyModule.class.php +++ b/htdocs/modulebuilder/template/core/modules/modMyModule.class.php @@ -299,12 +299,12 @@ class modMyModule extends DolibarrModules } /** - * Function called when module is enabled. - * The init function add constants, boxes, permissions and menus (defined in constructor) into Dolibarr database. - * It also creates data directories + * Function called when module is enabled. + * The init function add constants, boxes, permissions and menus (defined in constructor) into Dolibarr database. + * It also creates data directories * - * @param string $options Options when enabling module ('', 'noboxes') - * @return int 1 if OK, 0 if KO + * @param string $options Options when enabling module ('', 'noboxes') + * @return int 1 if OK, 0 if KO */ public function init($options='') { @@ -326,12 +326,12 @@ class modMyModule extends DolibarrModules } /** - * Function called when module is disabled. - * Remove from database constants, boxes and permissions from Dolibarr database. - * Data directories are not deleted + * Function called when module is disabled. + * Remove from database constants, boxes and permissions from Dolibarr database. + * Data directories are not deleted * - * @param string $options Options when enabling module ('', 'noboxes') - * @return int 1 if OK, 0 if KO + * @param string $options Options when enabling module ('', 'noboxes') + * @return int 1 if OK, 0 if KO */ public function remove($options = '') { diff --git a/htdocs/modulebuilder/template/myobject_list.php b/htdocs/modulebuilder/template/myobject_list.php index b33ab447592..7d0c5a7d26c 100644 --- a/htdocs/modulebuilder/template/myobject_list.php +++ b/htdocs/modulebuilder/template/myobject_list.php @@ -102,6 +102,7 @@ if ($user->societe_id > 0) //$socid = $user->societe_id; accessforbidden(); } +//$result = restrictedArea($user, 'mymodule', $id,''); // Initialize array of search criterias $search_all=trim(GETPOST("search_all",'alpha')); diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index c8a9a141aeb..5a103871058 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -727,19 +727,21 @@ class User extends CommonObject if ($perms) { if (! isset($this->rights) || ! is_object($this->rights)) $this->rights = new stdClass(); // For avoid error - if (! isset($this->rights->$module) || ! is_object($this->rights->$module)) $this->rights->$module = new stdClass(); - if ($subperms) + if ($module) { - if (! isset($this->rights->$module->$perms) || ! is_object($this->rights->$module->$perms)) $this->rights->$module->$perms = new stdClass(); - if(empty($this->rights->$module->$perms->$subperms)) $this->nb_rights++; - $this->rights->$module->$perms->$subperms = 1; + if (! isset($this->rights->$module) || ! is_object($this->rights->$module)) $this->rights->$module = new stdClass(); + if ($subperms) + { + if (! isset($this->rights->$module->$perms) || ! is_object($this->rights->$module->$perms)) $this->rights->$module->$perms = new stdClass(); + if(empty($this->rights->$module->$perms->$subperms)) $this->nb_rights++; + $this->rights->$module->$perms->$subperms = 1; + } + else + { + if(empty($this->rights->$module->$perms)) $this->nb_rights++; + $this->rights->$module->$perms = 1; + } } - else - { - if(empty($this->rights->$module->$perms)) $this->nb_rights++; - $this->rights->$module->$perms = 1; - } - } $i++; } diff --git a/htdocs/user/class/usergroup.class.php b/htdocs/user/class/usergroup.class.php index f16af4a4c48..f2ca661681f 100644 --- a/htdocs/user/class/usergroup.class.php +++ b/htdocs/user/class/usergroup.class.php @@ -50,6 +50,8 @@ class UserGroup extends CommonObject public $datem; // Modification date of group public $members=array(); // Array of users + public $nb_rights; // Number of rights granted to the user + private $_tab_loaded=array(); // Array of cache of already loaded permissions public $oldcopy; // To contains a clone of this when we need to save old properties of object @@ -63,6 +65,7 @@ class UserGroup extends CommonObject function __construct($db) { $this->db = $db; + $this->nb_rights = 0; return 0; } @@ -536,10 +539,12 @@ class UserGroup extends CommonObject if ($subperms) { if (! isset($this->rights->$module->$perms) || ! is_object($this->rights->$module->$perms)) $this->rights->$module->$perms = new stdClass(); + if(empty($this->rights->$module->$perms->$subperms)) $this->nb_rights++; $this->rights->$module->$perms->$subperms = 1; } else { + if(empty($this->rights->$module->$perms)) $this->nb_rights++; $this->rights->$module->$perms = 1; } } diff --git a/htdocs/user/group/card.php b/htdocs/user/group/card.php index 1b7be0b0a17..5a68dd1391b 100644 --- a/htdocs/user/group/card.php +++ b/htdocs/user/group/card.php @@ -60,6 +60,11 @@ if (! empty($conf->multicompany->enabled) && $conf->entity > 1 && $conf->global- } $object = new Usergroup($db); +if ($id > 0) +{ + $object->fetch($id); + $object->getrights(); +} $extrafields = new ExtraFields($db); // fetch optionals attributes and labels diff --git a/htdocs/user/group/perms.php b/htdocs/user/group/perms.php index 6c9e7d3966b..3b6d7037229 100644 --- a/htdocs/user/group/perms.php +++ b/htdocs/user/group/perms.php @@ -56,7 +56,6 @@ if (! $canreadperms) accessforbidden(); $object = new Usergroup($db); $object->fetch($id); -$object->getrights(); $entity=$conf->entity; @@ -73,19 +72,26 @@ $parameters=array(); $reshook=$hookmanager->executeHooks('doActions',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); -if (empty($reshook)) { +if (empty($reshook)) +{ if ($action == 'addrights' && $caneditperms) { $editgroup = new Usergroup($db); $result=$editgroup->fetch($id); - if ($result > 0) $editgroup->addrights($rights, $module, '', $entity); + if ($result > 0) + { + $editgroup->addrights($rights, $module, '', $entity); + } } if ($action == 'delrights' && $caneditperms) { $editgroup = new Usergroup($db); $result=$editgroup->fetch($id); - if ($result > 0) $editgroup->delrights($rights, $module, '', $entity); + if ($result > 0) + { + $editgroup->delrights($rights, $module, '', $entity); + } } } @@ -98,11 +104,13 @@ $form = new Form($db); llxHeader('',$langs->trans("Permissions")); -if ($object->id) +if ($object->id > 0) { - /* + /* * Affichage onglets */ + $object->getrights(); // Reload permission + $head = group_prepare_head($object); $title = $langs->trans("Group"); dol_fiche_head($head, 'rights', $title, -1, 'group'); @@ -239,7 +247,6 @@ if ($object->id) if ($result) { $i = 0; - $var = true; $oldmod = ''; $num = $db->num_rows($result); @@ -258,31 +265,30 @@ if ($object->id) if ($oldmod <> $obj->module) { $oldmod = $obj->module; - $var = !$var; // Rupture detectee, on recupere objMod $objMod = $modules[$obj->module]; $picto=($objMod->picto?$objMod->picto:'generic'); + print ''; + print ''.img_object('', $picto, 'class="inline-block pictoobjectwidth"').' '.$objMod->getName(); + print ' '; + print ''; if ($caneditperms) { - print ''; - print ''.img_object('',$picto).' '.$objMod->getName(); - print ' '; - print ''; - print 'module.'#'.$objMod->getName().'">'.$langs->trans("All").""; + print 'module.'#'.$objMod->getName().'">'.$langs->trans("All").""; print '/'; print 'module.'#'.$objMod->getName().'">'.$langs->trans("None").""; - print ''; - print ' '; - print ''; } + print ''; + print ' '; + print ''; } - print ''; + print ''; // Module - print ''.img_object('',$picto).' '.$objMod->getName().''; + print ''.img_object('', $picto, 'class="inline-block pictoobjectwidth"').' '.$objMod->getName().''; if (is_array($permsgroupbyentity[$entity])) { diff --git a/htdocs/user/perms.php b/htdocs/user/perms.php index e523d01009f..b83a6831053 100644 --- a/htdocs/user/perms.php +++ b/htdocs/user/perms.php @@ -282,7 +282,6 @@ if ($result) { $num = $db->num_rows($result); $i = 0; - $var = True; $oldmod=''; while ($i < $num) @@ -295,39 +294,37 @@ if ($result) $i++; continue; } - if (isset($obj->module) && ($oldmod <> $obj->module)) { $oldmod = $obj->module; - $var = !$var; - // Rupture detectee, on recupere objMod + // Break detected, we get objMod $objMod=$modules[$obj->module]; $picto=($objMod->picto?$objMod->picto:'generic'); - if ($caneditperms && (empty($objMod->rights_admin_allowed) || empty($object->admin))) - { - // On affiche ligne pour modifier droits - print ''; - print ''.img_object('',$picto,'class="pictoobjectwidth"').' '.$objMod->getName(); - print ''; - print ''; - print 'module.'">'.$langs->trans("All").""; - print '/'; - print 'module.'">'.$langs->trans("None").""; - print ''; - print ' '; - print ''."\n"; - } + // Show break line + print ''; + print ''.img_object('',$picto,'class="pictoobjectwidth"').' '.$objMod->getName(); + print ''; + print ''; + if ($caneditperms && empty($objMod->rights_admin_allowed) || empty($object->admin)) + { + print 'module.'">'.$langs->trans("All").""; + print '/'; + print 'module.'">'.$langs->trans("None").""; + } + print ''; + print ' '; + print ''."\n"; } - print ''; + print ''; // Picto and label of permission print ''.img_object('',$picto,'class="pictoobjectwidth"').' '.$objMod->getName().''; // Permission and tick - if (! empty($object->admin) && ! empty($objMod->rights_admin_allowed)) // Permission own because admin + if (! empty($object->admin) && ! empty($objMod->rights_admin_allowed)) // Permission granted because admin { if ($caneditperms) { @@ -337,7 +334,7 @@ if ($result) print img_picto($langs->trans("Active"),'tick'); print ''; } - else if (in_array($obj->id, $permsuser)) // Permission own by user + else if (in_array($obj->id, $permsuser)) // Permission granted by user { if ($caneditperms) { @@ -350,7 +347,7 @@ if ($result) else if (is_array($permsgroupbyentity[$entity])) { - if (in_array($obj->id, $permsgroupbyentity[$entity])) // Permission own by group + if (in_array($obj->id, $permsgroupbyentity[$entity])) // Permission granted by group { if ($caneditperms) {