Debug/rewrite Blockedlog

This commit is contained in:
Laurent Destailleur 2017-11-30 14:21:55 +01:00
parent 39fdd1b37d
commit 6796c08cb8
7 changed files with 213 additions and 145 deletions

View File

@ -38,6 +38,10 @@ $showonlyerrors = GETPOST('showonlyerrors','int');
$block_static = new BlockedLog($db); $block_static = new BlockedLog($db);
/*
* Actions
*/
if($action === 'downloadblockchain') { if($action === 'downloadblockchain') {
$auth = new BlockedLogAuthority($db); $auth = new BlockedLogAuthority($db);
@ -54,8 +58,11 @@ if($action === 'downloadblockchain') {
} }
else if($action === 'downloadcsv') { else if($action === 'downloadcsv') {
$res = $db->query("SELECT rowid,tms,action,amounts,element,fk_object,date_object,ref_object,signature,fk_user $sql = "SELECT rowid,date_creation,tms,user_fullname,action,amounts,element,fk_object,date_object,ref_object,signature,fk_user,object_data";
FROM ".MAIN_DB_PREFIX."blockedlog ORDER BY rowid ASC"); $sql.= " FROM ".MAIN_DB_PREFIX."blockedlog";
$sql.= " WHERE entity = ".$conf->entity;
$sql.= " ORDER BY rowid ASC";
$res = $db->query($sql);
if($res) { if($res) {
@ -63,32 +70,35 @@ else if($action === 'downloadcsv') {
header('Content-Type: application/octet-stream'); header('Content-Type: application/octet-stream');
header("Content-Transfer-Encoding: Binary"); header("Content-Transfer-Encoding: Binary");
header("Content-disposition: attachment; filename=\"" .$signature. ".csv\""); header("Content-disposition: attachment; filename=\"archive-log-" .$signature. ".csv\"");
print $langs->transnoentities('Id') print $langs->transnoentities('Id')
.';'.$langs->transnoentities('Timestamp') .';'.$langs->transnoentities('Date')
.';'.$langs->transnoentities('User')
.';'.$langs->transnoentities('Action') .';'.$langs->transnoentities('Action')
.';'.$langs->transnoentities('Amounts')
.';'.$langs->transnoentities('Element') .';'.$langs->transnoentities('Element')
.';'.$langs->transnoentities('Amounts')
.';'.$langs->transnoentities('ObjectId') .';'.$langs->transnoentities('ObjectId')
.';'.$langs->transnoentities('Date') .';'.$langs->transnoentities('Date')
.';'.$langs->transnoentities('Ref') .';'.$langs->transnoentities('Ref')
.';'.$langs->transnoentities('Fingerprint') .';'.$langs->transnoentities('Fingerprint')
.';'.$langs->transnoentities('User')."\n"; .';'.$langs->transnoentities('FullData')
."\n";
while($obj = $db->fetch_object($res)) { while($obj = $db->fetch_object($res)) {
print $obj->rowid print $obj->rowid
.';'.$obj->tms .';'.$obj->date_creation
.';"'.$obj->user_fullname.'"'
.';'.$obj->action .';'.$obj->action
.';'.$obj->amounts
.';'.$obj->element .';'.$obj->element
.';'.$obj->amounts
.';'.$obj->fk_object .';'.$obj->fk_object
.';'.$obj->date_object .';'.$obj->date_object
.';'.$obj->ref_object .';"'.$obj->ref_object.'"'
.';'.$obj->signature .';'.$obj->signature
.';'.$obj->fk_user."\n"; .';"'.str_replace('"','""',$obj->object_data).'"'
."\n";
} }
exit; exit;
@ -99,11 +109,12 @@ else if($action === 'downloadcsv') {
} }
/* /*
* View * View
*/ */
$blocks = $block_static->getLog('all', 0, GETPOST('all') ? 0 : 50); $blocks = $block_static->getLog('all', 0, GETPOST('all','alpha') ? 0 : 50);
$form=new Form($db); $form=new Form($db);
@ -144,12 +155,13 @@ print getTitleFieldOfList($langs->trans('Fingerprint'), 0, $_SERVER["PHP_SELF"],
print getTitleFieldOfList('<span id="blockchainstatus"></span>', 0, $_SERVER["PHP_SELF"],'','','','',$sortfield,$sortorder,'')."\n"; print getTitleFieldOfList('<span id="blockchainstatus"></span>', 0, $_SERVER["PHP_SELF"],'','','','',$sortfield,$sortorder,'')."\n";
print '</tr>'; print '</tr>';
$atleastoneerror=0;
foreach($blocks as &$block) { foreach($blocks as &$block) {
$checksignature = $block->checkSignature(); $checksignature = $block->checkSignature();
$object_link = $block->getObjectLink(); $object_link = $block->getObjectLink();
if(!$showonlyerrors || $block->error>0) { if (!$showonlyerrors || $block->error>0) {
print '<tr class="oddeven">'; print '<tr class="oddeven">';
print '<td>'.$block->id.'</td>'; print '<td>'.$block->id.'</td>';
@ -166,7 +178,16 @@ foreach($blocks as &$block) {
print '</td>'; print '</td>';
print '<td>'; print '<td>';
print $block->error == 0 ? img_picto($langs->trans('OkCheckFingerprintValidity'), 'tick') : img_picto($langs->trans('KoCheckFingerprintValidity'), 'statut8'); if (empty($block->error))
{
if (empty($atleastoneerror)) print img_picto($langs->trans('OkCheckFingerprintValidity'), 'statut4');
else print img_picto($langs->trans('OkCheckFingerprintValidityButChainIsKo'), 'statut1');
}
else
{
$atleastoneerror++;
print img_picto($langs->trans('KoCheckFingerprintValidity'), 'statut8');
}
if(!empty($conf->global->BLOCKEDLOG_USE_REMOTE_AUTHORITY) && !empty($conf->global->BLOCKEDLOG_AUTHORITY_URL)) { if(!empty($conf->global->BLOCKEDLOG_USE_REMOTE_AUTHORITY) && !empty($conf->global->BLOCKEDLOG_AUTHORITY_URL)) {
print ' '.($block->certified ? img_picto($langs->trans('AddedByAuthority'), 'info') : img_picto($langs->trans('NotAddedByAuthorityYet'), 'info_black') ); print ' '.($block->certified ? img_picto($langs->trans('AddedByAuthority'), 'info') : img_picto($langs->trans('NotAddedByAuthorityYet'), 'info_black') );

View File

@ -1,5 +1,6 @@
<?php <?php
/* Copyright (C) 2017 ATM Consulting <contact@atm-consulting.fr> /* Copyright (C) 2017 ATM Consulting <contact@atm-consulting.fr>
* Copyright (C) 2017 Laurent Destailleur <eldy@destailleur.fr>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -13,6 +14,8 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* See https://medium.com/@lhartikk/a-blockchain-in-200-lines-of-code-963cc1cc0e54
*/ */
/** /**
@ -176,12 +179,20 @@ class BlockedLog
* Populate properties of log from object data * Populate properties of log from object data
* *
* @param Object $object object to store * @param Object $object object to store
* @param string $action action
* @param string $amounts amounts
*/ */
public function setObjectData(&$object) public function setObjectData(&$object, $action, $amounts)
{ {
global $mysoc; global $user, $mysoc;
// Set date // Generic fields
// action
$this->action = $action;
// amount
$this->amounts= $amounts;
// date
if ($object->element == 'payment' || $object->element == 'payment_supplier') if ($object->element == 'payment' || $object->element == 'payment_supplier')
{ {
$this->date_object = $object->datepaye; $this->date_object = $object->datepaye;
@ -193,43 +204,67 @@ class BlockedLog
else { else {
$this->date_object = $object->date; $this->date_object = $object->date;
} }
// ref
$this->ref_object = $object->ref; $this->ref_object = $object->ref;
// type of object
$this->element = $object->element; $this->element = $object->element;
// id of object
$this->fk_object = $object->id; $this->fk_object = $object->id;
$this->object_data=new stdClass(); $this->object_data=new stdClass();
if ($this->element == 'facture') // Add thirdparty info
if (empty($object->thirdparty) && method_exists('fetch_thirdparty')) $object->fetch_thirdparty();
if (! empty($object->thirdparty))
{ {
if (empty($object->thirdparty)) $object->fetch_thirdparty();
$this->object_data->thirdparty = new stdClass(); $this->object_data->thirdparty = new stdClass();
foreach($object->thirdparty as $key=>$value) { foreach($object->thirdparty as $key=>$value)
if (in_array($key, array('fields')) continue; // Discard some properties {
if (in_array($key, array('fields'))) continue; // Discard some properties
if (! in_array($key, array( 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', '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' '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 ))) continue; // Discard if not into a dedicated list
if (!is_object($value)) $this->object_data->thirdparty->{$key} = $value; if (!is_object($value)) $this->object_data->thirdparty->{$key} = $value;
} }
}
foreach($mysoc as $key=>$value) { // Add company info
if (in_array($key, array('fields')) continue; // Discard some properties if (! empty($mysoc))
{
$this->object_data->mycompany = new stdClass();
foreach($mysoc as $key=>$value)
{
if (in_array($key, array('fields'))) continue; // Discard some properties
if (! in_array($key, array( 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', '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' '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 ))) continue; // Discard if not into a dedicated list
if (!is_object($value)) $this->object_data->mycompany->{$key} = $value; if (!is_object($value)) $this->object_data->mycompany->{$key} = $value;
} }
}
// Add user info
$this->fk_user = $user->id;
$this->user_fullname = $user->getFullName($langs);
// Field specific to object
if ($this->element == 'facture')
{
$this->object_data->total_ht = (double) $object->total_ht; $this->object_data->total_ht = (double) $object->total_ht;
$this->object_data->total_tva = (double) $object->total_tva; $this->object_data->total_tva = (double) $object->total_tva;
$this->object_data->total_ttc = (double) $object->total_ttc; $this->object_data->total_ttc = (double) $object->total_ttc;
$this->object_data->total_localtax1= (double) $object->total_localtax1; $this->object_data->total_localtax1 = (double) $object->total_localtax1;
$this->object_data->total_localtax2= (double) $object->total_localtax2; $this->object_data->total_localtax2 = (double) $object->total_localtax2;
$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; $this->object_data->note_public = (double) $object->note_public;
} }
if($this->element == 'invoice_supplier') { if($this->element == 'invoice_supplier') {
@ -243,11 +278,12 @@ class BlockedLog
$this->object_data->total_ht = (double) $object->total_ht; $this->object_data->total_ht = (double) $object->total_ht;
$this->object_data->total_tva = (double) $object->total_tva; $this->object_data->total_tva = (double) $object->total_tva;
$this->object_data->total_ttc = (double) $object->total_ttc; $this->object_data->total_ttc = (double) $object->total_ttc;
$this->object_data->total_localtax1= (double) $object->total_localtax1; $this->object_data->total_localtax1 = (double) $object->total_localtax1;
$this->object_data->total_localtax2= (double) $object->total_localtax2; $this->object_data->total_localtax2 = (double) $object->total_localtax2;
$this->object_data->note_public = (double) $object->note_public;
$this->object_data->note_private= (double) $object->note_private;
$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') elseif ($this->element == 'payment'|| $object->element == 'payment_supplier')
{ {
@ -279,7 +315,7 @@ class BlockedLog
$langs->load("blockedlog"); $langs->load("blockedlog");
$sql = "SELECT b.rowid, b.signature, b.amounts, b.action, b.element, b.fk_object, b.certified, b.tms, b.fk_user, 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.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"; $sql.= " FROM ".MAIN_DB_PREFIX."blockedlog as b";
if ($id) $sql.= " WHERE b.rowid = ". $id; if ($id) $sql.= " WHERE b.rowid = ". $id;
@ -293,7 +329,9 @@ class BlockedLog
$this->id = $obj->rowid; $this->id = $obj->rowid;
$this->ref = $obj->rowid; $this->ref = $obj->rowid;
$this->signature = $obj->signature; $this->date_creation = $this->db->jdate($obj->date_creation);
$this->tms = $this->db->jdate($obj->tms);
$this->amounts = (double) $obj->amounts; $this->amounts = (double) $obj->amounts;
$this->action = $obj->action; $this->action = $obj->action;
$this->element = $obj->element; $this->element = $obj->element;
@ -302,14 +340,15 @@ class BlockedLog
$this->date_object = $this->db->jdate($obj->date_object); $this->date_object = $this->db->jdate($obj->date_object);
$this->ref_object = $obj->ref_object; $this->ref_object = $obj->ref_object;
$this->certified = ($obj->certified == 1);
$this->fk_user = $obj->fk_user; $this->fk_user = $obj->fk_user;
$this->user_fullname = $obj->user_fullname;
$this->tms = $this->db->jdate($obj->tms);
$this->object_data = unserialize($obj->object_data); $this->object_data = unserialize($obj->object_data);
$this->signature = $obj->signature;
$this->signature_line = $obj->signature_line;
$this->certified = ($obj->certified == 1);
return 1; return 1;
} }
else else
@ -355,11 +394,12 @@ class BlockedLog
$error=0; $error=0;
dol_syslog(get_class($this).'::create', LOG_DEBUG); // Clean data
$this->amounts=(double) $this->amounts;
$this->getSignatureRecursive();
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 (is_null($this->amounts))
{ {
$this->error=$langs->trans("BlockLogNeedAmountsValue"); $this->error=$langs->trans("BlockLogNeedAmountsValue");
@ -373,18 +413,27 @@ class BlockedLog
return -2; return -2;
} }
if(empty($this->action)) { if (empty($this->action) || empty($this->fk_user) || empty($this->user_fullname)) {
$this->error=$langs->trans("BlockLogNeedAction"); $this->error=$langs->trans("BadParameterWhenCallingCreateOfBlockedLog");
dol_syslog($this->error, LOG_WARNING); dol_syslog($this->error, LOG_WARNING);
return -3; return -3;
} }
$this->fk_user = $user->id; $this->date_creation = dol_now();
$this->db->begin(); $this->db->begin();
$previoushash = $this->getPreviousHash(1); // This get last record and lock database until insert is done
$keyforsignature = $this->buildKeyForSignature();
$this->signature_line = dol_hash($keyforsignature, '5'); // Not really usefull
$this->signature = dol_hash($previoushash . $keyforsignature, '5');
//var_dump($keyforsignature);var_dump($previoushash);var_dump($this->signature_line);var_dump($this->signature);
$sql = "INSERT INTO ".MAIN_DB_PREFIX."blockedlog ("; $sql = "INSERT INTO ".MAIN_DB_PREFIX."blockedlog (";
$sql.= "action,"; $sql.= " date_creation,";
$sql.= " action,";
$sql.= " amounts,"; $sql.= " amounts,";
$sql.= " signature,"; $sql.= " signature,";
$sql.= " signature_line,"; $sql.= " signature_line,";
@ -395,19 +444,22 @@ class BlockedLog
$sql.= " object_data,"; $sql.= " object_data,";
$sql.= " certified,"; $sql.= " certified,";
$sql.= " fk_user,"; $sql.= " fk_user,";
$sql.= " user_fullname,";
$sql.= " entity"; $sql.= " entity";
$sql.= ") VALUES ("; $sql.= ") VALUES (";
$sql.= "'".$this->db->idate($this->date_creation)."',";
$sql.= "'".$this->db->escape($this->action)."',"; $sql.= "'".$this->db->escape($this->action)."',";
$sql.= "".$this->amounts.","; $sql.= $this->amounts.",";
$sql.= "'".$this->db->escape($this->signature)."',"; $sql.= "'".$this->db->escape($this->signature)."',";
$sql.= "'".$this->db->escape($this->signature_line)."',"; $sql.= "'".$this->db->escape($this->signature_line)."',";
$sql.= "'".$this->db->escape($this->element)."',"; $sql.= "'".$this->db->escape($this->element)."',";
$sql.= "".$this->fk_object.","; $sql.= $this->fk_object.",";
$sql.= "'".$this->db->idate($this->date_object)."',"; $sql.= "'".$this->db->idate($this->date_object)."',";
$sql.= "'".$this->db->escape($this->ref_object)."',"; $sql.= "'".$this->db->escape($this->ref_object)."',";
$sql.= "'".$this->db->escape(serialize($this->object_data))."',"; $sql.= "'".$this->db->escape(serialize($this->object_data))."',";
$sql.= "0,"; $sql.= "0,";
$sql.= "".$user->id.","; $sql.= $this->fk_user.",";
$sql.= "'".$this->db->escape($this->user_fullname)."',";
$sql.= $conf->entity; $sql.= $conf->entity;
$sql.= ")"; $sql.= ")";
@ -437,32 +489,28 @@ class BlockedLog
return -1; return -1;
} }
// The commit will release the lock so we can insert nex record
} }
/** /**
* return crypted value. * Check if current signature still correct compare to the chain
*
* @param string $value string to crypt
* @return string crypted string
*/
private function crypt($value) {
return hash('sha256',$value);
}
/**
* check if current signature still correct compare to the chain
* *
* @return boolean * @return boolean
*/ */
public function checkSignature() { public function checkSignature()
{
$signature_to_test = $this->signature; //$oldblockedlog = new BlockedLog($this->db);
//$previousrecord = $oldblockedlog->fetch($this->id - 1);
$previoushash = $this->getPreviousHash(0, $this->id);
$this->getSignatureRecursive(); // Recalculate hash
$keyforsignature = $this->buildKeyForSignature();
$signature_line = dol_hash($keyforsignature, '5'); // Not really usefull
$signature = dol_hash($previoushash . $keyforsignature, '5');
//var_dump($previoushash); var_dump($keyforsignature); var_dump($signature_line); var_dump($signature);
$res = ($signature_to_test === $this->signature); $res = ($signature === $this->signature);
if(!$res) { if(!$res) {
$this->error++; $this->error++;
@ -472,32 +520,60 @@ class BlockedLog
} }
/** /**
* set current signatures * Return a string for signature
*
* @return string Key for signature
*/ */
private function getSignatureRecursive(){ private function buildKeyForSignature()
{
//print_r($this->object_data);
return $this->date_creation.'|'.$this->action.'|'.$this->amounts.'|'.$this->ref_object.'|'.$this->date_object.'|'.$this->user_fullname.'|'.print_r($this->object_data, true);
}
$this->signature_line = $this->crypt( $this->action . $this->getSignature() . $this->amounts . print_r($this->object_data, true) );
/*if($this->signature=='d6320580a02c1ab67fcc0a6d49d453c7d96dda0148901736f7f55725bfe1b900' || $this->signature=='ea65d435ff12ca929936a406aa9d707d99fb334c127878d256b602a5541bbbc9') {
var_dump($this->signature_line,$this->action ,$this->getSignature() , $this->amounts , $this->object_data);
}*/
$this->signature = $this->signature_line;
$logs = $this->getLog('all', 0, 0, 1) ; /**
if($logs!==false) { * Get previous signature/hash in chain
foreach($logs as &$b) { *
* @param int $withlock 1=With a lock
* @param int $beforeid Before id
* @return string Hash of last record
*/
private function getPreviousHash($withlock=0, $beforeid=0)
{
global $conf;
if($this->id>0 && $b->id == $this->id) break; // on arrête sur un enregistrement précis pour recalculer une signature $previoussignature='';
$b->getCurrentValue(); // on récupère la valeur actuelle en base de l'élément enregistré $sql="SELECT rowid, signature FROM ".MAIN_DB_PREFIX."blockedlog WHERE entity=".$conf->entity;
if ($beforeid) $sql.= " AND rowid < ".(int) $beforeid;
$sql.=" ORDER BY rowid DESC LIMIT 1";
$sql.=($withlock ? " FOR UPDATE ": "");
$this->signature = $this->crypt($this->signature. $this->action . $b->signature . $b->amounts); $resql = $this->db->query($sql);
} if ($resql) {
} $obj = $this->db->fetch_object($resql);
if ($obj)
{
$previoussignature = $obj->signature;
}
}
else
{
dol_print_error($this->db);
exit;
}
if (empty($previoussignature))
{
// First signature line (line 0)
$previoussignature = $this->getSignature();
}
return $previoussignature;
} }
/** /**
* return log object for a element. * Return array of log objects (with criterias)
* *
* @param string $element element to search * @param string $element element to search
* @param int $fk_object id of object to search * @param int $fk_object id of object to search
@ -505,25 +581,25 @@ class BlockedLog
* @param string $order sort of query * @param string $order sort of query
* @return array array of object log * @return array array of object log
*/ */
public function getLog($element, $fk_object, $limit = 0, $order = -1) { public function getLog($element, $fk_object, $limit = 0, $order = -1)
global $conf,$cachedlogs ; {
global $conf, $cachedlogs;
/* $cachedlogs allow fastest search */ /* $cachedlogs allow fastest search */
if(empty($cachedlogs)) $cachedlogs=array(); if (empty($cachedlogs)) $cachedlogs=array();
if ($element=='all') {
if($element=='all') {
$sql="SELECT rowid FROM ".MAIN_DB_PREFIX."blockedlog $sql="SELECT rowid FROM ".MAIN_DB_PREFIX."blockedlog
WHERE entity=".$conf->entity; WHERE entity=".$conf->entity;
} }
else if($element=='not_certified') { else if ($element=='not_certified') {
$sql="SELECT rowid FROM ".MAIN_DB_PREFIX."blockedlog $sql="SELECT rowid FROM ".MAIN_DB_PREFIX."blockedlog
WHERE entity=".$conf->entity." AND certified = 0"; WHERE entity=".$conf->entity." AND certified = 0";
} }
else if($element=='just_certified') { else if ($element=='just_certified') {
$sql="SELECT rowid FROM ".MAIN_DB_PREFIX."blockedlog $sql="SELECT rowid FROM ".MAIN_DB_PREFIX."blockedlog
WHERE entity=".$conf->entity." AND certified = 1"; WHERE entity=".$conf->entity." AND certified = 1";
@ -531,7 +607,6 @@ class BlockedLog
else{ else{
$sql="SELECT rowid FROM ".MAIN_DB_PREFIX."blockedlog $sql="SELECT rowid FROM ".MAIN_DB_PREFIX."blockedlog
WHERE element='".$element."' AND fk_object=".(int) $fk_object; WHERE element='".$element."' AND fk_object=".(int) $fk_object;
} }
$sql.=($order<0 ? ' ORDER BY rowid DESC ' : ' ORDER BY rowid ASC '); $sql.=($order<0 ? ' ORDER BY rowid DESC ' : ' ORDER BY rowid ASC ');
@ -544,9 +619,9 @@ class BlockedLog
$results=array(); $results=array();
while($obj = $this->db->fetch_object($res)) { while ($obj = $this->db->fetch_object($res)) {
if(!isset($cachedlogs[$obj->rowid])) { if (!isset($cachedlogs[$obj->rowid])) {
$b=new BlockedLog($this->db); $b=new BlockedLog($this->db);
$b->fetch($obj->rowid); $b->fetch($obj->rowid);
@ -554,7 +629,6 @@ class BlockedLog
} }
$results[] = $cachedlogs[$obj->rowid]; $results[] = $cachedlogs[$obj->rowid];
} }
return $results; return $results;
@ -565,52 +639,19 @@ class BlockedLog
} }
/** /**
* set amounts of log from current element value in order to compare signature. * Return the signature (hash) of the "genesis-block" (Block 0)
*/
private function getCurrentValue() {
if($this->element === 'payment') {
$sql="SELECT amount FROM ".MAIN_DB_PREFIX."paiement WHERE rowid=".$this->fk_object;
$res = $this->db->query($sql);
if($res && $obj = $this->db->fetch_object($res)) {
$this->amounts = (double) $obj->amount;
}
}
if($this->element === 'payment_supplier') {
$sql="SELECT amount FROM ".MAIN_DB_PREFIX."paiementfourn WHERE rowid=".$this->fk_object;
$res = $this->db->query($sql);
if($res && $obj = $this->db->fetch_object($res)) {
$this->amounts = (double) $obj->amount;
}
}
elseif($this->element === 'facture') {
$sql="SELECT total_ttc FROM ".MAIN_DB_PREFIX."facture WHERE rowid=".$this->fk_object;
$res = $this->db->query($sql);
if($res && $obj = $this->db->fetch_object($res)) {
$this->amounts = (double) $obj->total_ttc;
}
}
}
/**
* Return and set the entity signature included into line signature
* *
* @return string current entity signature * @return string Signature of genesis-block for current conf->entity
*/ */
public function getSignature() { public function getSignature()
{
global $db,$conf,$mysoc; global $db,$conf,$mysoc;
if (empty($conf->global->BLOCKEDLOG_ENTITY_FINGERPRINT)) { // creation of a unique fingerprint if (empty($conf->global->BLOCKEDLOG_ENTITY_FINGERPRINT)) { // creation of a unique fingerprint
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
$fingerprint = $this->crypt(print_r($mysoc,true).time().rand(0,1000)); $fingerprint = dol_hash(print_r($mysoc,true).getRandomPassword(1), '5');
dolibarr_set_const($db, 'BLOCKEDLOG_ENTITY_FINGERPRINT', $fingerprint, 'chaine',0,'Numeric Unique Fingerprint', $conf->entity); dolibarr_set_const($db, 'BLOCKEDLOG_ENTITY_FINGERPRINT', $fingerprint, 'chaine',0,'Numeric Unique Fingerprint', $conf->entity);

View File

@ -74,7 +74,7 @@ function dol_decode($chain)
* If constant MAIN_SECURITY_SALT is defined, we use it as a salt. * If constant MAIN_SECURITY_SALT is defined, we use it as a salt.
* *
* @param string $chain String to hash * @param string $chain String to hash
* @param string $type Type of hash ('0':auto, '1':sha1, '2':sha1+md5, '3':md5, '4':md5 for OpenLdap). Use '3' here, if hash is not needed for security purpose, for security need, prefer '0'. * @param string $type Type of hash ('0':auto, '1':sha1, '2':sha1+md5, '3':md5, '4':md5 for OpenLdap, '5':sha256). Use '3' here, if hash is not needed for security purpose, for security need, prefer '0'.
* @return string Hash of string * @return string Hash of string
*/ */
function dol_hash($chain, $type='0') function dol_hash($chain, $type='0')
@ -88,6 +88,7 @@ function dol_hash($chain, $type='0')
else if ($type == '2' || $type == 'sha1md5') return sha1(md5($chain)); else if ($type == '2' || $type == 'sha1md5') return sha1(md5($chain));
else if ($type == '3' || $type == 'md5') return md5($chain); else if ($type == '3' || $type == 'md5') return md5($chain);
else if ($type == '4' || $type == 'md5openldap') return '{md5}'.base64_encode(mhash(MHASH_MD5,$chain)); // For OpenLdap with md5 (based on an unencrypted password in base) else if ($type == '4' || $type == 'md5openldap') return '{md5}'.base64_encode(mhash(MHASH_MD5,$chain)); // For OpenLdap with md5 (based on an unencrypted password in base)
else if ($type == '5') return hash('sha256',$chain);
else if (! empty($conf->global->MAIN_SECURITY_HASH_ALGO) && $conf->global->MAIN_SECURITY_HASH_ALGO == 'sha1') return sha1($chain); else if (! empty($conf->global->MAIN_SECURITY_HASH_ALGO) && $conf->global->MAIN_SECURITY_HASH_ALGO == 'sha1') return sha1($chain);
else if (! empty($conf->global->MAIN_SECURITY_HASH_ALGO) && $conf->global->MAIN_SECURITY_HASH_ALGO == 'sha1md5') return sha1(md5($chain)); else if (! empty($conf->global->MAIN_SECURITY_HASH_ALGO) && $conf->global->MAIN_SECURITY_HASH_ALGO == 'sha1md5') return sha1(md5($chain));

View File

@ -80,9 +80,7 @@ class InterfaceActionsBlockedLog extends DolibarrTriggers
$b=new BlockedLog($this->db); $b=new BlockedLog($this->db);
$b->action = $action; $b->setObjectData($object, $action, $amounts); // Set field date_object, ref_object, fk_object, element, object_data
$b->amounts= $amounts;
$b->setObjectData($object); // Set field date_object, ref_object, fk_object, element, object_data
$res = $b->create($user); $res = $b->create($user);

View File

@ -575,6 +575,10 @@ ALTER TABLE llx_product ADD COLUMN accountancy_code_sell_export varchar(32) AFTE
ALTER TABLE llx_facture_rec ADD COLUMN modelpdf varchar(255) AFTER note_public; ALTER TABLE llx_facture_rec ADD COLUMN modelpdf varchar(255) AFTER note_public;
ALTER TABLE llx_facture_rec ADD COLUMN generate_pdf integer DEFAULT 1 AFTER auto_validate; ALTER TABLE llx_facture_rec ADD COLUMN generate_pdf integer DEFAULT 1 AFTER auto_validate;
ALTER TABLE llx_blockedlog ADD COLUMN date_creation datetime;
ALTER TABLE llx_blockedlog ADD COLUMN user_fullname varchar(255);
ALTER TABLE llx_blockedlog MODIFY COLUMN ref_object varchar(255);
-- SPEC : use database type 'double' to store monetary values -- SPEC : use database type 'double' to store monetary values
ALTER TABLE llx_blockedlog MODIFY COLUMN amounts double(24,8); ALTER TABLE llx_blockedlog MODIFY COLUMN amounts double(24,8);
ALTER TABLE llx_chargessociales MODIFY COLUMN amount double(24,8); ALTER TABLE llx_chargessociales MODIFY COLUMN amount double(24,8);

View File

@ -19,18 +19,20 @@
CREATE TABLE llx_blockedlog CREATE TABLE llx_blockedlog
( (
rowid integer AUTO_INCREMENT PRIMARY KEY, rowid integer AUTO_INCREMENT PRIMARY KEY,
tms timestamp, entity integer DEFAULT 1 NOT NULL,
date_creation datetime,
tms timestamp,
action varchar(50), action varchar(50),
amounts double(24,8) NOT NULL, amounts double(24,8) NOT NULL,
element varchar(50),
fk_user integer,
user_fullname varchar(255);
fk_object integer,
ref_object varchar(255),
date_object datetime,
signature varchar(100) NOT NULL, signature varchar(100) NOT NULL,
signature_line varchar(100) NOT NULL, signature_line varchar(100) NOT NULL,
element varchar(50),
fk_object integer,
ref_object varchar(100),
date_object datetime,
object_data text, object_data text,
fk_user integer,
entity integer DEFAULT 1 NOT NULL,
certified integer certified integer
) ENGINE=innodb; ) ENGINE=innodb;

View File

@ -9,6 +9,7 @@ ShowAllFingerPrintsErrorsMightBeTooLong=Show all archive logs with error (might
DownloadBlockChain=Download fingerprints DownloadBlockChain=Download fingerprints
KoCheckFingerprintValidity=Archived log is not valid. It means someone (a hacker ?) has modified some datas of this archived log after it was recorded, or has erased the previous archived record (check that line with previous # exists). KoCheckFingerprintValidity=Archived log is not valid. It means someone (a hacker ?) has modified some datas of this archived log after it was recorded, or has erased the previous archived record (check that line with previous # exists).
OkCheckFingerprintValidity=Archived log is valid. It means all data on this line were not modified and record follow the previous one. OkCheckFingerprintValidity=Archived log is valid. It means all data on this line were not modified and record follow the previous one.
OkCheckFingerprintValidityButChainIsKo=Archived log seems valid compared to previous one but the chain was corrupted previously.
AddedByAuthority=Stored into remote authority AddedByAuthority=Stored into remote authority
NotAddedByAuthorityYet=Not yet stored into remote authority NotAddedByAuthorityYet=Not yet stored into remote authority
ShowDetails=Show stored details ShowDetails=Show stored details