From 46ce77c571d51f99f4f7847704d2196fb0e1ccc2 Mon Sep 17 00:00:00 2001 From: jfefe Date: Sun, 3 May 2015 14:41:51 +0200 Subject: [PATCH] Refactor function to use it into API New function checkUserAccessToObject() is a piece of restrictedArea() function. --- htdocs/core/lib/security.lib.php | 330 +++++++++++++++++-------------- 1 file changed, 178 insertions(+), 152 deletions(-) diff --git a/htdocs/core/lib/security.lib.php b/htdocs/core/lib/security.lib.php index f00abaa339f86..644e2702a742a 100644 --- a/htdocs/core/lib/security.lib.php +++ b/htdocs/core/lib/security.lib.php @@ -331,163 +331,189 @@ function restrictedArea($user, $features, $objectid=0, $dbtablename='', $feature // is linked to a company allowed to $user. if (! empty($objectid) && $objectid > 0) { - foreach ($featuresarray as $feature) - { - $sql=''; - - $check = array('adherent','banque','user','usergroup','produit','service','produit|service','categorie'); // Test on entity only (Objects with no link to company) - $checksoc = array('societe'); // Test for societe object - $checkother = array('contact'); // Test on entity and link to societe. Allowed if link is empty (Ex: contacts...). - $checkproject = array('projet'); // Test for project object - $nocheck = array('barcode','stock','fournisseur'); // No test - $checkdefault = 'all other not already defined'; // Test on entity and link to third party. Not allowed if link is empty (Ex: invoice, orders...). - - // If dbtable not defined, we use same name for table than module name - if (empty($dbtablename)) $dbtablename = $feature; - - // Check permission for object with entity - if (in_array($feature,$check)) - { - $sql = "SELECT dbt.".$dbt_select; - $sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt"; - $sql.= " WHERE dbt.".$dbt_select." = ".$objectid; - if (($feature == 'user' || $feature == 'usergroup') && ! empty($conf->multicompany->enabled) && $conf->entity == 1 && $user->admin && ! $user->entity) - { - $sql.= " AND dbt.entity IS NOT NULL"; - } - else - { - $sql.= " AND dbt.entity IN (".getEntity($sharedelement, 1).")"; - } - } - else if (in_array($feature,$checksoc)) // We check feature = checksoc - { - // If external user: Check permission for external users - if ($user->societe_id > 0) - { - if ($user->societe_id <> $objectid) accessforbidden(); - } - // If internal user: Check permission for internal users that are restricted on their objects - else if (! empty($conf->societe->enabled) && ($user->rights->societe->lire && ! $user->rights->societe->client->voir)) - { - $sql = "SELECT sc.fk_soc"; - $sql.= " FROM (".MAIN_DB_PREFIX."societe_commerciaux as sc"; - $sql.= ", ".MAIN_DB_PREFIX."societe as s)"; - $sql.= " WHERE sc.fk_soc = ".$objectid; - $sql.= " AND sc.fk_user = ".$user->id; - $sql.= " AND sc.fk_soc = s.rowid"; - $sql.= " AND s.entity IN (".getEntity($sharedelement, 1).")"; - } - // If multicompany and internal users with all permissions, check user is in correct entity - else if (! empty($conf->multicompany->enabled)) - { - $sql = "SELECT s.rowid"; - $sql.= " FROM ".MAIN_DB_PREFIX."societe as s"; - $sql.= " WHERE s.rowid = ".$objectid; - $sql.= " AND s.entity IN (".getEntity($sharedelement, 1).")"; - } - } - else if (in_array($feature,$checkother)) - { - // If external user: Check permission for external users - if ($user->societe_id > 0) - { - $sql = "SELECT dbt.rowid"; - $sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt"; - $sql.= " WHERE dbt.rowid = ".$objectid; - $sql.= " AND dbt.fk_soc = ".$user->societe_id; - } - // If internal user: Check permission for internal users that are restricted on their objects - else if (! empty($conf->societe->enabled) && ($user->rights->societe->lire && ! $user->rights->societe->client->voir)) - { - $sql = "SELECT dbt.rowid"; - $sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt"; - $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON dbt.fk_soc = sc.fk_soc AND sc.fk_user = '".$user->id."'"; - $sql.= " WHERE dbt.rowid = ".$objectid; - $sql.= " AND (dbt.fk_soc IS NULL OR sc.fk_soc IS NOT NULL)"; // Contact not linked to a company or to a company of user - $sql.= " AND dbt.entity IN (".getEntity($sharedelement, 1).")"; - } - // If multicompany and internal users with all permissions, check user is in correct entity - else if (! empty($conf->multicompany->enabled)) - { - $sql = "SELECT dbt.rowid"; - $sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt"; - $sql.= " WHERE dbt.rowid = ".$objectid; - $sql.= " AND dbt.entity IN (".getEntity($sharedelement, 1).")"; - } - } - else if (in_array($feature,$checkproject)) - { - if (! empty($conf->projet->enabled) && ! $user->rights->projet->all->lire) - { - include_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; - $projectstatic=new Project($db); - $tmps=$projectstatic->getProjectsAuthorizedForUser($user,0,1,0); - $tmparray=explode(',',$tmps); - if (! in_array($objectid,$tmparray)) accessforbidden(); - } - else - { - $sql = "SELECT dbt.".$dbt_select; - $sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt"; - $sql.= " WHERE dbt.".$dbt_select." = ".$objectid; - $sql.= " AND dbt.entity IN (".getEntity($sharedelement, 1).")"; - } - } - else if (! in_array($feature,$nocheck)) // By default we check with link to third party - { - // If external user: Check permission for external users - if ($user->societe_id > 0) - { - if (empty($dbt_keyfield)) dol_print_error('','Param dbt_keyfield is required but not defined'); - $sql = "SELECT dbt.".$dbt_keyfield; - $sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt"; - $sql.= " WHERE dbt.rowid = ".$objectid; - $sql.= " AND dbt.".$dbt_keyfield." = ".$user->societe_id; - } - // If internal user: Check permission for internal users that are restricted on their objects - else if (! empty($conf->societe->enabled) && ($user->rights->societe->lire && ! $user->rights->societe->client->voir)) - { - if (empty($dbt_keyfield)) dol_print_error('','Param dbt_keyfield is required but not defined'); - $sql = "SELECT sc.fk_soc"; - $sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt"; - $sql.= ", ".MAIN_DB_PREFIX."societe as s"; - $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; - $sql.= " WHERE dbt.".$dbt_select." = ".$objectid; - $sql.= " AND sc.fk_soc = dbt.".$dbt_keyfield; - $sql.= " AND dbt.".$dbt_keyfield." = s.rowid"; - $sql.= " AND s.entity IN (".getEntity($sharedelement, 1).")"; - $sql.= " AND sc.fk_user = ".$user->id; - } - // If multicompany and internal users with all permissions, check user is in correct entity - else if (! empty($conf->multicompany->enabled)) - { - $sql = "SELECT dbt.".$dbt_select; - $sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt"; - $sql.= " WHERE dbt.".$dbt_select." = ".$objectid; - $sql.= " AND dbt.entity IN (".getEntity($sharedelement, 1).")"; - } - } - - //print "sql=".$sql."
"; - if ($sql) - { - $resql=$db->query($sql); - if ($resql) - { - if ($db->num_rows($resql) == 0) accessforbidden(); - } - else - { - accessforbidden(); - } - } - } + $ok = checkUserAccessToObject($user, $featuresarray,$objectid,$dbtablename,$feature2,$dbt_keyfield,$dbt_select); + return $ok ? 1 : accessforbidden(); } return 1; } +/** + * Check access by user to object + * + * @param User $user User to check + * @param array $featuresarray Features/modules to check + * @param int $objectid Object ID if we want to check a particular record (optional) is linked to a owned thirdparty (optional). + * @param string $dbtablename 'TableName&SharedElement' with Tablename is table where object is stored. SharedElement is an optional key to define where to check entity. Not used if objectid is null (optional) + * @param string $feature2 Feature to check, second level of permission (optional). Can be or check with 'level1|level2'. + * @param string $dbt_keyfield Field name for socid foreign key if not fk_soc. Not used if objectid is null (optional) + * @param string $dbt_select Field name for select if not rowid. Not used if objectid is null (optional) + * + * @return bool True if user has access, False otherwise + */ +function checkUserAccessToObject($user, $featuresarray, $objectid=0, $dbtablename='', $feature2='', $dbt_keyfield='', $dbt_select='') +{ + global $db, $conf; + + // More parameters + $params = explode('&', $dbtablename); + $dbtablename=(! empty($params[0]) ? $params[0] : ''); + $sharedelement=(! empty($params[1]) ? $params[1] : $dbtablename); + + foreach ($featuresarray as $feature) + { + $sql=''; + + $check = array('adherent','banque','user','usergroup','produit','service','produit|service','categorie'); // Test on entity only (Objects with no link to company) + $checksoc = array('societe'); // Test for societe object + $checkother = array('contact'); // Test on entity and link to societe. Allowed if link is empty (Ex: contacts...). + $checkproject = array('projet'); // Test for project object + $nocheck = array('barcode','stock','fournisseur'); // No test + $checkdefault = 'all other not already defined'; // Test on entity and link to third party. Not allowed if link is empty (Ex: invoice, orders...). + + // If dbtable not defined, we use same name for table than module name + if (empty($dbtablename)) $dbtablename = $feature; + + // Check permission for object with entity + if (in_array($feature,$check)) + { + $sql = "SELECT dbt.".$dbt_select; + $sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt"; + $sql.= " WHERE dbt.".$dbt_select." = ".$objectid; + if (($feature == 'user' || $feature == 'usergroup') && ! empty($conf->multicompany->enabled) && $conf->entity == 1 && $user->admin && ! $user->entity) + { + $sql.= " AND dbt.entity IS NOT NULL"; + } + else + { + $sql.= " AND dbt.entity IN (".getEntity($sharedelement, 1).")"; + } + } + else if (in_array($feature,$checksoc)) // We check feature = checksoc + { + // If external user: Check permission for external users + if ($user->societe_id > 0) + { + if ($user->societe_id <> $objectid) return false; + } + // If internal user: Check permission for internal users that are restricted on their objects + else if (! empty($conf->societe->enabled) && ($user->rights->societe->lire && ! $user->rights->societe->client->voir)) + { + $sql = "SELECT sc.fk_soc"; + $sql.= " FROM (".MAIN_DB_PREFIX."societe_commerciaux as sc"; + $sql.= ", ".MAIN_DB_PREFIX."societe as s)"; + $sql.= " WHERE sc.fk_soc = ".$objectid; + $sql.= " AND sc.fk_user = ".$user->id; + $sql.= " AND sc.fk_soc = s.rowid"; + $sql.= " AND s.entity IN (".getEntity($sharedelement, 1).")"; + } + // If multicompany and internal users with all permissions, check user is in correct entity + else if (! empty($conf->multicompany->enabled)) + { + $sql = "SELECT s.rowid"; + $sql.= " FROM ".MAIN_DB_PREFIX."societe as s"; + $sql.= " WHERE s.rowid = ".$objectid; + $sql.= " AND s.entity IN (".getEntity($sharedelement, 1).")"; + } + } + else if (in_array($feature,$checkother)) + { + // If external user: Check permission for external users + if ($user->societe_id > 0) + { + $sql = "SELECT dbt.rowid"; + $sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt"; + $sql.= " WHERE dbt.rowid = ".$objectid; + $sql.= " AND dbt.fk_soc = ".$user->societe_id; + } + // If internal user: Check permission for internal users that are restricted on their objects + else if (! empty($conf->societe->enabled) && ($user->rights->societe->lire && ! $user->rights->societe->client->voir)) + { + $sql = "SELECT dbt.rowid"; + $sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt"; + $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe_commerciaux as sc ON dbt.fk_soc = sc.fk_soc AND sc.fk_user = '".$user->id."'"; + $sql.= " WHERE dbt.rowid = ".$objectid; + $sql.= " AND (dbt.fk_soc IS NULL OR sc.fk_soc IS NOT NULL)"; // Contact not linked to a company or to a company of user + $sql.= " AND dbt.entity IN (".getEntity($sharedelement, 1).")"; + } + // If multicompany and internal users with all permissions, check user is in correct entity + else if (! empty($conf->multicompany->enabled)) + { + $sql = "SELECT dbt.rowid"; + $sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt"; + $sql.= " WHERE dbt.rowid = ".$objectid; + $sql.= " AND dbt.entity IN (".getEntity($sharedelement, 1).")"; + } + } + else if (in_array($feature,$checkproject)) + { + if (! empty($conf->projet->enabled) && ! $user->rights->projet->all->lire) + { + include_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; + $projectstatic=new Project($db); + $tmps=$projectstatic->getProjectsAuthorizedForUser($user,0,1,0); + $tmparray=explode(',',$tmps); + if (! in_array($objectid,$tmparray)) return false; + } + else + { + $sql = "SELECT dbt.".$dbt_select; + $sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt"; + $sql.= " WHERE dbt.".$dbt_select." = ".$objectid; + $sql.= " AND dbt.entity IN (".getEntity($sharedelement, 1).")"; + } + } + else if (! in_array($feature,$nocheck)) // By default we check with link to third party + { + // If external user: Check permission for external users + if ($user->societe_id > 0) + { + if (empty($dbt_keyfield)) dol_print_error('','Param dbt_keyfield is required but not defined'); + $sql = "SELECT dbt.".$dbt_keyfield; + $sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt"; + $sql.= " WHERE dbt.rowid = ".$objectid; + $sql.= " AND dbt.".$dbt_keyfield." = ".$user->societe_id; + } + // If internal user: Check permission for internal users that are restricted on their objects + else if (! empty($conf->societe->enabled) && ($user->rights->societe->lire && ! $user->rights->societe->client->voir)) + { + if (empty($dbt_keyfield)) dol_print_error('','Param dbt_keyfield is required but not defined'); + $sql = "SELECT sc.fk_soc"; + $sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt"; + $sql.= ", ".MAIN_DB_PREFIX."societe as s"; + $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; + $sql.= " WHERE dbt.".$dbt_select." = ".$objectid; + $sql.= " AND sc.fk_soc = dbt.".$dbt_keyfield; + $sql.= " AND dbt.".$dbt_keyfield." = s.rowid"; + $sql.= " AND s.entity IN (".getEntity($sharedelement, 1).")"; + $sql.= " AND sc.fk_user = ".$user->id; + } + // If multicompany and internal users with all permissions, check user is in correct entity + else if (! empty($conf->multicompany->enabled)) + { + $sql = "SELECT dbt.".$dbt_select; + $sql.= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt"; + $sql.= " WHERE dbt.".$dbt_select." = ".$objectid; + $sql.= " AND dbt.entity IN (".getEntity($sharedelement, 1).")"; + } + } + + //print "sql=".$sql."
"; + if ($sql) + { + $resql=$db->query($sql); + if ($resql) + { + if ($db->num_rows($resql) == 0) return false; + } + else + { + return false; + } + } + } + return true; +} /** * Show a message to say access is forbidden and stop program