123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453 |
- <?php
- /*
- * phpMeccano v0.2.0. Web-framework written with php programming language. Core module [policy.php].
- * Copyright (C) 2015-2019 Alexei Muzarov
- *
- * 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 2 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, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * e-mail: azexmail@gmail.com
- * e-mail: azexmail@mail.ru
- * https://bitbucket.org/azexmail/phpmeccano
- */
- namespace core;
- require_once MECCANO_CORE_DIR.'/extclass.php';
- interface intPolicy {
- function __construct(\mysqli $dbLink);
- public function delPolicy($plugin);
- public function setFuncAccess($plugin, $func, $groupId, $access = true); // old name [funcAccess]
- public function installPolicy(\DOMDocument $policy, $validate = true); // old name [install]
- public function groupPolicyList($plugin, $groupId, $code = MECCANO_DEF_LANG);
- public function getPolicyDescById($id);
- }
- class Policy extends ServiceMethods implements intPolicy {
- protected $dbLink; // database link
-
- public function __construct(\mysqli $dbLink) {
- $this->dbLink = $dbLink;
- }
-
- public function delPolicy($plugin) {
- $this->zeroizeError();
- if (!pregPlugin($plugin)) {
- $this->setError(ERROR_INCORRECT_DATA, 'delPolicy: incorrect plugin name');
- return false;
- }
- // checking if plugin exists
- $qPlugin = $this->dbLink->query("SELECT `id` "
- . "FROM `".MECCANO_TPREF."_core_plugins_installed` "
- . "WHERE `name`='$plugin' ;");
- if ($this->dbLink->errno) {
- $this->setError(ERROR_NOT_EXECUTED, 'delPolicy: '.$this->dbLink->error);
- return false;
- }
- if (!$this->dbLink->affected_rows) {
- $this->setError(ERROR_NOT_FOUND, 'delPolicy: unable to find plugin');
- return false;
- }
- $queries = [
- "DELETE `d` FROM `".MECCANO_TPREF."_core_policy_descriptions` `d` "
- . "JOIN `".MECCANO_TPREF."_core_policy_summary_list` `s` "
- . "ON `s`.`id`=`d`.`policyid` "
- . "WHERE `s`.`name`='$plugin' ;",
- "DELETE `a` FROM `".MECCANO_TPREF."_core_policy_access` `a` "
- . "JOIN `".MECCANO_TPREF."_core_policy_summary_list` `s` "
- . "ON `s`.`id`=`a`.`funcid` "
- . "WHERE `s`.`name`='$plugin' ;",
- "DELETE `n` FROM `".MECCANO_TPREF."_core_policy_nosession` `n` "
- . "JOIN `".MECCANO_TPREF."_core_policy_summary_list` `s` "
- . "ON `s`.`id`=`n`.`funcid` "
- . "WHERE `s`.`name`='$plugin' ;",
- "DELETE FROM `".MECCANO_TPREF."_core_policy_summary_list` "
- . "WHERE `name`='$plugin' ;"];
- foreach ($queries as $value) {
- $this->dbLink->query($value);
- if ($this->dbLink->errno) {
- $this->setError(ERROR_NOT_EXECUTED, 'delPolicy: something went wrong -> '.$this->dbLink->error);
- return false;
- }
- }
- return true;
- }
-
- public function setFuncAccess($plugin, $func, $groupId, $access = true) {
- $this->zeroizeError();
- if ($this->usePolicy && !$this->checkFuncAccess('core', 'policy_func_access')) {
- $this->setError(ERROR_RESTRICTED_ACCESS, "setFuncAccess: restricted by the policy");
- return false;
- }
- if (!is_integer($groupId) || !pregPlugin($plugin) || !pregPlugin($func)) {
- $this->setError(ERROR_NOT_EXECUTED, 'setFuncAccess: incorect type of incoming parameters');
- return false;
- }
- if (!$groupId) {
- if ($access) {
- $access = 1;
- }
- else {
- $access = 0;
- }
- $this->dbLink->query("UPDATE `".MECCANO_TPREF."_core_policy_nosession` `n` "
- . "JOIN `".MECCANO_TPREF."_core_policy_summary_list` `s` "
- . "ON `n`.`funcid`=`s`.`id` "
- . "SET `n`.`access`=$access "
- . "WHERE `s`.`func`='$func' "
- . "AND `s`.`name`='$plugin' ;");
- }
- elseif ($access) {
- $this->dbLink->query("UPDATE `".MECCANO_TPREF."_core_policy_access` `a` "
- . "JOIN `".MECCANO_TPREF."_core_policy_summary_list` `s` "
- . "ON `a`.`funcid`=`s`.`id` "
- . "SET `a`.`access`=1 "
- . "WHERE `s`.`func`='$func' "
- . "AND `s`.`name`='$plugin' "
- . "AND `a`.`groupid`=$groupId ;");
- }
- elseif (!$access && $groupId!=1) {
- $this->dbLink->query("UPDATE `".MECCANO_TPREF."_core_policy_access` `a` "
- . "JOIN `".MECCANO_TPREF."_core_policy_summary_list` `s` "
- . "ON `a`.`funcid`=`s`.`id` "
- . "SET `a`.`access`=0 "
- . "WHERE `s`.`func`='$func' "
- . "AND `s`.`name`='$plugin' "
- . "AND `a`.`groupid`=$groupId ;");
- }
- else {
- $this->setError(ERROR_SYSTEM_INTERVENTION, 'setFuncAccess: impossible to disable access for system group');
- return false;
- }
- if ($this->dbLink->errno) {
- $this->setError(ERROR_NOT_EXECUTED, 'setFuncAccess: unable to change access -> '.$this->dbLink->error);
- return false;
- }
- if (!$this->dbLink->affected_rows) {
- $this->setError(ERROR_NOT_FOUND, 'setFuncAccess: plugin name, function or group does not exist or access flag was not changed');
- return false;
- }
- return true;
- }
-
- public function installPolicy(\DOMDocument $policy, $validate = true) {
- $this->zeroizeError();
- if ($validate && !@$policy->relaxNGValidate(MECCANO_CORE_DIR.'/validation-schemas/policy-v01.rng')) {
- $this->setError(ERROR_INCORRECT_DATA, 'installPolicy: incorrect structure of incoming data');
- return false;
- }
- $pluginName = $policy->getElementsByTagName('policy')->item(0)->getAttribute('plugin');
- // check whether plugin is installed
- $qPlugin = $this->dbLink->query("SELECT `id` "
- . "FROM `".MECCANO_TPREF."_core_plugins_installed` "
- . "WHERE `name`='$pluginName' ;");
- if ($this->dbLink->errno) {
- $this->setError(ERROR_NOT_EXECUTED, "installPolicy: unable to check whether the plugin [$pluginName] is installed -> ".$this->dbLink->errno);
- return false;
- }
- if (!$this->dbLink->affected_rows) {
- $this->setError(ERROR_NOT_FOUND, "installPolicy: plugin [$pluginName] is not installed");
- return false;
- }
- // get list of available languages
- $qAvaiLang = $this->dbLink->query("SELECT `code`, `id` "
- . "FROM `".MECCANO_TPREF."_core_langman_languages` ;");
- if ($this->dbLink->errno) {
- $this->setError(ERROR_NOT_EXECUTED, 'installPolicy: unable to get list of available languages: '.$this->dbLink->error);
- return false;
- }
- // avaiable languages
- $avLangIds = [];
- $avLangCodes = [];
- while ($row = $qAvaiLang->fetch_row()) {
- $avLangIds[$row[0]] = $row[1];
- $avLangCodes[] = $row[0];
- }
- $incomingPolicy = [];
- $defaultRules = [];
- $funcNodes = $policy->getElementsByTagName('function');
- foreach ($funcNodes as $funcNode) {
- $funcName = $funcNode->getAttribute('name');
- $nonAuthRule = $funcNode->getAttribute('nonauth');
- $authRule = $funcNode->getAttribute('auth');
- $defaultRules[$funcName] = [(int) $nonAuthRule, (int) $authRule];
- $incomingPolicy[$funcName] = [];
- $langNodes = $funcNode->getElementsByTagName('description');
- foreach ($langNodes as $langNode){
- $code = $langNode->getAttribute('code');
- if (isset($avLangIds[$code])) {
- $incomingPolicy[$funcName][$code]['short'] = $langNode->getElementsByTagName('short')->item(0)->nodeValue;
- $incomingPolicy[$funcName][$code]['detailed'] = $langNode->getElementsByTagName('detailed')->item(0)->nodeValue;
- }
- }
- }
- // get installed policies of the plugin
- $qPolicy = $this->dbLink->query("SELECT `func`, `id` "
- . "FROM `".MECCANO_TPREF."_core_policy_summary_list` "
- . "WHERE `name`='$pluginName' ;");
- if ($this->dbLink->errno) {
- $this->setError(ERROR_NOT_EXECUTED, 'installEvents: unable to get installed events -> '.$this->dbLink->error);
- return false;
- }
- $installedPolicy = [];
- while ($row = $qPolicy->fetch_row()) {
- $installedPolicy[$row[0]] = $row[1];
- }
- // delete outdated policies
- $outdatedPolicy = array_diff(array_keys($installedPolicy), array_keys($incomingPolicy));
- foreach ($outdatedPolicy as $func) {
- $funcId = $installedPolicy[$func];
- $sql = [
- "DELETE FROM `".MECCANO_TPREF."_core_policy_descriptions` "
- . "WHERE `policyid`=$funcId ;",
- "DELETE FROM `".MECCANO_TPREF."_core_policy_access` "
- . "WHERE `funcid`=$funcId ;",
- "DELETE FROM `".MECCANO_TPREF."_core_policy_nosession` "
- . "WHERE `funcid`=$funcId ;",
- "DELETE FROM `".MECCANO_TPREF."_core_policy_summary_list` "
- . "WHERE `id`=$funcId ;"
- ];
- foreach ($sql as $dQuery) {
- $this->dbLink->query($dQuery);
- if ($this->dbLink->errno) {
- $this->setError(ERROR_NOT_EXECUTED, "installPolicy: unable to delete outdated policy -> ".$this->dbLink->error);
- return false;
- }
- }
- }
- // getting of group identifiers
- $qGroupIds = $this->dbLink->query("SELECT `id` "
- . "FROM `".MECCANO_TPREF."_core_userman_groups` ;");
- if ($this->dbLink->errno) {
- $this->setError(ERROR_NOT_EXECUTED, 'installPolicy: unable to get group identifiers -> '.$this->dbLink->error);
- return false;
- }
- $groupIds = [];
- while ($row = $qGroupIds->fetch_row()) {
- $groupIds[] = $row[0];
- }
- // install/update policies
- foreach ($incomingPolicy as $funcName => $descriptions) {
- $missingCodes = array_diff($avLangCodes, array_keys($descriptions));
- if ($missingCodes) {
- foreach ($missingCodes as $code) {
- $descriptions[$code]['short'] = "$funcName";
- $descriptions[$code]['detailed'] = "$funcName";
- }
- }
- // update policy
- if (isset($installedPolicy[$funcName])) {
- $funcId = $installedPolicy[$funcName];
- foreach ($descriptions as $inCode => $desc) {
- $codeId = $avLangIds[$inCode];
- $updateShort = $this->dbLink->real_escape_string($desc['short']);
- $updateDetailed = $this->dbLink->real_escape_string($desc['detailed']);
- // update policy description
- $this->dbLink->query("UPDATE `".MECCANO_TPREF."_core_policy_descriptions` "
- . "SET `short`='$updateShort', `detailed`='$updateDetailed' "
- . "WHERE `policyid`=$funcId "
- . "AND `codeid`=$codeId ;");
- if ($this->dbLink->errno) {
- $this->setError(ERROR_NOT_EXECUTED, 'installPolicy: unable to update policy description -> '.$this->dbLink->error);
- return false;
- }
- }
- }
- // install policy
- else {
- // create record in the summary list
- $this->dbLink->query("INSERT INTO `".MECCANO_TPREF."_core_policy_summary_list` (`name`, `func`) "
- . "VALUES ('$pluginName', '$funcName') ;");
- if ($this->dbLink->errno) {
- $this->setError(ERROR_NOT_EXECUTED, 'installPolicy: unable to add policy into the summary list -> '.$this->dbLink->error);
- return false;
- }
- $insertId = $this->dbLink->insert_id;
- // get default rules
- list($nonAuthRule, $authRule) = $defaultRules[$funcName];
- // policy for the inactive session (non-authorized user)
- $this->dbLink->query("INSERT INTO `".MECCANO_TPREF."_core_policy_nosession` (`funcid`, `access`) "
- . "VALUES ($insertId, $nonAuthRule) ;");
- if ($this->dbLink->errno) {
- $this->setError(ERROR_NOT_EXECUTED, 'installPolicy: unable to create policy for the inactive session -> '.$this->dbLink->error);
- return false;
- }
- // policy for the groups
- foreach ($groupIds as $groupId) {
- if ($groupId == 1) {
- $access = 1;
- }
- else {
- $access = $authRule;
- }
- $this->dbLink->query("INSERT INTO `".MECCANO_TPREF."_core_policy_access` (`groupid`, `funcid`, `access`) "
- . "VALUES ($groupId, $insertId, $access) ;");
- if ($this->dbLink->errno) {
- $this->setError(ERROR_NOT_EXECUTED, 'installPolicy: unable to install group policy -> '.$this->dbLink->error);
- return false;
- }
- }
- // create policy description
- foreach ($descriptions as $inCode => $desc) {
- $codeId = $avLangIds[$inCode];
- $insertShort = $this->dbLink->real_escape_string($desc['short']);
- $insertDetailed = $this->dbLink->real_escape_string($desc['detailed']);
- $this->dbLink->query("INSERT INTO `".MECCANO_TPREF."_core_policy_descriptions` "
- . "(`codeid`, `policyid`, `short`, `detailed`) "
- . "VALUES ($codeId, $insertId, '$insertShort', '$insertDetailed') ;");
- if ($this->dbLink->errno) {
- $this->setError(ERROR_NOT_EXECUTED, 'installPolicy: unable to install policy description -> '.$this->dbLink->error);
- return false;
- }
- }
-
- }
- }
- return true;
- }
-
- public function groupPolicyList($plugin, $groupId, $code = MECCANO_DEF_LANG) {
- $this->zeroizeError();
- if ($this->usePolicy && !$this->checkFuncAccess('core', 'policy_list_about')) {
- $this->setError(ERROR_RESTRICTED_ACCESS, "groupPolicyList: restricted by the policy");
- return false;
- }
- if (!pregPlugin($plugin) || !(is_integer($groupId) || is_bool($groupId)) || !pregLang($code)) {
- $this->setError(ERROR_INCORRECT_DATA, 'groupPolicyList: incorect incoming parameters');
- return false;
- }
- if (!$groupId) {
- $qList = $this->dbLink->query("SELECT `d`.`id`, `d`.`short`, `s`.`func`, `n`.`access` "
- . "FROM `".MECCANO_TPREF."_core_policy_summary_list` `s` "
- . "JOIN `".MECCANO_TPREF."_core_policy_nosession` `n` "
- . "ON `s`.`id`=`n`.`funcid` "
- . "JOIN `".MECCANO_TPREF."_core_policy_descriptions` `d` "
- . "ON `d`.`policyid`=`s`.`id` "
- . "JOIN `".MECCANO_TPREF."_core_langman_languages` `l` "
- . "ON `d`.`codeid`=`l`.`id` "
- . "WHERE `s`.`name`='$plugin' "
- . "AND `l`.`code`='$code' ;");
- }
- else {
- $qList = $this->dbLink->query("SELECT `d`.`id`, `d`.`short`, `s`.`func`, `a`.`access` "
- . "FROM `".MECCANO_TPREF."_core_policy_summary_list` `s` "
- . "JOIN `".MECCANO_TPREF."_core_policy_access` `a` "
- . "ON `s`.`id`=`a`.`funcid` "
- . "JOIN `".MECCANO_TPREF."_core_policy_descriptions` `d` "
- . "ON `d`.`policyid`=`s`.`id` "
- . "JOIN `".MECCANO_TPREF."_core_langman_languages` `l` "
- . "ON `d`.`codeid`=`l`.`id` "
- . "WHERE `s`.`name`='$plugin' "
- . "AND `a`.`groupid`=$groupId "
- . "AND `l`.`code`='$code' ;");
- }
- if ($this->dbLink->errno) {
- $this->setError(ERROR_NOT_EXECUTED, 'groupPolicyList: something went wrong -> '.$this->dbLink->error);
- return false;
- }
- if (!$this->dbLink->affected_rows) {
- $this->setError(ERROR_NOT_FOUND, 'groupPolicyList: not found');
- return false;
- }
- if ($this->outputType == 'xml') {
- $xml = new \DOMDocument('1.0', 'utf-8');
- $policyNode = $xml->createElement('policy');
- $xml->appendChild($policyNode);
- $attr_plugin = $xml->createAttribute('plugin');
- $attr_plugin->value = $plugin;
- $policyNode->appendChild($attr_plugin);
- $attr_group = $xml->createAttribute('group');
- $attr_group->value = $groupId;
- $policyNode->appendChild($attr_group);
- while ($row = $qList->fetch_row()) {
- $funcNode = $xml->createElement('function');
- $policyNode->appendChild($funcNode);
- $funcNode->appendChild($xml->createElement('id', $row[0]));
- $funcNode->appendChild($xml->createElement('short', $row[1]));
- $funcNode->appendChild($xml->createElement('name', $row[2]));
- $funcNode->appendChild($xml->createElement('access', $row[3]));
- }
- return $xml;
- }
- else {
- $policyNode = [];
- $policyNode['plugin'] = $plugin;
- $policyNode['group'] = $groupId;
- $policyNode['functions'] = [];
- while ($row = $qList->fetch_row()) {
- $policyNode['functions'][] = [
- 'id' => (int) $row[0],
- 'short' => $row[1],
- 'name' => $row[2],
- 'access' => (int) $row[3]
- ];
- }
- if ($this->outputType == 'array') {
- return $policyNode;
- }
- else {
- return json_encode($policyNode);
- }
- }
- }
-
- public function getPolicyDescById($id) {
- $this->zeroizeError();
- if ($this->usePolicy && !$this->checkFuncAccess('core', 'policy_list_about')) {
- $this->setError(ERROR_RESTRICTED_ACCESS, "getPolicyDescById: restricted by the policy");
- return false;
- }
- if (!is_integer($id)) {
- $this->setError(ERROR_INCORRECT_DATA, 'getPolicyDescById: identifier must be integer');
- return false;
- }
- $qDesc = $this->dbLink->query("SELECT `short`, `detailed` "
- . "FROM `".MECCANO_TPREF."_core_policy_descriptions` "
- . "WHERE `id`=$id ;");
- if ($this->dbLink->errno) {
- $this->setError(ERROR_NOT_EXECUTED, 'getPolicyDescById: unable to get description -> '.$this->dbLink->error);
- return false;
- }
- if (!$this->dbLink->affected_rows) {
- $this->setError(ERROR_NOT_FOUND, 'getPolicyDescById: description was not found');
- return false;
- }
- list($short, $detailed) = $qDesc->fetch_row();
- if ($this->outputType == 'xml') {
- $xml = new \DOMDocument('1.0', 'utf-8');
- $polycyNode = $xml->createElement('policy');
- $xml->appendChild($polycyNode);
- $idNode = $xml->createElement('id', $id);
- $shortNode = $xml->createElement('short', $short);
- $detailedNode = $xml->createElement('detailed', $detailed);
- $polycyNode->appendChild($idNode);
- $polycyNode->appendChild($shortNode);
- $polycyNode->appendChild($detailedNode);
- return $xml;
- }
- else {
- if ($this->outputType == 'json') {
- return json_encode(['id' => $id, 'short' => $short, 'detailed' => $detailed]);
- }
- else {
- return ['id' => $id, 'short' => $short, 'detailed' => $detailed];
- }
- }
-
- }
-
- }
|