Sync changes v29.0.0 from IceHrmPro (https://icehrm.com/purchase-icehrmpro)
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
namespace Classes;
|
||||
|
||||
use Model\BaseModel;
|
||||
use Utils\LogManager;
|
||||
|
||||
abstract class AbstractModuleManager
|
||||
@@ -254,7 +255,17 @@ abstract class AbstractModuleManager
|
||||
protected function addModelClass($className)
|
||||
{
|
||||
$this->modelClasses[] = $className;
|
||||
BaseService::getInstance()->addModelClass($className, $this->moduleObject['model_namespace']."\\".$className);
|
||||
$classWithNamespace = $this->moduleObject['model_namespace']."\\".$className;
|
||||
BaseService::getInstance()->addModelClass($className, $classWithNamespace);
|
||||
/** @var BaseModel $modelClass */
|
||||
$modelClass = new $classWithNamespace();
|
||||
if ($modelClass->isCustomFieldsEnabled()) {
|
||||
$objectName = $modelClass->getObjectName();
|
||||
BaseService::getInstance()->addCustomFieldClass(
|
||||
$className,
|
||||
(null === $objectName)? $className : $objectName
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
protected function addHistoryGeneric($type, $table, $refName, $refId, $field, $oldValue, $newValue)
|
||||
@@ -278,4 +289,12 @@ abstract class AbstractModuleManager
|
||||
{
|
||||
BaseService::getInstance()->addCalculationHook($code, $name, $class, $method);
|
||||
}
|
||||
|
||||
public function install()
|
||||
{
|
||||
}
|
||||
|
||||
public function uninstall()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ use Employees\Common\Model\EmployeeApproval;
|
||||
use FieldNames\Common\Model\CustomField;
|
||||
use FieldNames\Common\Model\FieldNameMapping;
|
||||
use Metadata\Common\Model\CalculationHook;
|
||||
use Model\BaseModel;
|
||||
use Model\DataEntryBackup;
|
||||
use Model\Setting;
|
||||
use Modules\Common\Model\Module;
|
||||
@@ -51,7 +52,8 @@ class BaseService
|
||||
public $calculationHooks = array();
|
||||
public $customFieldManager = null;
|
||||
public $migrationManager = null;
|
||||
public $modelClassMap = array();
|
||||
public $modelClassMap = [];
|
||||
public $customFieldsClassMap = [];
|
||||
public $currentProfileId = false;
|
||||
|
||||
protected $cacheService = null;
|
||||
@@ -167,6 +169,20 @@ class BaseService
|
||||
$this->modelClassMap[$modelClass] = $fullQualifiedName;
|
||||
}
|
||||
|
||||
public function getCustomFieldClassMap()
|
||||
{
|
||||
$map = [];
|
||||
foreach($this->customFieldsClassMap as $key => $val) {
|
||||
$map[] = [$key, $val];
|
||||
}
|
||||
return $map;
|
||||
}
|
||||
|
||||
public function addCustomFieldClass($customFieldsClass, $objectName)
|
||||
{
|
||||
$this->customFieldsClassMap[$customFieldsClass] = $objectName;
|
||||
}
|
||||
|
||||
public function getModelClassName($name)
|
||||
{
|
||||
return $this->getFullQualifiedModelClassName($name);
|
||||
@@ -637,7 +653,10 @@ class BaseService
|
||||
|
||||
$processedList = array();
|
||||
foreach ($list as $obj) {
|
||||
$processedList[] = $this->cleanUpAdoDB($obj->postProcessGetData($obj));
|
||||
$processedObj = $this->cleanUpAdoDB($obj->postProcessGetData($obj));
|
||||
if (null !== $processedObj) {
|
||||
$processedList[] = $processedObj;
|
||||
}
|
||||
}
|
||||
|
||||
$list = $processedList;
|
||||
@@ -749,7 +768,7 @@ class BaseService
|
||||
$obj = $this->enrichObjectCustomFields($table, $obj);
|
||||
|
||||
$obj = $obj->postProcessGetElement($obj);
|
||||
return $this->cleanUpAdoDB($obj->postProcessGetData($obj));
|
||||
return $this->cleanUpAdoDB($obj);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -928,6 +947,7 @@ class BaseService
|
||||
{
|
||||
$fileFields = $this->fileFields;
|
||||
$nsTable = $this->getFullQualifiedModelClassName($table);
|
||||
/** @var BaseModel $ele */
|
||||
$ele = new $nsTable();
|
||||
|
||||
$ele->Load('id = ?', array($id));
|
||||
@@ -985,7 +1005,7 @@ class BaseService
|
||||
$dataEntryBackup->data = json_encode($newObj);
|
||||
$dataEntryBackup->Save();
|
||||
}
|
||||
|
||||
$ele->executePostDeleteActions($ele);
|
||||
$this->audit(IceConstants::AUDIT_DELETE, "Deleted an object in ".$table." [id:".$ele->id."]");
|
||||
}
|
||||
|
||||
@@ -998,6 +1018,7 @@ class BaseService
|
||||
}
|
||||
|
||||
$cfs = $this->customFieldManager->getCustomFields($table, $id);
|
||||
/** @var CustomField $cf */
|
||||
foreach ($cfs as $cf) {
|
||||
$cf->Delete();
|
||||
}
|
||||
@@ -1804,7 +1825,7 @@ END;
|
||||
$companyStructure->Load('id = ?', array($parentCompanyStructure));
|
||||
}
|
||||
} while (!empty($companyStructure->id)
|
||||
&& !empty($parentCompanyStructure)
|
||||
&& !empty($parentCompanyStructure)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -61,6 +61,7 @@ class DomainAwareInputCleaner
|
||||
|
||||
$filterData = json_decode($filters, true);
|
||||
foreach ($filterData as $name => $value) {
|
||||
|
||||
if (!$this->isValidColumnName($name) || !$this->isValidFilterValue($value)) {
|
||||
return '';
|
||||
}
|
||||
@@ -90,6 +91,14 @@ class DomainAwareInputCleaner
|
||||
|
||||
private function isValidFilterValue($input)
|
||||
{
|
||||
if (is_array($input)) {
|
||||
$isValid = true;
|
||||
foreach ($input as $val) {
|
||||
$isValid = $isValid && !!preg_match('/^[-_: \d\p{L}]+$/u', $val);
|
||||
}
|
||||
|
||||
return $isValid;
|
||||
}
|
||||
return !!preg_match('/^[-_: \d\p{L}]+$/u', $input);
|
||||
}
|
||||
}
|
||||
|
||||
146
core/src/Classes/ExtensionManager.php
Normal file
146
core/src/Classes/ExtensionManager.php
Normal file
@@ -0,0 +1,146 @@
|
||||
<?php
|
||||
|
||||
namespace Classes;
|
||||
|
||||
use Utils\LogManager;
|
||||
|
||||
class ExtensionManager
|
||||
{
|
||||
const GROUP = 'extension';
|
||||
protected function processExtensionInDB()
|
||||
{
|
||||
$dbModule = new \Modules\Common\Model\Module();
|
||||
$extensions = $dbModule->Find("mod_group = ?", array(self::GROUP));
|
||||
|
||||
$extensionsInDB = [];
|
||||
foreach ($extensions as $dbm) {
|
||||
$extensionsInDB[$dbm->name] = $dbm;
|
||||
ModuleAccessService::getInstance()->setModule($dbm->name, self::GROUP, $dbm);
|
||||
}
|
||||
|
||||
return $extensionsInDB;
|
||||
}
|
||||
|
||||
public function getExtensionsPath()
|
||||
{
|
||||
return APP_BASE_PATH.'../extensions/';
|
||||
}
|
||||
|
||||
public function getExtensionMetaData($extensionName)
|
||||
{
|
||||
return json_decode(file_get_contents($this->getExtensionsPath().$extensionName.'/meta.json'));
|
||||
}
|
||||
|
||||
public function setupExtensions()
|
||||
{
|
||||
$menu = [];
|
||||
$extensions = [];
|
||||
$extensionDirs = scandir($this->getExtensionsPath());
|
||||
$currentLocation = 0;
|
||||
|
||||
$extensionsInDB = $this->processExtensionInDB();
|
||||
|
||||
$needToInstall = false;
|
||||
|
||||
foreach ($extensionDirs as $extensionDir) {
|
||||
if (is_dir($this->getExtensionsPath().$extensionDir) && $extensionDir != '.' && $extensionDir != '..') {
|
||||
$meta = $this->getExtensionMetaData($extensionDir);
|
||||
|
||||
$arr = [];
|
||||
$arr['name'] = $extensionDir;
|
||||
$arr['label'] = $meta->label;
|
||||
$arr['icon'] = $meta->icon;
|
||||
$arr['menu'] = $meta->menu[0];
|
||||
$arr['order'] = 0;
|
||||
$arr['status'] = 'Enabled';
|
||||
$arr['user_levels'] = $meta->user_levels;
|
||||
$arr['user_roles'] = isset($meta->user_roles)?$meta->user_roles:"";
|
||||
$arr['model_namespace'] = $meta->model_namespace;
|
||||
$arr['manager'] = $meta->manager;
|
||||
|
||||
// Add menu
|
||||
$menu[$meta->menu[0]] = $meta->menu[1];
|
||||
|
||||
//Check in admin dbmodules
|
||||
if (isset($extensionsInDB[$arr['name']])) {
|
||||
$dbModule = $extensionsInDB[$arr['name']];
|
||||
|
||||
$arr['name'] = $dbModule->name;
|
||||
$arr['label'] = $dbModule->label;
|
||||
$arr['icon'] = $dbModule->icon;
|
||||
$arr['menu'] = $dbModule->menu;
|
||||
$arr['status'] = $dbModule->status;
|
||||
$arr['user_levels'] = json_decode($dbModule->user_levels);
|
||||
$arr['user_roles'] = empty($dbModule->user_roles)
|
||||
? [] : json_decode($dbModule->user_roles);
|
||||
$arr['user_roles_blacklist'] = empty($dbModule->user_roles_blacklist)
|
||||
? [] : json_decode($dbModule->user_roles_blacklist);
|
||||
} else {
|
||||
$dbModule = new \Modules\Common\Model\Module();
|
||||
$dbModule->menu = $arr['menu'];
|
||||
$dbModule->name = $arr['name'];
|
||||
$dbModule->label = $arr['label'];
|
||||
$dbModule->icon = $arr['icon'];
|
||||
$dbModule->mod_group = self::GROUP;
|
||||
$dbModule->mod_order = $arr['order'];
|
||||
$dbModule->status = "Enabled";
|
||||
$dbModule->version = isset($meta->version)?$meta->version:"";
|
||||
$dbModule->update_path = self::GROUP.">".$extensionDir;
|
||||
$dbModule->user_levels = isset($meta->user_levels)?json_encode($meta->user_levels):"";
|
||||
$dbModule->user_roles = isset($meta->user_roles)?json_encode($meta->user_roles):"";
|
||||
|
||||
$ok = $dbModule->Save();
|
||||
if (!$ok) {
|
||||
LogManager::getInstance()->error('Error saving module: '.$dbModule->name);
|
||||
}
|
||||
$needToInstall = $ok;
|
||||
}
|
||||
|
||||
/* @var \Classes\AbstractModuleManager */
|
||||
$manager = $this->includeModuleManager($extensionDir, $arr);
|
||||
if ($dbModule->status == 'Disabled') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($needToInstall) {
|
||||
$manager->install();
|
||||
}
|
||||
|
||||
$menuName = $arr['menu'];
|
||||
if (!isset($extensions[$menuName])) {
|
||||
$extensions[$menuName] = array();
|
||||
}
|
||||
|
||||
if (!$meta->headless) {
|
||||
if ($arr['order'] == '0' || $arr['order'] == '') {
|
||||
$extensions[$menuName]["Z".$currentLocation] = $arr;
|
||||
$currentLocation++;
|
||||
} else {
|
||||
$extensions[$arr['menu']]["A".$arr['order']] = $arr;
|
||||
}
|
||||
}
|
||||
|
||||
$initializer = $manager->getInitializer();
|
||||
if ($initializer !== null) {
|
||||
$initializer->setBaseService(BaseService::getInstance());
|
||||
$initializer->init();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [$menu, $extensions];
|
||||
}
|
||||
|
||||
public function includeModuleManager($name, $data)
|
||||
{
|
||||
include($this->getExtensionsPath().$name.'/'.$name.'.php');
|
||||
$moduleManagerClass = $data['manager'];
|
||||
/* @var \Classes\AbstractModuleManager $moduleManagerObj*/
|
||||
$moduleManagerObj = new $moduleManagerClass();
|
||||
$moduleManagerObj->setModuleObject($data);
|
||||
$moduleManagerObj->setModuleType(self::GROUP);
|
||||
$moduleManagerObj->setModulePath(CLIENT_PATH.'/'.self::GROUP.'/'.$name);
|
||||
\Classes\BaseService::getInstance()->addModuleManager($moduleManagerObj);
|
||||
return $moduleManagerObj;
|
||||
}
|
||||
}
|
||||
20
core/src/Classes/IceExtension.php
Normal file
20
core/src/Classes/IceExtension.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
namespace Classes;
|
||||
|
||||
abstract class IceExtension extends AbstractModuleManager
|
||||
{
|
||||
public function initializeUserClasses()
|
||||
{
|
||||
// TODO: Implement initializeUserClasses() method.
|
||||
}
|
||||
|
||||
public function initializeFieldMappings()
|
||||
{
|
||||
// TODO: Implement initializeFieldMappings() method.
|
||||
}
|
||||
|
||||
public function initializeDatabaseErrorMappings()
|
||||
{
|
||||
// TODO: Implement initializeDatabaseErrorMappings() method.
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Classes;
|
||||
|
||||
use Firebase\JWT\JWT;
|
||||
use Firebase\JWT\SignatureInvalidException;
|
||||
|
||||
class JwtTokenService
|
||||
{
|
||||
@@ -22,7 +23,11 @@ class JwtTokenService
|
||||
public function getBaseToken($jwtToken)
|
||||
{
|
||||
$secret = APP_SEC.APP_PASSWORD;
|
||||
$jwt = JWT::decode($jwtToken, $secret, array('HS256'));
|
||||
try {
|
||||
$jwt = JWT::decode($jwtToken, $secret, array('HS256'));
|
||||
} catch (SignatureInvalidException $e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (time() > intval($jwt->expire)) {
|
||||
return null;
|
||||
|
||||
@@ -15,6 +15,8 @@ class MemcacheService
|
||||
public static $openConnections = array();
|
||||
private static $me = null;
|
||||
|
||||
protected $inMemoryStore = [];
|
||||
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
@@ -56,6 +58,15 @@ class MemcacheService
|
||||
}
|
||||
|
||||
public function set($key, $value, $expiry = 3600)
|
||||
{
|
||||
if (!$this->setInServer($key, $value, $expiry)) {
|
||||
$this->inMemoryStore[$this->compressKey($key)] = $value;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function setInServer($key, $value, $expiry = 3600)
|
||||
{
|
||||
if (!class_exists('\\Memcached')) {
|
||||
return false;
|
||||
@@ -74,6 +85,19 @@ class MemcacheService
|
||||
}
|
||||
|
||||
public function get($key)
|
||||
{
|
||||
$data = $this->getFromServer($key);
|
||||
if ($data) {
|
||||
return $data;
|
||||
}
|
||||
if (isset($this->inMemoryStore[$this->compressKey($key)])) {
|
||||
return $this->inMemoryStore[$this->compressKey($key)];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getFromServer($key)
|
||||
{
|
||||
if (!class_exists('\\Memcached')) {
|
||||
return false;
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
namespace Classes\Migration;
|
||||
|
||||
use Utils\LogManager;
|
||||
|
||||
abstract class AbstractMigration
|
||||
{
|
||||
protected $file;
|
||||
@@ -16,7 +18,7 @@ abstract class AbstractMigration
|
||||
|
||||
protected $lastError;
|
||||
|
||||
public function __construct($file)
|
||||
public function __construct($file = null)
|
||||
{
|
||||
$this->file = $file;
|
||||
}
|
||||
@@ -50,6 +52,7 @@ abstract class AbstractMigration
|
||||
$ret = $this->db()->Execute($sql);
|
||||
if (!$ret) {
|
||||
$this->lastError = $this->db()->ErrorMsg();
|
||||
LogManager::getInstance()->error('Error in migration: '.$this->lastError);
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ class ModuleAccess
|
||||
* @param $name
|
||||
* @param $group
|
||||
*/
|
||||
public function __construct($name, $group)
|
||||
public function __construct($name, $group = 'extension')
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->group = $group;
|
||||
|
||||
98
core/src/Classes/ModuleBuilderV2/ModuleBuilder.php
Normal file
98
core/src/Classes/ModuleBuilderV2/ModuleBuilder.php
Normal file
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: Thilina
|
||||
* Date: 8/20/17
|
||||
* Time: 9:47 AM
|
||||
*/
|
||||
|
||||
namespace Classes\ModuleBuilderV2;
|
||||
|
||||
use Classes\PermissionManager;
|
||||
|
||||
class ModuleBuilder
|
||||
{
|
||||
public $modules = array();
|
||||
public $user = null;
|
||||
|
||||
function __construct()
|
||||
{
|
||||
$this->user = \Classes\BaseService::getInstance()->getCurrentUser();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ModuleTab $module
|
||||
*/
|
||||
public function addModuleOrGroup($module)
|
||||
{
|
||||
$this->modules[] = $module;
|
||||
}
|
||||
|
||||
public function getTabHeadersHTML()
|
||||
{
|
||||
$html = "";
|
||||
foreach ($this->modules as $module) {
|
||||
$html .= $module->getHTML()."\r\n";
|
||||
}
|
||||
return $html;
|
||||
}
|
||||
|
||||
public function getTabPagesHTML()
|
||||
{
|
||||
$html = "";
|
||||
/* @var ModuleTab $module */
|
||||
foreach ($this->modules as $module) {
|
||||
if (get_class($module) === ModuleTab::class) {
|
||||
$html .= $module->getPageHTML()."\r\n";
|
||||
} else {
|
||||
/* @var ModuleTab $mod */
|
||||
foreach ($module->modules as $mod) {
|
||||
$html .= $mod->getPageHTML()."\r\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
return $html;
|
||||
}
|
||||
|
||||
public function getModJsHTML()
|
||||
{
|
||||
$moduleData = [
|
||||
'user_level' => $this->user->user_level,
|
||||
'permissions' => [
|
||||
]
|
||||
];
|
||||
|
||||
$html = "var modJsList = new Array();\r\n";
|
||||
$activeModule = "";
|
||||
/* @var ModuleTab $module */
|
||||
foreach ($this->modules as $module) {
|
||||
if (get_class($module) == ModuleTab::class) {
|
||||
$html .= $module->getJSObjectCode()."\r\n";
|
||||
|
||||
$modelClass = $module->modelPath;
|
||||
$moduleData['permissions'][$module->name] = PermissionManager::checkGeneralAccess(new $modelClass());
|
||||
|
||||
if ($module->isActive) {
|
||||
$activeModule = $module->name;
|
||||
}
|
||||
} else {
|
||||
/* @var ModuleTab $mod */
|
||||
foreach ($module->modules as $mod) {
|
||||
$modelClass = $mod->modelPath;
|
||||
$moduleData['permissions'][$mod->name] = PermissionManager::checkGeneralAccess(new $modelClass());
|
||||
|
||||
if ($module->isActive && $activeModule == "") {
|
||||
$activeModule = $mod->name;
|
||||
}
|
||||
$html .= $mod->getJSObjectCode()."\r\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$html .= "var modJs = modJsList['tab".$activeModule."'];\r\n";
|
||||
|
||||
$html = "var data = ".json_encode($moduleData).";\r\n".$html;
|
||||
|
||||
return $html;
|
||||
}
|
||||
}
|
||||
96
core/src/Classes/ModuleBuilderV2/ModuleTab.php
Normal file
96
core/src/Classes/ModuleBuilderV2/ModuleTab.php
Normal file
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: Thilina
|
||||
* Date: 8/20/17
|
||||
* Time: 9:47 AM
|
||||
*/
|
||||
|
||||
namespace Classes\ModuleBuilderV2;
|
||||
|
||||
class ModuleTab
|
||||
{
|
||||
public $modelPath;
|
||||
public $name;
|
||||
public $class;
|
||||
public $label;
|
||||
public $adapterName;
|
||||
public $filter;
|
||||
public $orderBy;
|
||||
public $isActive = false;
|
||||
public $isInsideGroup = false;
|
||||
public $options = array();
|
||||
|
||||
public function __construct(
|
||||
$modelPath,
|
||||
$name,
|
||||
$class,
|
||||
$label,
|
||||
$adapterName,
|
||||
$filter,
|
||||
$orderBy,
|
||||
$isActive = false,
|
||||
$options = array()
|
||||
)
|
||||
{
|
||||
$this->modelPath = $modelPath;
|
||||
$this->name = $name;
|
||||
$this->class = $class;
|
||||
$this->label = $label;
|
||||
$this->adapterName = $adapterName;
|
||||
$this->filter = $filter;
|
||||
$this->orderBy = $orderBy;
|
||||
$this->isActive = $isActive;
|
||||
|
||||
$this->options = array_merge(
|
||||
$options, [
|
||||
"setObjectTypeName" => "'{$this->name}'",
|
||||
"setAccess" => "data.permissions.{$this->name} ? data.permissions.{$this->name} : {}",
|
||||
"setDataPipe" => 'new IceDataPipe(modJsList.tab' . $this->name . ')',
|
||||
"setRemoteTable" => true,
|
||||
]);
|
||||
}
|
||||
|
||||
public function getHTML()
|
||||
{
|
||||
$active = ($this->isActive)?"active":"";
|
||||
if (!$this->isInsideGroup) {
|
||||
return '<li class="' . $active . '"><a id="tab' . $this->name
|
||||
. '" href="#tabPage' . $this->name . '">' . t($this->label) . '</a></li>';
|
||||
} else {
|
||||
return '<li class="' . $active . '"><a id="tab' . $this->name
|
||||
. '" href="#tabPage' . $this->name . '">' . t($this->label) . '</a></li>';
|
||||
}
|
||||
}
|
||||
|
||||
public function getPageHTML()
|
||||
{
|
||||
$active = ($this->isActive)?" active":"";
|
||||
$html = '<div class="tab-pane'.$active.'" id="tabPage'.$this->name.'">'.
|
||||
'<div id="'.$this->name.'Table" class="reviewBlock" data-content="List" style="padding-left:5px;"></div>'.
|
||||
'<div id="'.$this->name.'Form"></div>'.
|
||||
'<div id="'.$this->name.'FilterForm"></div>'.
|
||||
'</div>';
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
public function getJSObjectCode()
|
||||
{
|
||||
$js = "";
|
||||
if (empty($this->filter)) {
|
||||
$js.= "modJsList['tab" . $this->name . "'] = new " .
|
||||
$this->adapterName . "('" . $this->class . "','" . $this->name . "','','".$this->orderBy. "');\r\n";
|
||||
} else {
|
||||
$js.= "modJsList['tab" . $this->name . "'] = new " .
|
||||
$this->adapterName . "('" . $this->class . "','" . $this->name . "'," .
|
||||
$this->filter . ",'".$this->orderBy. "');\r\n";
|
||||
}
|
||||
|
||||
foreach ($this->options as $key => $val) {
|
||||
$js.= "modJsList['tab" . $this->name . "'].".$key."(".$val. ");\r\n";
|
||||
}
|
||||
|
||||
return $js;
|
||||
}
|
||||
}
|
||||
53
core/src/Classes/ModuleBuilderV2/ModuleTabGroup.php
Normal file
53
core/src/Classes/ModuleBuilderV2/ModuleTabGroup.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: Thilina
|
||||
* Date: 8/20/17
|
||||
* Time: 9:48 AM
|
||||
*/
|
||||
|
||||
namespace Classes\ModuleBuilderV2;
|
||||
|
||||
class ModuleTabGroup
|
||||
{
|
||||
public $name;
|
||||
public $label;
|
||||
public $isActive = false;
|
||||
public $modules = array();
|
||||
|
||||
public function __construct($name, $label)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->label = $label;
|
||||
}
|
||||
|
||||
public function addModuleTab($moduleTab)
|
||||
{
|
||||
if ($moduleTab->isActive) {
|
||||
$this->isActive = true;
|
||||
$moduleTab->isActive = false;
|
||||
}
|
||||
$moduleTab->isInsideGroup = true;
|
||||
$this->modules[] = $moduleTab;
|
||||
}
|
||||
|
||||
public function getHTML()
|
||||
{
|
||||
$html = "";
|
||||
$active = ($this->isActive)?" active":"";
|
||||
|
||||
$html.= '<li class="dropdown'.$active.'">'."\r\n".
|
||||
'<a href="#" id="'.$this->name.
|
||||
'" class="dropdown-toggle" data-toggle="dropdown" aria-controls="'.$this->name.
|
||||
'-contents">'.$this->label.' <span class="caret"></span></a>'."\r\n".
|
||||
'<ul class="dropdown-menu" role="menu" aria-labelledby="'.$this->name.'" id="'.$this->name.'-contents">';
|
||||
|
||||
foreach ($this->modules as $module) {
|
||||
$html.= $module->getHTML();
|
||||
}
|
||||
|
||||
$html .= "</ul></li>";
|
||||
|
||||
return $html;
|
||||
}
|
||||
}
|
||||
@@ -103,7 +103,7 @@ class PasswordManager
|
||||
return new IceResponse(IceResponse::ERROR, $error);
|
||||
}
|
||||
|
||||
if (strlen($password) > 20) {
|
||||
if (strlen($password) > 30) {
|
||||
$error = "Password too long";
|
||||
|
||||
return new IceResponse(IceResponse::ERROR, $error);
|
||||
|
||||
@@ -424,10 +424,8 @@ class RestEndPoint
|
||||
$token = $_GET['token'];
|
||||
}
|
||||
|
||||
if (strlen($token) > 32) {
|
||||
$tokenService = new JwtTokenService();
|
||||
$token = $tokenService->getBaseToken($token);
|
||||
}
|
||||
$tokenService = new JwtTokenService();
|
||||
$token = $tokenService->getBaseToken($token);
|
||||
|
||||
return $token;
|
||||
}
|
||||
|
||||
85
core/src/Classes/SAMLManager.php
Normal file
85
core/src/Classes/SAMLManager.php
Normal file
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
namespace Classes;
|
||||
|
||||
use \RobRichards\XMLSecLibs\MoXMLSecurityKey;
|
||||
use Utils\LogManager;
|
||||
|
||||
class SAMLManager
|
||||
{
|
||||
public function getSSOEmail($samlData, $relayState) {
|
||||
// Service Providers Assertion Consumer Service (ACS) URL
|
||||
$acsUrl = CLIENT_BASE_URL.'login.php';
|
||||
$samlResponse = htmlspecialchars($samlData);
|
||||
|
||||
$samlResponse = base64_decode($samlResponse);
|
||||
|
||||
$document = new \DOMDocument();
|
||||
$document->loadXML($samlResponse);
|
||||
$samlResponseXml = $document->firstChild;
|
||||
|
||||
$doc = $document->documentElement;
|
||||
$xpath = new \DOMXpath($document);
|
||||
$xpath->registerNamespace('samlp', 'urn:oasis:names:tc:SAML:2.0:protocol');
|
||||
$xpath->registerNamespace('saml', 'urn:oasis:names:tc:SAML:2.0:assertion');
|
||||
|
||||
$status = $xpath->query('/samlp:Response/samlp:Status/samlp:StatusCode', $doc);
|
||||
$statusString = $status->item(0)->getAttribute('Value');
|
||||
|
||||
|
||||
$statusArray = explode(':',$statusString);
|
||||
if(array_key_exists(7, $statusArray)){
|
||||
$status = $statusArray[7];
|
||||
}
|
||||
|
||||
if ('Success' !== $status) {
|
||||
$StatusMessage = $xpath->query('/samlp:Response/samlp:Status/samlp:StatusMessage', $doc)->item(0);
|
||||
LogManager::getInstance()->error('SAML login failed: status = '. $status);
|
||||
if(!empty($StatusMessage)) {
|
||||
$StatusMessage = $StatusMessage->nodeValue;
|
||||
LogManager::getInstance()->error('SAML login failed: status message = '. $StatusMessage);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
$x509cert = SettingsManager::getInstance()->getSetting('SAML: X.509 Certificate');
|
||||
|
||||
$samlResponse = new \SAML2_Response($samlResponseXml);
|
||||
$responseSignatureData = $samlResponse->getSignatureData();
|
||||
$assertionSignatureData = current($samlResponse->getAssertions())->getSignatureData();
|
||||
|
||||
$certFingerPrint = MoXMLSecurityKey::getRawThumbprint($x509cert);
|
||||
$certFingerPrint = preg_replace('/\s+/', '', $certFingerPrint);
|
||||
$validSignature = false;
|
||||
if(!empty($responseSignatureData)) {
|
||||
$validSignature = \Utilities::processResponse($acsUrl, $certFingerPrint, $responseSignatureData, $samlResponse, 0, $relayState);
|
||||
LogManager::getInstance()->error('SAML: response signature validity :'.$validSignature);
|
||||
}
|
||||
|
||||
if(!empty($assertionSignatureData)) {
|
||||
$validSignature = \Utilities::processResponse($acsUrl, $certFingerPrint, $assertionSignatureData, $samlResponse, 0, $relayState);
|
||||
LogManager::getInstance()->error('SAML: response signature validity :'.$validSignature);
|
||||
}
|
||||
|
||||
if(!$validSignature) {
|
||||
LogManager::getInstance()->error('Invalid response or assertion signature');
|
||||
return false;
|
||||
}
|
||||
|
||||
$issuer = current($samlResponse->getAssertions())->getIssuer();
|
||||
$assertion = current($samlResponse->getAssertions());
|
||||
$audiences = $assertion->getValidAudiences();
|
||||
$expectedIssuer = SettingsManager::getInstance()->getSetting('SAML: IDP Issuer');
|
||||
if ($issuer !== $expectedIssuer) {
|
||||
LogManager::getInstance()->error('SAML Invalid Issuer :'.$issuer.' expected :'.$expectedIssuer);
|
||||
return false;
|
||||
}
|
||||
|
||||
$ssoEmail = current(current($samlResponse->getAssertions())->getNameId());
|
||||
if (!$ssoEmail) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $ssoEmail;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,22 @@
|
||||
<?php
|
||||
namespace Classes;
|
||||
|
||||
use Classes\Crypt\AesCtr;
|
||||
use Model\Setting;
|
||||
|
||||
class SettingsManager
|
||||
{
|
||||
|
||||
const ENCRYPTED_PREFIX = 'iceenc_';
|
||||
|
||||
private static $me = null;
|
||||
|
||||
private $encryptedSettings = [];
|
||||
|
||||
private function __construct()
|
||||
{
|
||||
$this->addEncryptedSetting('SAML: X.509 Certificate');
|
||||
$this->addEncryptedSetting('LDAP: Manager Password');
|
||||
}
|
||||
|
||||
public static function getInstance()
|
||||
@@ -21,9 +28,62 @@ class SettingsManager
|
||||
return self::$me;
|
||||
}
|
||||
|
||||
public function addEncryptedSetting($name) {
|
||||
if (!$this->isEncryptedSetting($name)) {
|
||||
$this->encryptedSettings[] = $name;
|
||||
}
|
||||
}
|
||||
|
||||
public function isEncryptedSetting($name) {
|
||||
return in_array($name, $this->encryptedSettings);
|
||||
}
|
||||
|
||||
public function getInstanceKey() {
|
||||
$settings = new Setting();
|
||||
$settings->Load("name = ?", array("Instance: Key"));
|
||||
if ($settings->name != "Instance: Key") {
|
||||
return null;
|
||||
}
|
||||
return $settings->value;
|
||||
}
|
||||
|
||||
private function encrypt($value) {
|
||||
$id = BaseService::getInstance()->getInstanceId();
|
||||
$key = $this->getInstanceKey();
|
||||
return AesCtr::encrypt($value, $id.$key, 256);
|
||||
}
|
||||
|
||||
public function encryptSetting($name, $value) {
|
||||
// check the existence of prefix and encrypt only if need to avoid double encryption
|
||||
if (
|
||||
$this->isEncryptedSetting($name)
|
||||
&& substr($value, 0, strlen(self::ENCRYPTED_PREFIX)) !== self::ENCRYPTED_PREFIX
|
||||
) {
|
||||
$value = self::ENCRYPTED_PREFIX.$this->encrypt($value);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
private function decrypt($value) {
|
||||
$id = BaseService::getInstance()->getInstanceId();
|
||||
$key = $this->getInstanceKey();
|
||||
return AesCtr::decrypt($value, $id.$key, 256);
|
||||
}
|
||||
|
||||
public function decryptSetting($name, $value) {
|
||||
if (
|
||||
$this->isEncryptedSetting($name)
|
||||
&& substr($value, 0, strlen(self::ENCRYPTED_PREFIX)) === self::ENCRYPTED_PREFIX
|
||||
) {
|
||||
$value = $this->decrypt(substr($value, strlen(self::ENCRYPTED_PREFIX)));
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function getSetting($name)
|
||||
{
|
||||
|
||||
if (class_exists("\\Classes\\ProVersion")) {
|
||||
$pro = new ProVersion();
|
||||
$val = $pro->getSetting($name);
|
||||
@@ -34,20 +94,28 @@ class SettingsManager
|
||||
|
||||
$setting = new Setting();
|
||||
$setting->Load("name = ?", array($name));
|
||||
$value = null;
|
||||
if ($setting->name == $name) {
|
||||
return $setting->value;
|
||||
$value = $setting->value;
|
||||
}
|
||||
return null;
|
||||
|
||||
if (null === $value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->decryptSetting($name, $value);
|
||||
}
|
||||
|
||||
public function setSetting($name, $value)
|
||||
{
|
||||
$setting = new Setting();
|
||||
$setting->Load("name = ?", array($name));
|
||||
if ($setting->name == $name) {
|
||||
$setting->value = $value;
|
||||
$setting->Save();
|
||||
if ($setting->name !== $name) {
|
||||
return;
|
||||
}
|
||||
|
||||
$setting->value = $this->encryptSetting($name, $value);
|
||||
$setting->Save();
|
||||
}
|
||||
|
||||
public function addSetting($name, $value)
|
||||
@@ -55,14 +123,21 @@ class SettingsManager
|
||||
$setting = new Setting();
|
||||
$setting->Load("name = ?", array($name));
|
||||
if ($setting->name == $name) {
|
||||
$setting->value = $value;
|
||||
$setting->value = $this->encryptSetting($name, $value);
|
||||
$setting->Save();
|
||||
} else {
|
||||
$setting->name = $name;
|
||||
$setting->value = $value;
|
||||
$setting->description = $value;
|
||||
$setting->value = $this->encryptSetting($name, $value);
|
||||
$setting->description = '';
|
||||
$setting->meta = '';
|
||||
$setting->Save();
|
||||
}
|
||||
}
|
||||
|
||||
public function getDeprecatedSettings() {
|
||||
return [
|
||||
'Attendance: Work Week Start Day',
|
||||
'Attendance: Overtime Calculation Class'
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user