Rev 105 | Rev 164 | Ir a la última revisión | Autoría | Comparar con el anterior | Ultima modificación | Ver Log |
<?phpdeclare(strict_types=1);namespace LeadersLinked;use Laminas\Db\Adapter\AdapterInterface;use Laminas\ModuleManager\ModuleEvent;use Laminas\ModuleManager\ModuleManager;use Laminas\Mvc\MvcEvent;use Laminas\Config\Reader\Ini;use Laminas\Permissions\Acl\Acl;use Laminas\Permissions\Acl\Role\GenericRole;use LeadersLinked\Plugin\CurrentUserPlugin;use LeadersLinked\Mapper\UserMapper;use LeadersLinked\Authentication\AuthTokenAdapter;use Laminas\Authentication\AuthenticationService;use Laminas\Permissions\Acl\Resource\GenericResource;use LeadersLinked\Model\UserType;use LeadersLinked\Plugin\CurrentNetworkPlugin;use LeadersLinked\Model\Network;use LeadersLinked\Model\User;use LeadersLinked\Mapper\CompanyUserMapper;use LeadersLinked\Model\CompanyUser;use LeadersLinked\Mapper\CompanyMapper;use LeadersLinked\Mapper\CompanyServiceMapper;use LeadersLinked\Model\Service;use LeadersLinked\Library\Functions;use LeadersLinked\Mapper\DailyPulseMapper;use LeadersLinked\Model\DailyPulse;use LeadersLinked\Mapper\OrganizationPositionMapper;use LeadersLinked\Mapper\KnowledgeAreaCategoryJobDescriptionMapper;use LeadersLinked\Mapper\MyCoachCategoryJobDescriptionMapper;use LeadersLinked\Mapper\KnowledgeAreaCategoryUserMapper;use LeadersLinked\Mapper\MyCoachCategoryUserMapper;use Firebase\JWT\JWT;use Firebase\JWT\Key;use LeadersLinked\Mapper\JwtTokenMapper;use LeadersLinked\Authentication\AuthUserIdAdapter;use LeadersLinked\Model\JwtToken;class Module{/**** @var Acl*/private $acl;/**** @var AdapterInterface*/private $adapter;/**** @var CurrentUserPlugin*/private $currentUserPlugin;/**** @var CurrentNetworkPlugin*/private $currentNetworkPlugin;/**** @var array*/private $routesAuthorized = [];/**** @var boolean*/private $authByOTP = false;/**** @var boolean*/private $authByJWT = false;/**** @var int*/private $jwtID = 0;/**** @var JwtToken*/private $jwtToken;/**** @var array*/private $config;public function init(ModuleManager $moduleManager){$events = $moduleManager->getEventManager();$events->attach(ModuleEvent::EVENT_MERGE_CONFIG, array($this, 'onMergeConfig'));}public function onMergeConfig(ModuleEvent $event){$configListener = $event->getConfigListener();$this->config = $configListener->getMergedConfig(false);$reader = new Ini();$data = $reader->fromFile('config/leaderslinked.ini');$prefix = 'leaderslinked';foreach($data as $section => $pairs){foreach($pairs as $key => $value){$this->config[$prefix . '.' . $section . '.' . $key] = $value;}}$configListener->setMergedConfig($this->config);}public function getConfig() : array{return include __DIR__ . '/../config/module.config.php';}public function onBootstrap(MvcEvent $event){$response = $event->getResponse();Functions::addCrossSiteToResponse($response);$event->setResponse($response);$serviceManager = $event->getApplication()->getServiceManager();$eventManager = $event->getApplication()->getEventManager();$eventManager->attach(MvcEvent::EVENT_DISPATCH_ERROR, [$this,'onDispatchError'], 0);$eventManager->attach(MvcEvent::EVENT_RENDER_ERROR, [$this,'onRenderError'], 0);$adapter = $serviceManager->get('leaders-linked-db');$session = $serviceManager->get('leaders-linked-session');$session->start();$translator = $serviceManager->get('MvcTranslator');$translator->addTranslationFile('phpArray',__DIR__ . '/i18n/validate.php','default');$translator->addTranslationFile('phpArray',__DIR__ . '/i18n/spanish.php','default');\Laminas\Validator\AbstractValidator::setDefaultTranslator($translator);$headers = $event->getRequest()->getHeaders();if($headers->has('token')) {$device_uuid = Functions::sanitizeFilterString($headers->get('token')->getFieldValue());} else {$device_uuid = '';}if($headers->has('secret')) {$password = Functions::sanitizeFilterString($headers->get('secret')->getFieldValue());} else {$password = '';}if($headers->has('rand')) {$rand = Functions::sanitizeFilterString($headers->get('rand')->getFieldValue());} else {$rand = 0;}if($headers->has('created')) {$timestamp = Functions::sanitizeFilterString($headers->get('created')->getFieldValue());} else {$timestamp = 0;}$this->currentNetworkPlugin = new CurrentNetworkPlugin($adapter);if(!$this->currentNetworkPlugin->hasNetwork()) {$response = $event->getResponse();$code = 200;$content = json_encode(['success' => false, 'data' => '200 Unauthorized - Private network - not found', 'fatal' => true]);$this->sendResponse($response, $code, $content);}if($this->currentNetworkPlugin->getNetwork()->status == Network::STATUS_INACTIVE) {$response = $event->getResponse();$code = 200;$content = json_encode(['success' => false, 'data' => '200 Unauthorized - Private network - inactive', 'fatal' => true]);$this->sendResponse($response, $code, $content);}$this->authByOTP = false;if($device_uuid && $password && $rand && $timestamp) {$this->authByOTP = true;$tokenAuthAdapter = new AuthTokenAdapter($adapter);$tokenAuthAdapter->setData($device_uuid, $password, $timestamp, $rand);$authService = new AuthenticationService();$result = $authService->authenticate($tokenAuthAdapter);if($result->getCode() != \Laminas\Authentication\Result::SUCCESS) {$response = $event->getResponse();$code = 200;$content = json_encode(['success' => false, 'data' => $result->getMessages()[0], 'fatal' => true]);$this->sendResponse($response, $code, $content);}}$this->jwtID = 0;$this->authByJWT = false;$headers = getallheaders();if(!empty($headers['authorization']) || !empty($headers['Authorization'])) {$token = trim(empty($headers['authorization']) ? $headers['Authorization'] : $headers['authorization']);if (substr($token, 0, 6 ) == 'Bearer') {$token = trim(substr($token, 7));if(!empty($this->config['leaderslinked.jwt.key'])) {$key = $this->config['leaderslinked.jwt.key'];try {$payload = JWT::decode($token, new Key($key, 'HS256'));if(empty($payload->iss) || $payload->iss != $_SERVER['HTTP_HOST']) {$response = $event->getResponse();$code = 200;$content = json_encode(['success' => false, 'data' => 'Unauthorized - JWT - Wrong server', 'fatal' => true]);$this->sendResponse($response, $code, $content);}$uuid = empty($payload->uuid) ? '' : $payload->uuid;if($uuid) {$jwtTokenMapper = JwtTokenMapper::getInstance($adapter);$jwtToken = $jwtTokenMapper->fetchOneByUuid($uuid);if($jwtToken) {$this->jwtID = $jwtToken->id;$_SESSION['aes'] = $jwtToken->aes;if($jwtToken->user_id) {$authByUserId = new AuthUserIdAdapter($adapter);$authByUserId->setData($jwtToken->user_id);$authService = new AuthenticationService();$result = $authService->authenticate($authByUserId);if($result->getCode() != \Laminas\Authentication\Result::SUCCESS) {$response = $event->getResponse();$code = 200;$content = json_encode(['success' => false, 'data' => $result->getMessages()[0], 'fatal' => true]);$this->sendResponse($response, $code, $content);}}} else {$response = $event->getResponse();$code = 200;$content = json_encode(['success' => false, 'data' => 'Unauthorized - JWT - Expired', 'fatal' => true]);$this->sendResponse($response, $code, $content);}}} catch(\Exception $e) {$response = $event->getResponse();$code = 200;$content = json_encode(['success' => false, 'data' => 'Unauthorized - JWT - Wrong key', 'fatal' => true]);$this->sendResponse($response, $code, $content);}}}}if(empty($_SERVER['REDIRECT_URL'])) {if(empty($_SERVER['REQUEST_URI'])) {$routeName = '';} else {$routeName = $_SERVER['REQUEST_URI'];}} else {$routeName = $_SERVER['REDIRECT_URL'];}$routeName = strtolower(trim($routeName));if(strlen($routeName) > 0 && substr($routeName, 0, 1) == '/') {$routeName = substr($routeName, 1);}$this->currentUserPlugin = new CurrentUserPlugin($adapter);if($this->authByOTP && substr($routeName, 0, 8) == 'services') {$checkUserForNetwork = false;} else {if($this->currentUserPlugin->hasIdentity()) {$checkUserForNetwork = true;} else {$checkUserForNetwork = false;}}if($checkUserForNetwork) {if(!$routeName || in_array($routeName, ['signout', 'signin', 'home'])) {$checkUserForNetwork = false;}}if($checkUserForNetwork) {if($this->currentUserPlugin->getUser()->network_id != $this->currentNetworkPlugin->getNetworkId()) {$response = $event->getResponse();$this->sendResponse($response, ['success' => false, 'data' => '200 Unauthorized - The user is not part of this private network', 'fatal' => true]);exit;}}$this->initAcl($event);$sharedManager = $eventManager->getSharedManager();$sharedManager->attach(__NAMESPACE__, MvcEvent::EVENT_DISPATCH, [$this, 'authPreDispatch'], 100);$sharedManager->attach(__NAMESPACE__, MvcEvent::EVENT_DISPATCH, [$this, 'authPosDispatch'], -100);}public function initAcl(MvcEvent $event){$serviceManager = $event->getApplication()->getServiceManager();$adapter = $serviceManager->get('leaders-linked-db');require_once (dirname(__DIR__) . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'acl.config.php');$this->acl = new Acl();$resources = getAclResources();foreach($resources as $resourceName){$this->acl->addResource(new GenericResource($resourceName));}$usertypes = getAclUsertype();foreach($usertypes as $usertype => $resources){$this->acl->addRole(new GenericRole($usertype));foreach ($resources as $resourceName){$this->acl->allow($usertype, $resourceName);}}if($this->currentUserPlugin->hasIdentity() && $this->currentUserPlugin->getUser()->is_super_user == User::IS_SUPER_USER_YES) {$resources = getAclSuperAdmin();foreach($resources as $resourceName){$this->acl->allow(UserType::ADMIN, $resourceName);}}$allowMyCoach = false;$allowKnowledgeArea = false;$allowDailyPulse = false;$companyMapper = CompanyMapper::getInstance($adapter);$company = $companyMapper->fetchDefaultForNetworkByNetworkId($this->currentNetworkPlugin->getNetwork()->id);if($company) {$companyServiceMapper = CompanyServiceMapper::getInstance($adapter);$companyService = $companyServiceMapper->fetchOneActiveByCompanyIdAndServiceId($company->id, Service::DAILY_PULSE);$companyUserMapper = CompanyUserMapper::getInstance($adapter);$companyUser = $companyUserMapper->fetchOneAcceptedByCompanyIdAndUserId($company->id, $this->currentUserPlugin->getUserId());if($companyService) {$dailyPulseMapper = DailyPulseMapper::getInstance($adapter);$dailyPulse = $dailyPulseMapper->fetchOneByCompanyId($company->id);if($dailyPulse) {$privacy = $dailyPulse->privacy;} else {$privacy = DailyPulse::PRIVACY_COMPANY;}if($privacy == DailyPulse::PRIVACY_PUBLIC) {$allowDailyPulse = true;} else {$allowDailyPulse = !empty($companyUser);}}$job_description_ids = [];$organizationPositionMapper = OrganizationPositionMapper::getInstance($adapter);$records = $organizationPositionMapper->fetchAllByCompanyIdAndEmployeeId($company->id, $this->currentUserPlugin->getUserId());foreach($records as $record){array_push($job_description_ids, $record->job_description_id);}$companyService = $companyServiceMapper->fetchOneActiveByCompanyIdAndServiceId($company->id, Service::KNOWLEDGE_AREA);if($companyService) {if($job_description_ids) {$knowledgeAreaCategoryJobDescriptionMapper = KnowledgeAreaCategoryJobDescriptionMapper::getInstance($adapter);$records = $knowledgeAreaCategoryJobDescriptionMapper->fetchAllByCompanyIdAndJobDescriptionIds($company->id, $job_description_ids);if(!empty($records)) {$allowKnowledgeArea = true;}}if($companyUser && !$allowKnowledgeArea) {$knowledgeAreaCategoryUserMapper = KnowledgeAreaCategoryUserMapper::getInstance($adapter);$records = $knowledgeAreaCategoryUserMapper->fetchAllByUserId($companyUser->user_id);if(!empty($records)) {$allowKnowledgeArea = true;}}}$companyService = $companyServiceMapper->fetchOneActiveByCompanyIdAndServiceId($company->id, Service::MY_COACH);if($companyService) {if($job_description_ids) {$myCoachCategoryJobDescriptionMapper = MyCoachCategoryJobDescriptionMapper::getInstance($adapter);$records = $myCoachCategoryJobDescriptionMapper->fetchAllByCompanyIdAndJobDescriptionIds($company->id, $job_description_ids);if(!empty($records)) {$allowKnowledgeArea = true;}}if($companyUser && !$allowMyCoach) {$myCoachCategoryUserMapper = MyCoachCategoryUserMapper::getInstance($adapter);$records = $myCoachCategoryUserMapper->fetchAllByUserId($companyUser->user_id);if(!empty($records)) {$allowMyCoach = true;}}}} else {$companyUser = '';}$usertype = $this->currentUserPlugin->getUserTypeId();if($allowDailyPulse) {$resources = getAclDailyPulse();foreach($resources as $resourceName){$this->acl->allow($usertype, $resourceName);}}if($allowKnowledgeArea) {$resources = getAclKnowledgeArea();foreach($resources as $resourceName){$this->acl->allow($usertype, $resourceName);}}if($allowMyCoach) {$resources = getAclMyCoach();foreach($resources as $resourceName){$this->acl->allow($usertype, $resourceName);}}if($this->currentNetworkPlugin->getNetwork()->default == Network::DEFAULT_YES) {$usertypes = getAclUsertypeDefaultNetwork();foreach($usertypes as $usertype => $resources){foreach ($resources as $resourceName){$this->acl->allow($usertype, $resourceName);}}} else {if($this->currentUserPlugin->hasIdentity()) {if($company) {if($companyUser) {$usertype = $this->currentUserPlugin->getUserTypeId();if($companyUser->creator == CompanyUser::CREATOR_YES) {$resources = getAclUsertypeOtherNetworkCreator();foreach($resources as $resourceName){$this->acl->allow($usertype, $resourceName);}}if($companyUser->creator == CompanyUser::CREATOR_NO) {$resources = getAclUsertypeOtherNetworkNonCreator();foreach($resources as $resourceName){$this->acl->allow($usertype, $resourceName);}}}}}}$event->getViewModel()->setVariable('acl', $this->acl);}public function onDispatchError(MvcEvent $event){$this->processError($event);}public function onRenderError(MvcEvent $event){$this->processError($event);}/**** @param \Laminas\Http\Response $response* @param int $code* @param string $content*/public function sendResponse($response, $code, $content){$headers = $response->getHeaders();$headers->clearHeaders();$headers->addHeaderLine('Content-type', 'application/json; charset=UTF-8');Functions::addCrossSiteToResponse($response);$response->setStatusCode($code);$response->setContent($content); //json_encode($data));$response->send();exit;}public function processError(MvcEvent $event){$error = $event->getError();if (!$error) {return;}$response = $event->getResponse();if('error-exception' == $error) {$exception = $event->getParam('exception');error_log($exception->getCode() . ' ' . $exception->getMessage());error_log($exception->getTraceAsString());$response = $event->getResponse();$code = 200;$content = json_encode(['success' => false, 'data' => $exception->getCode() . ' ' . $exception->getMessage(), 'fatal' => true]);$this->sendResponse($response, $code, $content);} else if('error-router-no-match' == $error) {$response = $event->getResponse();$code = 404;$content = json_encode(['success' => false, 'data' => 'error-router-no-match', 'fatal' => true]);$this->sendResponse($response, $code, $content);} else if(' error-controller-not-found' == $error) {$response = $event->getResponse();$code = 404;$content = json_encode(['success' => false, 'data' => 'error-controller-not-found', 'fatal' => true]);$this->sendResponse($response, $code, $content);} else {$response = $event->getResponse();$code = 200;$content = json_encode(['success' => false, 'data' => $error, 'fatal' => true]);$this->sendResponse($response, $code, $content);}exit;}public function authPreDispatch(MvcEvent $event){$serviceManager = $event->getApplication()->getServiceManager();$adapter = $serviceManager->get('leaders-linked-db');$routeName = $event->getRouteMatch()->getMatchedRouteName();$requestMethod = isset($_SERVER['REQUEST_METHOD']) ? trim(strtoupper($_SERVER['REQUEST_METHOD'])) : '';if($requestMethod == 'POST') {if($this->authByOTP && substr($routeName, 0, 8) == 'services') {$exclude = true;} else {$exclude = false;$usertypes = getAclUsertype();foreach($usertypes[UserType::GUEST] as $resourceName){if($routeName == $resourceName) {$exclude = true;break;}}}if(!$exclude) {$httpToken = isset($_SERVER['HTTP_X_CSRF_TOKEN']) ? $_SERVER['HTTP_X_CSRF_TOKEN'] : '';if($this->jwtID) {$jwtTokenMapper = JwtTokenMapper::getInstance($this->adapter);$jwtToken = $jwtTokenMapper->fetchOne($this->jwtID);if($jwtToken) {$sessionToken = $jwtToken->csrf;//$jwtToken->csrf= '';// $jwtTokenMapper->update($jwtToken);} else {$sessionToken = '';}} else {$sessionToken = '';}//error_log('$this->jwtID = ' . $this->jwtID . ' $httpToken = ' . $httpToken . ' $sessionToken = ' . $sessionToken);if ( $httpToken != $sessionToken) {$response = $event->getResponse();$this->sendResponse($response, 200, json_encode(['success' => false, 'data' => 'Unauthorized - CSRF fail', 'fatal' => true]));}}}if($this->currentUserPlugin->hasIdentity()) {$user = $this->currentUserPlugin->getUser();$userTypeId = $user->usertype_id;} else {$userTypeId = UserType::GUEST;}if($this->acl->isAllowed($userTypeId, $routeName)) {$user = $this->currentUserPlugin->getUser();if($user) {$updateLastActivity = true;if ('chat' == substr($routeName, 0, 4)) {$updateLastActivity = false;}if ('inmail' == substr($routeName, 0, 6)) {$updateLastActivity = false;}if ('check-session' == $routeName) {$updateLastActivity = false;}if($updateLastActivity) {$userMapper = UserMapper::getInstance($adapter);$userMapper->updateLastActivity($user->id);}}} else {$response = $event->getResponse();$response->setStatusCode(200);$response->setContent(json_encode(['success' => false, 'data' => 'Unauthorized - Does not have permission', 'fatal' => true]));$response->send();exit;}}public function authPosDispatch(MvcEvent $event){//$response = $event->getResponse();// Functions::addCrossSiteToResponse($response);}}