Merge pull request #6969 from atm-alexis/NEW_blocklog_develop_refactor

NEW blockedlog hash and authority
This commit is contained in:
Laurent Destailleur 2017-06-11 15:54:47 +02:00 committed by GitHub
commit 5471170a97
17 changed files with 1426 additions and 3 deletions

View File

@ -0,0 +1,126 @@
<?php
/* Copyright (C) 2017 ATM Consulting <contact@atm-consulting.fr>
*
* 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
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* \file htdocs/blockedlog/admin/blockedlog.php
* \ingroup system
* \brief Page setup for blockedlog module
*/
require '../../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/blockedlog/lib/blockedlog.lib.php';
require_once DOL_DOCUMENT_ROOT.'/blockedlog/class/blockedlog.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
$langs->load("admin");
$langs->load("other");
$langs->load("blockedlog");
if (! $user->admin) accessforbidden();
$action = GETPOST('action','alpha');
/*
* Actions
*/
if (preg_match('/set_(.*)/',$action,$reg))
{
$code=$reg[1];
if (dolibarr_set_const($db, $code, GETPOST($code), 'chaine', 0, '', $conf->entity) > 0)
{
header("Location: ".$_SERVER["PHP_SELF"]);
exit;
}
else
{
dol_print_error($db);
}
}
if (preg_match('/del_(.*)/',$action,$reg))
{
$code=$reg[1];
if (dolibarr_del_const($db, $code, 0) > 0)
{
Header("Location: ".$_SERVER["PHP_SELF"]);
exit;
}
else
{
dol_print_error($db);
}
}
/*
* View
*/
$block_static = new BlockedLog($db);
$form=new Form($db);
llxHeader('',$langs->trans("BlockedLogSetup"));
$linkback='<a href="'.DOL_URL_ROOT.'/admin/modules.php">'.$langs->trans("BackToModuleList").'</a>';
print load_fiche_titre($langs->trans("ModuleSetup").' BlockedLog',$linkback);
$head=blockedlogadmin_prepare_head();
dol_fiche_head($head, 'blockedlog', '', -1);
print $langs->trans("BlockedLogDesc")."<br>\n";
print '<br>';
print '<table class="noborder" width="100%">';
print '<tr class="liste_titre">';
print '<td>'.$langs->trans("Key").'</td>';
print '<td>'.$langs->trans("Value").'</td>';
print "</tr>\n";
print '<tr class="oddeven">';
print '<td class="titlefield">';
print $langs->trans("EntityKey").'</td><td align="center">';
print $block_static->getSignature();
print '</td></tr>';
// Example with a yes / no select
$var=!$var;
print '<tr '.$bc[$var].'>';
print '<td>'.$langs->trans("BlockedLogAuthorityUrl").img_info($langs->trans('BlockedLogAuthorityNeededToStoreYouFingerprintsInNonAlterableRemote')).'</td>';
print '<td align="right" width="300">';
print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'">';
print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
print '<input type="hidden" name="action" value="set_BLOCKEDLOG_AUTHORITY_URL">';
print '<input type="text" name="BLOCKEDLOG_AUTHORITY_URL" value="'.$conf->global->BLOCKEDLOG_AUTHORITY_URL.'" size="40" />';
print '<input type="submit" class="button" value="'.$langs->trans("Modify").'">';
print '</form>';
print '</td></tr>';
print '</table>';
dol_fiche_end();
print '<br><br>';
llxFooter();
$db->close();

View File

@ -0,0 +1,142 @@
<?php
/* Copyright (C) 2017 ATM Consulting <contact@atm-consulting.fr>
*
* 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
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* \file htdocs/blockedlog/admin/blockedlog.php
* \ingroup system
* \brief Page setup for blockedlog module
*/
require '../../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/blockedlog/lib/blockedlog.lib.php';
require_once DOL_DOCUMENT_ROOT.'/blockedlog/class/blockedlog.class.php';
require_once DOL_DOCUMENT_ROOT.'/blockedlog/class/authority.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
$langs->load("admin");
$langs->load("other");
$langs->load("blockedlog");
if (! $user->admin) accessforbidden();
$action = GETPOST('action','alpha');
if($action === 'downloadblockchain') {
$auth = new BlockedLogAuthority($db);
$bc = $auth->getLocalBlockChain();
header('Content-Type: application/octet-stream');
header("Content-Transfer-Encoding: Binary");
header("Content-disposition: attachment; filename=\"" .$auth->signature. ".certif\"");
echo $bc;
exit;
}
/*
* View
*/
$block_static = new BlockedLog($db);
$blocks = $block_static->getLog('all', 0, GETPOST('all') ? 0 : 50);
$form=new Form($db);
llxHeader('',$langs->trans("BlockedLogSetup"));
$linkback='<a href="'.DOL_URL_ROOT.'/admin/modules.php">'.$langs->trans("BackToModuleList").'</a>';
print load_fiche_titre($langs->trans("ModuleSetup").' BlockedLog',$linkback);
$head=blockedlogadmin_prepare_head();
dol_fiche_head($head, 'fingerprints', '', -1);
print $langs->trans("FingerprintsDesc")."<br>\n";
print '<br>';
echo '<div align="right"><a href="?all=1">'.$langs->trans('ShowAllFingerPrintsMightBeTooLong').'</a> <a href="?action=downloadblockchain">'.$langs->trans('DownloadBlockChain').'</a></div>';
print '<table class="noborder" width="100%">';
print '<tr class="liste_titre">';
print '<td>'.$langs->trans('Date').'</td>';
print '<td>'.$langs->trans('Ref').'</td>';
print '<td>'.$langs->trans('Action').'</td>';
print '<td>'.$langs->trans('Element').'</td>';
print '<td>'.$langs->trans('Amount').'</td>';
print '<td>'.$langs->trans('Author').'</td>';
print '<td>'.$langs->trans('Fingerprint').'</td>';
print '<td><span id="blockchainstatus"></span></td>';
print '</tr>';
foreach($blocks as &$block) {
print '<tr class="oddeven">';
print '<td>'.dol_print_date($block->tms,'dayhour').'</td>';
print '<td>'.$block->ref_object.'</td>';
print '<td>'.$langs->trans('log'.$block->action).'</td>';
print '<td>'.$block->getObject().'</td>';
print '<td align="right">'.price($block->amounts).'</td>';
print '<td>'.$block->getUser().'</td>';
print '<td>'.$block->signature.'</td>';
print '<td>';
print $block->checkSignature() ? img_picto('OkCheckPaymentValidity', 'on') : img_picto($langs->trans('KoCheckPaymentValidity'), 'off');
print ' '.($block->certified ? img_picto($langs->trans('AddedByAuthority'), 'info') : img_picto($langs->trans('NotAddedByAuthorityYet'), 'info_black') );
print '</td>';
print '</tr>';
}
print '</table>';
?>
<script type="text/javascript">
$.ajax({
url : "<?php echo dol_buildpath('/blockedlog/ajax/check_signature.php',1) ?>"
,dataType:"html"
}).done(function(data) {
if(data == 'hashisok') {
$('#blockchainstatus').html('<?php echo $langs->trans('AuthorityReconizeFingerprintConformity'). ' '. img_picto($langs->trans('SignatureOK'), 'on') ?>');
}
else{
$('#blockchainstatus').html('<?php echo $langs->trans('AuthorityDidntReconizeFingerprintConformity'). ' '.img_picto($langs->trans('SignatureKO'), 'off') ?>');
}
});
</script>
<?php
dol_fiche_end();
print '<br><br>';
llxFooter();
$db->close();

View File

View File

@ -0,0 +1,45 @@
<?php
require '../../master.inc.php';
require_once DOL_DOCUMENT_ROOT.'/blockedlog/class/blockedlog.class.php';
require_once DOL_DOCUMENT_ROOT.'/blockedlog/class/authority.class.php';
$user=new User($db);
$user->fetch(1); //TODO conf user authority
$auth = new BlockedLogAuthority($db);
$signature = GETPOST('s');
$newblock = GETPOST('b');
$hash = GETPOST('h');
if($auth->fetch(0, $signature)<=0) {
$auth->signature = $signature;
$auth->create($user);
}
if(!empty($hash)) {
echo $auth->checkBlockchain($hash) ? 'hashisok' : 'hashisjunk';
}
elseif(!empty($newblock)){
if($auth->checkBlock($newblock)) {
$auth->addBlock($newblock);
$auth->update($user);
echo 'blockadded';
}
else{
echo 'blockalreadyadded';
}
}
else{
echo 'idontunderstandwhatihavetodo';
}

View File

@ -0,0 +1,30 @@
<?php
require '../../main.inc.php';
if(empty($conf->global->BLOCKEDLOG_AUTHORITY_URL)) exit('BLOCKEDLOG_AUTHORITY_URL not set');
require_once DOL_DOCUMENT_ROOT.'/blockedlog/class/blockedlog.class.php';
require_once DOL_DOCUMENT_ROOT.'/blockedlog/class/authority.class.php';
$auth=new BlockedLogAuthority($db);
$auth->syncSignatureWithAuthority();
$block_static = new BlockedLog($db);
$blocks = $block_static->getLog('just_certified', 0, 0, 1) ;
$auth->signature = $block_static->getSignature();
foreach($blocks as &$b) {
$auth->blockchain.=$b->signature;
}
$hash = $auth->getBlockchainHash();
$url = $conf->global->BLOCKEDLOG_AUTHORITY_URL.'/blockedlog/ajax/authority.php?s='.$auth->signature.'&h='.$hash;
$res = file_get_contents($url);
//echo $url;
echo $res;

View File

@ -0,0 +1,333 @@
<?php
/* Copyright (C) 2017 ATM Consulting <contact@atm-consulting.fr>
*
* 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
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* Class to manage certif authority
*/
class BlockedLogAuthority
{
/**
* Id of the log
* @var int
*/
public $id;
/**
* Unique fingerprint of the blockchain to store
* @var string
*/
public $signature = '';
/**
* Entire fingerprints blockchain
* @var string
*/
public $blockchain = '';
/**
* timestamp
* @var int
*/
public $tms = 0;
/**
* Constructor
*
* @param DoliDB $db Database handler
*/
public function __construct($db) {
$this->db = $db;
}
/**
* Get the blockchain
*
* @return string blockchain
*/
public function getLocalBlockChain() {
$block_static = new BlockedLog($this->db);
$this->signature = $block_static->getSignature();
$blocks = $block_static->getLog('all', 0, 0, 1) ;
$this->blockchain = '';
foreach($blocks as &$b) {
$this->blockchain.=$b->signature;
}
return $this->blockchain;
}
/**
* Get hash of the block chain to check
*
* @return string hash md5 of blockchain
*/
public function getBlockchainHash() {
return md5($this->signature.$this->blockchain);
}
/**
* Get hash of the block chain to check
*
* @param string $hash hash md5 of blockchain to test
* @return boolean
*/
public function checkBlockchain($hash) {
return ($hash === $this->getBlockchainHash() );
}
/**
* Add a new block to the chain
*
* @param string $block new block to chain
*/
public function addBlock($block) {
$this->blockchain.=$block;
}
/**
* hash already exist into chain ?
*
* @param string $block new block to chain
* @return boolean
*/
public function checkBlock($block) {
if(strlen($block)!=64) return false;
$blocks = str_split($this->blockchain,64);
if(!in_array($block,$blocks)) {
return true;
}
else{
return false;
}
}
/**
* Get object from database
*
* @param int $id Id of object to load
* @param string $signature Signature of object to load
* @return int >0 if OK, <0 if KO, 0 if not found
*/
public function fetch($id, $signature='') {
global $langs;
dol_syslog(get_class($this)."::fetch id=".$id, LOG_DEBUG);
if (empty($id) && empty($signature))
{
$this->error='BadParameter';
return -1;
}
$langs->load("blockedlog");
$sql = "SELECT b.rowid, b.signature, b.blockchain, b.tms";
$sql.= " FROM ".MAIN_DB_PREFIX."blockedlog_authority as b";
if ($id) $sql.= " WHERE b.rowid = ". $id;
else if($signature)$sql.= " WHERE b.signature = '". $this->db->escape( $signature ) ."'" ;
$resql=$this->db->query($sql);
if ($resql)
{
if ($this->db->num_rows($resql))
{
$obj = $this->db->fetch_object($resql);
$this->id = $obj->rowid;
$this->ref = $obj->rowid;
$this->signature = $obj->signature;
$this->blockchain = $obj->blockchain;
$this->tms = $this->db->jdate($obj->tms);
return 1;
}
else
{
$this->error=$langs->trans("RecordNotFound");
return 0;
}
}
else
{
$this->error=$this->db->error();
return -1;
}
}
/**
* Create authority in database.
*
* @param User $user Object user that create
* @return int <0 if KO, >0 if OK
*/
public function create($user) {
global $conf,$langs,$hookmanager;
$langs->load('blockedlog');
$error=0;
dol_syslog(get_class($this).'::create', LOG_DEBUG);
$this->db->begin();
$sql = "INSERT INTO ".MAIN_DB_PREFIX."blockedlog_authority (";
$sql.= " signature,";
$sql.= " blockchain";
$sql.= ") VALUES (";
$sql.= "'".$this->db->escape($this->signature)."',";
$sql.= "'".$this->db->escape($this->blockchain)."'";
$sql.= ")";
$res = $this->db->query($sql);
if ($res)
{
$id = $this->db->last_insert_id(MAIN_DB_PREFIX."blockedlog_authority");
if ($id > 0)
{
$this->id = $id;
$this->db->commit();
return $this->id;
}
else
{
$this->db->rollback();
return -2;
}
}
else
{
$this->error=$this->db->error();
$this->db->rollback();
return -1;
}
}
/**
* Create authority in database.
*
* @param User $user Object user that create
* @return int <0 if KO, >0 if OK
*/
public function update($user) {
global $conf,$langs,$hookmanager;
$langs->load('blockedlog');
$error=0;
dol_syslog(get_class($this).'::create', LOG_DEBUG);
$this->db->begin();
$sql = "UPDATE ".MAIN_DB_PREFIX."blockedlog_authority SET ";
$sql.= " blockchain='".$this->db->escape($this->blockchain)."'";
$sql.= " WHERE rowid=".$this->id;
$res = $this->db->query($sql);
if ($res)
{
$this->db->commit();
return 1;
}
else
{
$this->error=$this->db->error();
$this->db->rollback();
return -1;
}
}
/**
* For cron to sync to authority.
*
* @return int <0 if KO, >0 if OK
*/
public function syncSignatureWithAuthority() {
global $conf, $langs;
//TODO create cron task on activation
if(empty($conf->global->BLOCKEDLOG_AUTHORITY_URL)) {
$this->error = $langs->trans('NoAuthorityURLDefined');
return -2;
}
require_once DOL_DOCUMENT_ROOT.'/blockedlog/class/blockedlog.class.php';
$block_static = new BlockedLog($this->db);
$blocks = $block_static->getLog('not_certified', 0, 0, 1);
$signature=$block_static->getSignature();
foreach($blocks as &$block) {
$url = $conf->global->BLOCKEDLOG_AUTHORITY_URL.'/blockedlog/ajax/authority.php?s='.$signature.'&b='.$block->signature;
$res = file_get_contents($url);
echo $block->signature.' '.$url. ' '.$res.'<br>';
if($res === 'blockalreadyadded' || $res === 'blockadded') {
$block->setCertified();
}
else {
$this->error = $langs->trans('ImpossibleToContactAuthority ',$url);
return -1;
}
}
return 1;
}
}

View File

@ -0,0 +1,529 @@
<?php
/* Copyright (C) 2017 ATM Consulting <contact@atm-consulting.fr>
*
* 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
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* Class to manage Blocked Log
*/
class BlockedLog
{
/**
* Id of the log
* @var int
*/
public $id;
/**
* Unique fingerprint of the log
* @var string
*/
public $signature = '';
/**
* Unique fingerprint of the line log content
* @var string
*/
public $signature_line = '';
public $amounts = null;
/**
* trigger action
* @var string
*/
public $action = '';
/**
* Object element
* @var string
*/
public $element = '';
/**
* Object id
* @var int
*/
public $fk_object = 0;
/**
* Log certified by remote authority or not
* @var boolean
*/
public $certified = false;
/**
* Author
* @var int
*/
public $fk_user = 0;
public $date_object = 0;
public $ref_object = '';
public $object_data = null;
/**
* Constructor
*
* @param DoliDB $db Database handler
*/
public function __construct(DoliDB $db)
{
$this->db = $db;
}
/**
* try to retrieve logged object
*/
public function getObject() {
global $langs;
if($this->element === 'facture') {
require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
$object = new Facture($this->db);
if($object->fetch($this->fk_object)>0) {
return $object->getNomUrl(1);
}
}
else if($this->element === 'payment') {
require_once DOL_DOCUMENT_ROOT.'/compta/paiement/class/paiement.class.php';
$object = new Paiement($this->db);
if($object->fetch($this->fk_object)>0) {
return $object->getNomUrl(1);
}
}
return $langs->trans('ImpossibleToReloadObject', $this->element, $this->fk_object);
}
/**
* try to retrieve user author
*/
public function getUser() {
global $langs, $cachedUser;
if(empty($cachedUser))$cachedUser=array();
if(empty($cachedUser[$this->fk_user])) {
$u=new User($this->db);
if($u->fetch($this->fk_user)>0) {
$cachedUser[$this->fk_user] = $u;
}
}
if(!empty($cachedUser[$this->fk_user])) {
return $cachedUser[$this->fk_user]->getNomUrl(1);
}
return $langs->trans('ImpossibleToRetrieveUser', $this->fk_user);
}
/**
* populate log by object
*
* @param payment|facture $object object to store
*/
public function setObjectData(&$object) {
if($object->element=='payment') {
$this->date_object = $object->datepaye;
}
else{
$this->date_object = $object->date;
}
$this->ref_object = $object->ref;
$this->element = $object->element;
$this->fk_object = $object->id;
$this->object_data=new stdClass();
if($this->element === 'facture') {
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;
}
$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->note_public = (double) $object->note_public;
$this->object_data->note_private= (double) $object->note_private;
}
elseif($this->element==='payment'){
$this->object_data->amounts = $object->amounts;
}
}
/**
* Get object from database
*
* @param int $id Id of object to load
* @return int >0 if OK, <0 if KO, 0 if not found
*/
public function fetch($id) {
global $langs;
dol_syslog(get_class($this)."::fetch id=".$id, LOG_DEBUG);
if (empty($id))
{
$this->error='BadParameter';
return -1;
}
$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.= " FROM ".MAIN_DB_PREFIX."blockedlog as b";
if ($id) $sql.= " WHERE b.rowid = ". $id;
$resql=$this->db->query($sql);
if ($resql)
{
if ($this->db->num_rows($resql))
{
$obj = $this->db->fetch_object($resql);
$this->id = $obj->rowid;
$this->ref = $obj->rowid;
$this->signature = $obj->signature;
$this->amounts = (double) $obj->amounts;
$this->action = $obj->action;
$this->element = $obj->element;
$this->fk_object = trim($obj->fk_object);
$this->date_object = $this->db->jdate($obj->date_object);
$this->ref_object = $obj->ref_object;
$this->certified = ($obj->certified == 1);
$this->fk_user = $obj->fk_user;
$this->tms = $this->db->jdate($obj->tms);
$this->object_data = unserialize($obj->object_data);
return 1;
}
else
{
$this->error=$langs->trans("RecordNotFound");
return 0;
}
}
else
{
$this->error=$this->db->error();
return -1;
}
}
/**
* Set block certified by authority
*
* @return boolean
*/
public function setCertified() {
$res = $this->db->query("UPDATE ".MAIN_DB_PREFIX."blockedlog SET certified=1 WHERE rowid=".$this->id);
if($res===false) return false;
return true;
}
/**
* Create blocked log in database.
*
* @param User $user Object user that create
* @return int <0 if KO, >0 if OK
*/
public function create($user) {
global $conf,$langs,$hookmanager;
$langs->load('blockedlog');
$error=0;
dol_syslog(get_class($this).'::create', LOG_DEBUG);
$this->getSignatureRecursive();
if (is_null($this->amounts))
{
$this->error=$langs->trans("BlockLogNeedAmountsValue");
dol_syslog($this->error, LOG_WARNING);
return -1;
}
if(empty($this->element)) {
$this->error=$langs->trans("BlockLogNeedElement");
dol_syslog($this->error, LOG_WARNING);
return -2;
}
if(empty($this->action)) {
$this->error=$langs->trans("BlockLogNeedAction");
dol_syslog($this->error, LOG_WARNING);
return -3;
}
$this->fk_user = $user->id;
$this->db->begin();
$sql = "INSERT INTO ".MAIN_DB_PREFIX."blockedlog (";
$sql.= "action,";
$sql.= " amounts,";
$sql.= " signature,";
$sql.= " signature_line,";
$sql.= " element,";
$sql.= " fk_object,";
$sql.= " date_object,";
$sql.= " ref_object,";
$sql.= " object_data,";
$sql.= " certified,";
$sql.= " fk_user,";
$sql.= " entity";
$sql.= ") VALUES (";
$sql.= "'".$this->db->escape($this->action)."',";
$sql.= "".$this->amounts.",";
$sql.= "'".$this->db->escape($this->signature)."',";
$sql.= "'".$this->db->escape($this->signature_line)."',";
$sql.= "'".$this->db->escape($this->element)."',";
$sql.= "".$this->fk_object.",";
$sql.= "'".$this->db->idate($this->date_object)."',";
$sql.= "'".$this->db->escape($this->ref_object)."',";
$sql.= "'".$this->db->escape(serialize($this->object_data))."',";
$sql.= "0,";
$sql.= "".$user->id.",";
$sql.= $conf->entity;
$sql.= ")";
$res = $this->db->query($sql);
if ($res)
{
$id = $this->db->last_insert_id(MAIN_DB_PREFIX."blockedlog");
if ($id > 0)
{
$this->id = $id;
$this->db->commit();
return $this->id;
}
else
{
$this->db->rollback();
return -2;
}
}
else
{
$this->error=$this->db->error();
$this->db->rollback();
return -1;
}
}
/**
* return crypted value.
*
* @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
*/
public function checkSignature() {
$signature_to_test = $this->signature;
$this->getSignatureRecursive();
return ($signature_to_test=== $this->signature);
}
/**
* set current signatures
*/
private function getSignatureRecursive(){
$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) {
foreach($logs as &$b) {
if($this->id>0 && $b->id == $this->id) break; // on arrête sur un enregistrement précis pour recalculer une signature
$b->getCurrentValue(); // on récupère la valeur actuelle en base de l'élément enregistré
$this->signature = $this->crypt($this->signature. $this->action . $b->signature . $b->amounts);
}
}
}
/**
* return log object for a element.
*
* @param string $element element to search
* @param int $fk_object id of object to search
* @param int $limit max number of element, 0 for all
* @param string $order sort of query
* @return array array of object log
*/
public function getLog($element, $fk_object, $limit = 0, $order = -1) {
global $conf,$cachedlogs ;
/* $cachedlogs allow fastest search */
if(empty($cachedlogs)) $cachedlogs=array();
if($element=='all') {
$sql="SELECT rowid FROM ".MAIN_DB_PREFIX."blockedlog
WHERE entity=".$conf->entity;
}
else if($element=='not_certified') {
$sql="SELECT rowid FROM ".MAIN_DB_PREFIX."blockedlog
WHERE entity=".$conf->entity." AND certified = 0";
}
else if($element=='just_certified') {
$sql="SELECT rowid FROM ".MAIN_DB_PREFIX."blockedlog
WHERE entity=".$conf->entity." AND certified = 1";
}
else{
$sql="SELECT rowid FROM ".MAIN_DB_PREFIX."blockedlog
WHERE element='".$element."' AND fk_object=".(int) $fk_object;
}
$sql.=($order<0 ? ' ORDER BY rowid DESC ' : ' ORDER BY rowid ASC ');
if($limit > 0 )$sql.=' LIMIT '.$limit;
$res = $this->db->query($sql);
if($res) {
$results=array();
while($obj = $this->db->fetch_object($res)) {
if(!isset($cachedlogs[$obj->rowid])) {
$b=new BlockedLog($this->db);
$b->fetch($obj->rowid);
$cachedlogs[$obj->rowid] = $b;
}
$results[] = $cachedlogs[$obj->rowid];
}
return $results;
}
else{
return false;
}
}
/**
* set amounts of log from current element value in order to compare signature.
*/
private function getCurrentValue() {
if($this->action === 'PAYMENT_CUSTOMER_CREATE'
|| $this->action === 'PAYMENT_ADD_TO_BANK') {
$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;
}
}
}
/**
* return and set the entity signature included into line signature
*
* @return string current entity signature
*/
public function getSignature() {
global $db,$conf,$mysoc;
if(empty($conf->global->BLOCKEDLOG_ENTITY_FINGERPRINT)) { // creation of a unique fingerprint
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
$fingerprint = $this->crypt(print_r($mysoc,true).time().rand(0,1000));
dolibarr_set_const($db, 'BLOCKEDLOG_ENTITY_FINGERPRINT', $fingerprint, 'chaine',0,'Numeric Unique Fingerprint', $conf->entity);
$conf->global->BLOCKEDLOG_ENTITY_FINGERPRINT= $fingerprint;
}
return $conf->global->BLOCKEDLOG_ENTITY_FINGERPRINT;
}
}

View File

@ -0,0 +1,57 @@
<?php
/* Copyright (C) 2017 ATM Consulting <contact@atm-consulting.fr>
*
* 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
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* \file htdocs/blockedlog/lib/blockedlog.lib.php
* \ingroup system
* \brief Library for common blockedlog functions
*/
/**
* Define head array for tabs of blockedlog tools setup pages
*
* @return Array of head
*/
function blockedlogadmin_prepare_head()
{
global $langs, $conf;
$h = 0;
$head = array();
$head[$h][0] = DOL_URL_ROOT."/blockedlog/admin/blockedlog.php";
$head[$h][1] = $langs->trans("BlockedLog");
$head[$h][2] = 'blockedlog';
$h++;
$head[$h][0] = DOL_URL_ROOT."/blockedlog/admin/fingerprints.php";
$head[$h][1] = $langs->trans("Fingerprints");
$head[$h][2] = 'fingerprints';
$h++;
$object=new stdClass();
// 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); to remove a tab
complete_head_from_modules($conf,$langs,$object,$head,$h,'blockedlog');
complete_head_from_modules($conf,$langs,$object,$head,$h,'blockedlog','remove');
return $head;
}

View File

View File

@ -196,7 +196,7 @@ class Paiement extends CommonObject
$this->db->begin();
$ref = $this->getNextNumRef('');
$this->ref = $this->getNextNumRef('');
if ($way == 'dolibarr')
{
@ -210,7 +210,7 @@ class Paiement extends CommonObject
}
$sql = "INSERT INTO ".MAIN_DB_PREFIX."paiement (entity, ref, datec, datep, amount, multicurrency_amount, fk_paiement, num_paiement, note, fk_user_creat)";
$sql.= " VALUES (".$conf->entity.", '".$ref."', '". $this->db->idate($now)."', '".$this->db->idate($this->datepaye)."', '".$total."', '".$mtotal."', ".$this->paiementid.", '".$this->num_paiement."', '".$this->db->escape($this->note)."', ".$user->id.")";
$sql.= " VALUES (".$conf->entity.", '".$this->ref."', '". $this->db->idate($now)."', '".$this->db->idate($this->datepaye)."', '".$total."', '".$mtotal."', ".$this->paiementid.", '".$this->num_paiement."', '".$this->db->escape($this->note)."', ".$user->id.")";
dol_syslog(get_class($this)."::Create insert paiement", LOG_DEBUG);
$resql = $this->db->query($sql);

View File

@ -60,7 +60,7 @@ class modBlockedLog extends DolibarrModules
// Config pages
//-------------
$this->config_page_url = array();
$this->config_page_url = array('blockedlog.php@blockedlog');
// Dependancies
//-------------

View File

@ -0,0 +1,94 @@
<?php
/* Copyright (C) 2017 ATM Consulting <contact@atm-consulting.fr>
*
* 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
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* \file htdocs/core/triggers/interface_50_modAgenda_ActionsBlockedLog.class.php
* \ingroup system
* \brief Trigger file for blockedlog module
*/
require_once DOL_DOCUMENT_ROOT.'/core/triggers/dolibarrtriggers.class.php';
require_once DOL_DOCUMENT_ROOT.'/blockedlog/class/blockedlog.class.php';
/**
* Class of triggered functions for agenda module
*/
class InterfaceActionsBlockedLog extends DolibarrTriggers
{
public $family = 'system';
public $description = "Triggers of this module add blocklog.";
public $version = self::VERSION_DOLIBARR;
public $picto = 'system';
/**
* Function called on Dolibarrr payment or invoice event.
*
* @param string $action Event action code
* @param Object $object Object
* @param User $user Object user
* @param Translate $langs Object langs
* @param conf $conf Object conf
* @return int <0 if KO, 0 if no triggered ran, >0 if OK
*/
public function runTrigger($action, $object, User $user, Translate $langs, Conf $conf)
{
// Do not log events not enabled for this action
if (empty($conf->blockedlog->enabled)) {
return 0;
}
if($action==='BILL_VALIDATE' || $action === 'BILL_PAYED' || $action==='BILL_UNPAYED') {
$amounts= (double) $object->total_ttc;
}
else if($action === 'PAYMENT_CUSTOMER_CREATE' || $action === 'PAYMENT_ADD_TO_BANK') {
$amounts = 0;
if(!empty($object->amounts)) {
foreach($object->amounts as $amount) {
$amounts+= price2num($amount);
}
}
}
else if(strpos($action,'PAYMENT')!==false) {
$amounts= (double) $object->amount;
}
else {
return 0; // not implemented action log
}
$b=new BlockedLog($this->db);
$b->action = $action;
$b->amounts= $amounts;
$b->setObjectData($object);
$res = $b->create($user);
if($res<0) {
setEventMessage($b->error,'errors');
return -1;
}
else {
return 1;
}
}
}

View File

@ -397,3 +397,37 @@ ALTER TABLE llx_usergroup_rights DROP INDEX fk_usergroup;
ALTER TABLE llx_usergroup_rights ADD UNIQUE INDEX uk_usergroup_rights (entity, fk_usergroup, fk_id);
ALTER TABLE llx_usergroup_rights ADD CONSTRAINT fk_usergroup_rights_fk_usergroup FOREIGN KEY (fk_usergroup) REFERENCES llx_usergroup (rowid);
CREATE TABLE llx_blockedlog
(
rowid integer AUTO_INCREMENT PRIMARY KEY,
tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
action varchar(50),
amounts real NOT NULL,
signature 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,
fk_user integer,
entity integer DEFAULT 1,
certified integer
) ENGINE=innodb;
ALTER TABLE llx_blockedlog ADD INDEX signature (signature);
ALTER TABLE llx_blockedlog ADD INDEX fk_object_element (fk_object,element);
ALTER TABLE llx_blockedlog ADD INDEX entity (entity);
ALTER TABLE llx_blockedlog ADD INDEX fk_user (fk_user);
ALTER TABLE llx_blockedlog ADD INDEX entity_action (entity,action);
ALTER TABLE llx_blockedlog ADD INDEX entity_action_certified (entity,action,certified);
CREATE TABLE llx_blockedlog_authority
(
rowid integer AUTO_INCREMENT PRIMARY KEY,
blockchain longtext NOT NULL,
signature varchar(100) NOT NULL,
tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=innodb;
ALTER TABLE llx_blockedlog_authority ADD INDEX signature (signature);

View File

@ -0,0 +1,6 @@
ALTER TABLE llx_blockedlog ADD INDEX signature (signature);
ALTER TABLE llx_blockedlog ADD INDEX fk_object_element (fk_object,element);
ALTER TABLE llx_blockedlog ADD INDEX entity (entity);
ALTER TABLE llx_blockedlog ADD INDEX fk_user (fk_user);
ALTER TABLE llx_blockedlog ADD INDEX entity_action (entity,action);
ALTER TABLE llx_blockedlog ADD INDEX entity_action_certified (entity,action,certified);

View File

@ -0,0 +1,19 @@
CREATE TABLE llx_blockedlog
(
rowid integer AUTO_INCREMENT PRIMARY KEY,
tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
action varchar(50),
amounts real NOT NULL,
signature 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,
fk_user integer,
entity integer DEFAULT 1,
certified integer
) ENGINE=innodb;

View File

@ -0,0 +1 @@
ALTER TABLE llx_blockedlog_authority ADD INDEX signature (signature);

View File

@ -0,0 +1,7 @@
CREATE TABLE llx_blockedlog_authority
(
rowid integer AUTO_INCREMENT PRIMARY KEY,
blockchain longtext NOT NULL,
signature varchar(100) NOT NULL,
tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=innodb;