diff --git a/application/controllers/api/v1/system/PCRM.php b/application/controllers/api/v1/system/PCRM.php index 4d527adb1..fda65796d 100644 --- a/application/controllers/api/v1/system/PCRM.php +++ b/application/controllers/api/v1/system/PCRM.php @@ -12,159 +12,28 @@ */ // ------------------------------------------------------------------------ -if(!defined("BASEPATH")) exit("No direct script access allowed"); +if (!defined("BASEPATH")) exit("No direct script access allowed"); class PCRM extends APIv1_Controller { - // Black list of resources that are no allowed to be used - private static $RESOURCES_BLACK_LIST = array("LogLib", "FilesystemLib", "MigrationLib", "REST_Controller"); - /** - * Message API constructor. + * API constructor */ public function __construct() { parent::__construct(); + + // Loads the PCRMLib + $this->load->library("PCRMLib"); } /** - * @return void + * Manages a HTTP get call */ public function getCall() { - $parameters = $this->_getParameters($this->get()); - $validation = $this->_validateCall($parameters); - - // If the validation was passed - if($validation->error == EXIT_SUCCESS) - { - $loaded = null; - // Check if the resource is already loaded, it works only with libraries and drivers - if (($loaded = $this->load->is_loaded($parameters->resourceName)) === false) - { - // If the given resource is a model - if(strpos($parameters->resourceName, "_model") !== false) - { - try - { - // Try to load it - $loaded = $this->load->model($parameters->resourcePath . $parameters->resourceName); - } - catch(Exception $e) - { - // Errors while loading the model - $loaded = null; - $result = $this->_error($e->getMessage()); - } - } - // If the given resource is a library - else if(strpos($parameters->resourceName, "Lib") !== false) - { - // The method "library" of the class CI_Loader provided by CI has some limitations, - // so to be able to check errors was used this workaround - try - { - // Gets all the configured resources paths - $packagePaths = $this->load->get_package_paths(); - // Looking for a file in every paths with the same name of the resource - $found = null; - for ($i = 0; $i < count($packagePaths) && is_null($found); $i++) - { - if (file_exists($packagePaths[$i] . "libraries/" . $parameters->resourcePath . $parameters->resourceName . ".php")) - { - $found = $packagePaths[$i] . "libraries/" . $parameters->resourcePath . $parameters->resourceName . ".php"; - } - } - - // If the file was found - if (!is_null($found)) - { - // Load the file - $loaded = $this->load->file($found); - // If the resource is not present inside the file - if (!class_exists($parameters->resourceName)) - { - $loaded = null; - // Same phrase error as load->model() - $result = $this->_error($found . " exists, but doesn't declare class " . $parameters->resourceName); - } - } - else - { - $loaded = null; - // Same phrase error as load->model() - $result = $this->_error("Unable to load the requested class: " . $parameters->resourceName); - } - } - catch(Exception $e) - { - $result = $this->_error($e->getMessage()); - } - } - // Wrong selection! - else - { - $result = $this->_error("Neither a lib nor model: " . $parameters->resourcePath . $parameters->resourceName); - } - } - - // If the resource was found and loaded - if(!is_null($loaded)) - { - try - { - // Get informations about the function - $reflectionMethod = new ReflectionMethod($parameters->resourceName, $parameters->function); - // If the number of given parameters is equal to the number of parameters required by the function - if ($reflectionMethod->getNumberOfRequiredParameters() == count($parameters->parameters)) - { - // If the function is static - if ($reflectionMethod->isStatic() === true) - { - $classMethod = $parameters->resourceName . "::" . $parameters->function; - } - // If the function is not static - else - { - $classMethod = array(new $parameters->resourceName(), $parameters->function); - } - - // If the function of that resource is callable - if(is_callable($classMethod)) - { - // Call resource->function() - $resultCall = @call_user_func_array($classMethod, $parameters->parameters); - // If errors occurred while running it - if($resultCall === false) - { - $result = $this->_error("Error running " . $parameters->resourceName . "->" . $parameters->function . "()"); - } - // Returns the result of resource->function() - else - { - $result = $resultCall; - } - } - else - { - $result = $this->_error($parameters->resourceName . "->" . $parameters->function . "() is not callable!"); - } - } - else - { - $result = $this->_error("Wrong parameters number"); - } - } - catch(Exception $e) - { - $result = $this->_error($e->getMessage()); - } - } - } - else - { - $result = $validation; - } + // Start me up! + $result = $this->pcrmlib->start($this->get(), PermissionLib::SELECT_RIGHT); // Print the result $this->response($result, REST_Controller::HTTP_OK); @@ -175,88 +44,34 @@ class PCRM extends APIv1_Controller */ public function postCall() { - $validation = $this->_validatePostMessage($this->post()); + // Start me up! + $result = $this->pcrmlib->start($this->post(), PermissionLib::UPDATE_RIGHT); - if(is_object($validation) && $validation->error == EXIT_SUCCESS) - { - $result = $this->messagelib->sendMessage( - $this->post()['person_id'], $this->post()['subject'], $this->post()['body'], PRIORITY_NORMAL, $this->post()['relationmessage_id'], $this->post()['oe_kurzbz'] - ); - - $this->response($result, REST_Controller::HTTP_OK); - } - else - { - $this->response($validation, REST_Controller::HTTP_OK); - } + // Print the result + $this->response($result, REST_Controller::HTTP_OK); } - + /** - * Gets the parameters from the call + * @return void */ - private function _getParameters($parametersArray) + public function putCall() { - $parameters = new stdClass(); - $parameters->parameters = array(); - $count = 0; + // Start me up! + $result = $this->pcrmlib->start($this->put(), PermissionLib::INSERT_RIGHT); - foreach($parametersArray as $parameterName => $parameterValue) - { - // The name of the resource, path included - if($parameterName == "resource") - { - // Separates the resource path from the resource name - $splittedResource = preg_split("/\//", $parameterValue); - $parameters->resourceName = $splittedResource[count($splittedResource) - 1]; - $parameters->resourcePath = str_replace($parameters->resourceName, "", $parameterValue); - } - // The name of the function - else if($parameterName == "function") - { - $parameters->function = $parameterValue; - } - // It is assumed that all other parameters are parameters to be passed to the function - // They will be passed to the function in the same order in which they are passed to - // this controller - else - { - $parameters->parameters[$count++] = $parameterValue; - } - } - - return $parameters; + // Print the result + $this->response($result, REST_Controller::HTTP_OK); } - + /** - * Validate the given parameters + * @return void */ - private function _validateCall($parameters) + public function deleteCall() { - if (!is_object($parameters)) - { - return $this->_error("Parameter is not an object"); - } - if (!isset($parameters->resourcePath)) - { - return $this->_error("Resource path is not specified"); - } - if (!isset($parameters->resourceName)) - { - return $this->_error("Resource name is not specified"); - } - if (!isset($parameters->function)) - { - return $this->_error("Function is not specified"); - } - if (!is_array($parameters->parameters)) - { - return $this->_error("Parameters are not specified"); - } - if (in_array($parameters->resourceName, PCRM::$RESOURCES_BLACK_LIST)) - { - return $this->_error("You are trying to access to unauthorized resources"); - } + // Start me up! + $result = $this->pcrmlib->start($this->delete(), PermissionLib::DELETE_RIGHT); - return $this->_success("Input data are valid"); + // Print the result + $this->response($result, REST_Controller::HTTP_OK); } } \ No newline at end of file diff --git a/application/libraries/PCRMLib.php b/application/libraries/PCRMLib.php new file mode 100644 index 000000000..cd5421b5b --- /dev/null +++ b/application/libraries/PCRMLib.php @@ -0,0 +1,396 @@ +ci =& get_instance(); + + // Loads helper message to manage returning messages + $this->ci->load->helper("message"); + + $this->ci->load->library("PermissionLib"); + } + + /** + * Everything starts here... + */ + public function start($callParameters, $permissionType) + { + $result = null; + $parameters = $this->_getParameters($callParameters); + $validation = $this->_validateCall($parameters); + + // If the validation was passed + if ($validation->error == EXIT_SUCCESS) + { + $loaded = null; + // If the given resource is a model + if (strpos($parameters->resourceName, PCRMLib::MODEL_PREFIX) !== false) + { + // Try to load the model + $result = $this->_loadModel($parameters->resourcePath, $parameters->resourceName); + if ($result->error == EXIT_SUCCESS) + { + $loaded = $result->retval; + } + } + // If the given resource is a library + else if (strpos($parameters->resourceName, PCRMLib::LIB_PREFIX) !== false) + { + // Check if the resource is already loaded, it works only with libraries and drivers + $isLoaded = $this->ci->load->is_loaded($parameters->resourceName); + // If not loaded then load it + if ($isLoaded === false) + { + // Checks if the operation is permitted by the API caller + // Only for libraries, permissions are automatically handled by models + $result = $this->checkLibraryPermission( + $parameters->resourcePath, + $parameters->resourceName, + $parameters->function, + $permissionType + ); + if ($result->error == EXIT_ERROR) + { + $loaded = null; + } + else + { + // Try to load the library + $result = $this->_loadLibrary($parameters->resourcePath, $parameters->resourceName); + if ($result->error == EXIT_SUCCESS) + { + $loaded = $result->retval; + } + } + } + // If it is already loaded $isLoaded contains the instance of the library + else + { + $loaded = $isLoaded; + } + } + // Wrong selection! + else + { + $result = $this->_error("Neither a lib nor model: " . $parameters->resourcePath . $parameters->resourceName); + } + + // If the resource was found and loaded + if (!is_null($loaded)) + { + $result = $this->_callThis($parameters->resourceName, $parameters->function, $parameters->parameters); + } + else + { + // Resource not loaded + } + } + else + { + $result = $validation; + } + + return $result; + } + + /** + * Gets the parameters from the call + */ + private function _getParameters($parametersArray) + { + $parameters = new stdClass(); + $parameters->parameters = array(); + $count = 0; + + foreach ($parametersArray as $parameterName => $parameterValue) + { + // The name of the resource, path included + if ($parameterName == PCRMLib::RESOURCE_PARAMETER) + { + // Separates the resource path from the resource name + $splittedResource = preg_split(PCRMLib::REG_SPLIT_EXPR, $parameterValue); + $parameters->resourceName = $splittedResource[count($splittedResource) - 1]; + $parameters->resourcePath = str_replace($parameters->resourceName, "", $parameterValue); + } + // The name of the function + else if ($parameterName == PCRMLib::FUNCTION_PARAMETER) + { + $parameters->function = $parameterValue; + } + // It is assumed that all other parameters are the parameters to be passed to the function + // They will be passed to the function in the same order in which they are passed to + // this controller + else + { + $parameters->parameters[$count++] = $parameterValue; + } + } + + return $parameters; + } + + /** + * Validate the given parameters + */ + private function _validateCall($parameters) + { + if (!is_object($parameters)) + { + return $this->_error("Parameter is not an object"); + } + if (!isset($parameters->resourcePath)) + { + return $this->_error("Resource path is not specified"); + } + if (!isset($parameters->resourceName)) + { + return $this->_error("Resource name is not specified"); + } + if (!isset($parameters->function)) + { + return $this->_error("Function is not specified"); + } + if (!is_array($parameters->parameters)) + { + return $this->_error("Parameters are not specified"); + } + if (in_array($parameters->resourceName, PCRMLib::$RESOURCES_BLACK_LIST)) + { + return $this->_error("You are trying to access to unauthorized resources"); + } + + return $this->_success("Input data are valid"); + } + + /** + * Loads a model using the given path and name + * + * NOTE: the models automatically handle the permissions + */ + private function _loadModel($resourcePath, $resourceName) + { + $loaded = null; + $result = null; + + try + { + $loaded = $this->ci->load->model($resourcePath . $resourceName); + } + catch (Exception $e) + { + // Errors while loading the model + $result = $this->_error("Errors while loading the model: " . $e->getMessage()); + } + + if (!is_null($loaded)) + { + $result = $this->_success($loaded); + } + + return $result; + } + + private function checkLibraryPermission($resourcePath, $resourceName, $function, $permissionType) + { + $result = null; + $permissionPath = ""; + + if ($resourcePath != "") + { + $permissionPath = $resourcePath; + } + + $permissionPath .= $resourceName . "." . $function; + + if ($this->ci->permissionlib->hasPermission($permissionPath, $permissionType) === false) + { + $result = $this->_error(lang("fhc_".FHC_NORIGHT)." -> ".$permissionPath, FHC_NORIGHT); + } + else + { + $result = $this->_success("Has permission"); + } + + return $result; + } + + /** + * Loads a library using the given path and name + * + * The method "library" of the class CI_Loader provided by CI has some limitations, + * so to be able to check errors was used a workaround. + * It consists in: + * - Checking if the file (identified by parameters $resourcePath and $resourceName) exists + * - If exists it will be loaded using the method "file" from CI_Loader + * - Checks if the loaded file contains a class identified by parameter $resourceName + * + * If one of the previous tests fails, it will be returned a null value + */ + private function _loadLibrary($resourcePath, $resourceName) + { + $loaded = null; + + try + { + // Gets all the configured resources paths + $packagePaths = $this->ci->load->get_package_paths(); + // Looking for a file in every paths with the same name of the resource + $found = null; + for ($i = 0; $i < count($packagePaths) && is_null($found); $i++) + { + $file = $packagePaths[$i] . PCRMLib::LIBS_PATH . DIRECTORY_SEPARATOR . + $resourcePath . $resourceName . PCRMLib::LIB_FILE_EXTENSION; + if (file_exists($file)) + { + $found = $file; + } + } + + // If the file was found + if (!is_null($found)) + { + // Load the file + $loaded = $this->ci->load->file($found); + // If the resource is not present inside the file + if (!class_exists($resourceName)) + { + $loaded = null; + // Same phrase error as load->model() provided by CI + $result = $this->_error($found . " exists, but doesn't declare class " . $resourceName); + } + } + else + { + $loaded = null; + // Same phrase error as load->model() provided by CI + $result = $this->_error("Unable to load the requested class: " . $resourceName); + } + } + catch (Exception $e) + { + // Errors while loading the library + $result = $this->_error("Errors while loading the library: " . $e->getMessage()); + } + + if (!is_null($loaded)) + { + $result = $this->_success($loaded); + } + + return $result; + } + + /** + * Calls a method of a class with the given parameters and returns its result + * + * @param string $resourceName identifies the class name + * @param string $function identifies the method name + * @param array $parameters contains the parameters to be passed to the method + */ + private function _callThis($resourceName, $function, $parameters) + { + $result = null; + + try + { + // Get informations about the function + $reflectionMethod = new ReflectionMethod($resourceName, $function); + // If the number of given parameters is greater or equal to the number of + // parameters required by the function + if (count($parameters) >= $reflectionMethod->getNumberOfRequiredParameters()) + { + // If the function is static + if ($reflectionMethod->isStatic() === true) + { + $classMethod = $resourceName . "::" . $function; + } + // If the function is not static + else + { + $classMethod = array(new $resourceName(), $function); + } + + // If the resource's function is callable + if (is_callable($classMethod)) + { + + // Call resource->function() + // @ was applied to prevent really ugly and unmanageable errors + $resultCall = @call_user_func_array($classMethod, $parameters); + // If errors occurred while running it + // NOTE: if the called function via call_user_func_array returns a boolean set as false, + // it will be recognized like a running error. A little bit tricky ;) + if ($resultCall === false) + { + $result = $this->_error("Error running " . $resourceName . "->" . $function . "()"); + } + // Returns the result of resource->function() + else + { + $result = $this->_success($resultCall); + } + } + else + { + $result = $this->_error($resourceName . "->" . $function . "() is not callable!"); + } + } + else + { + $result = $this->_error( + "Number of required parameters: " . $reflectionMethod->getNumberOfRequiredParameters() . + ". Given: " . count($parameters) + ); + } + } + catch (Exception $e) + { + $result = $this->_error($e->getMessage()); + } + + return $result; + } + + /* + * + */ + private function _error($retval = '', $message = EXIT_ERROR) + { + return error($retval, $message); + } + + /* + * + */ + private function _success($retval, $message = EXIT_SUCCESS) + { + return success($retval, $message); + } +} \ No newline at end of file diff --git a/application/libraries/PermissionLib.php b/application/libraries/PermissionLib.php index de9b43844..880568d0c 100644 --- a/application/libraries/PermissionLib.php +++ b/application/libraries/PermissionLib.php @@ -34,32 +34,54 @@ require_once(FCPATH.'include/benutzerberechtigung.class.php'); class PermissionLib { + const SELECT_RIGHT = "s"; + const UPDATE_RIGHT = "u"; + const INSERT_RIGHT = "i"; + const DELETE_RIGHT = "d"; + public $bb; /** - * Auth Username, Password over FH-Complete - * - * @param string $username - * @param string $password - * @return bool + * */ function __construct() { - $this->CI =& get_instance(); - $this->CI->load->helper('fhcauth'); + // Loads CI instance + $this->ci =& get_instance(); + + // Loads the library to manage the rights system + $this->ci->load->library("FHC_DB_ACL"); + + // Loads the array of resources + $this->ci->fhc_db_acl->acl = $this->ci->config->item('fhc_acl'); } + /** + * @return bool true if a user has the right to access to the specified + * resource with a specified permission type, false otherwise + */ + public function hasPermission($sourceName, $permissionType) + { + // If the resource exists + if (isset($this->ci->fhc_db_acl->acl[$sourceName])) + { + // Checks permission + return $this->ci->fhc_db_acl->isBerechtigt($this->ci->fhc_db_acl->acl[$sourceName], $permissionType); + } + // if the resource does not exist, do not lose useful clock cycles + else + { + return false; + } + } + function isBerechtigt($berechtigung_kurzbz, $art = null, $oe_kurzbz = null, $kostenstelle_id = null) { $this->bb->getBerechtigungen(getAuthUID()); return $this->bb->isBerechtigt($berechtigung_kurzbz, $oe_kurzbz, $art, $kostenstelle_id); } - - function getPermissions($uid) - { - } - function isEntitled($berechtigung_kurzbz, $oe_kurzbz=null, $art=null, $kostenstelle_id=null) - { - } + function getPermissions($uid) {} + + function isEntitled($berechtigung_kurzbz, $oe_kurzbz=null, $art=null, $kostenstelle_id=null) {} } \ No newline at end of file diff --git a/system/mlists/mlists_generate.php b/system/mlists/mlists_generate.php index 56465f353..2f43c5c63 100644 --- a/system/mlists/mlists_generate.php +++ b/system/mlists/mlists_generate.php @@ -419,10 +419,10 @@ $error_msg=''; tbl_studiengang.studiengang_kz=tbl_lehrveranstaltung.studiengang_kz AND (studiensemester_kurzbz='$studiensemester' OR studiensemester_kurzbz='$stsem2') AND - mitarbeiter_uid NOT LIKE '\\_%' AND tbl_studiengang.studiengang_kz!=0 AND + mitarbeiter_uid NOT LIKE '\\\\_%' AND tbl_studiengang.studiengang_kz!=0 AND (mitarbeiter_uid,UPPER(typ::varchar(1) || tbl_studiengang.kurzbz || '_lkt')) NOT IN (SELECT uid, UPPER(gruppe_kurzbz) FROM public.tbl_benutzergruppe - WHERE gruppe_kurzbz LIKE '%\\_LKT' AND UPPER(gruppe_kurzbz)!=UPPER('tw_lkt') AND UPPER(gruppe_kurzbz)!=UPPER('tw_fix_lkt') AND UPPER(gruppe_kurzbz)!=UPPER('tw_ext_lkt') AND UPPER(gruppe_kurzbz)!=UPPER('moodle_lkt'))"; + WHERE gruppe_kurzbz LIKE '%\\\\_LKT' AND UPPER(gruppe_kurzbz)!=UPPER('tw_lkt') AND UPPER(gruppe_kurzbz)!=UPPER('tw_fix_lkt') AND UPPER(gruppe_kurzbz)!=UPPER('tw_ext_lkt') AND UPPER(gruppe_kurzbz)!=UPPER('moodle_lkt'))"; //echo $sql_query; if(!($result=$db->db_query($sql_query))) $error_msg.=$db->db_last_error().$sql_query; diff --git a/tests/codeception/tests/api/v1/PCRMCept.php b/tests/codeception/tests/api/v1/PCRMCept.php new file mode 100644 index 000000000..efd882e60 --- /dev/null +++ b/tests/codeception/tests/api/v1/PCRMCept.php @@ -0,0 +1,21 @@ +wantTo("Test API call v1/system/PCRM/Call"); +$I->amHttpAuthenticated("admin", "1q2w3"); +$I->haveHttpHeader("FHC-API-KEY", "testapikey@fhcomplete.org"); + +$I->sendGET("v1/system/PCRM/Call", array( + "resource" => "codex/Bundesland_model", "function" => "load", "bundesland_code" => "1") +); +$I->seeResponseCodeIs(200); +$I->seeResponseIsJson(); +$I->seeResponseContainsJson(["error" => 0]); + +$I->sendGET("v1/system/PCRM/Call", array( + "resource" => "PermissionLib", "function" => "hasPermission", + "sn" => "bis.tbl_archiv", "pt" => "s") +); +$I->seeResponseCodeIs(200); +$I->seeResponseIsJson(); +$I->seeResponseContainsJson(["error" => 0]); \ No newline at end of file diff --git a/vilesci/stammdaten/reihungstestverwaltung.php b/vilesci/stammdaten/reihungstestverwaltung.php index 5da26c393..f1979fe6e 100644 --- a/vilesci/stammdaten/reihungstestverwaltung.php +++ b/vilesci/stammdaten/reihungstestverwaltung.php @@ -1286,6 +1286,10 @@ else echo ' '; echo ''; } + else + { + echo 'Keine Berechtigung zum zuteilen von Räumen'; + } foreach ($orte->result AS $row) { //echo ' ';