Proyectos de Subversion LeadersLinked - Antes de SPA

Rev

Rev 4808 | Rev 5951 | Ir a la última revisión | | Comparar con el anterior | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 www 1
<?php
2
declare(strict_types=1);
3
 
4
namespace LeadersLinked;
5
 
6
use Laminas\Db\Adapter\AdapterInterface;
7
use Laminas\Cache\Storage\Adapter\AbstractAdapter as CacheAdapter;
8
use Laminas\ModuleManager\ModuleEvent;
9
use Laminas\ModuleManager\ModuleManager;
10
use Laminas\Mvc\MvcEvent;
11
use Laminas\Config\Reader\Ini;
12
use Laminas\Permissions\Acl\Acl;
13
use Laminas\Permissions\Acl\Role\GenericRole;
14
use LeadersLinked\Plugin\CurrentUserPlugin;
15
use LeadersLinked\Model\Company;
16
use LeadersLinked\Mapper\UserMapper;
17
use LeadersLinked\Authentication\AuthTokenAdapter;
18
use Laminas\Authentication\AuthenticationService;
19
use Laminas\Permissions\Acl\Resource\GenericResource;
20
use LeadersLinked\Model\UserType;
3639 efrain 21
use LeadersLinked\Plugin\CurrentNetworkPlugin;
22
use LeadersLinked\Model\Network;
23
use LeadersLinked\Model\User;
24
use LeadersLinked\Mapper\CompanyUserMapper;
25
use LeadersLinked\Model\CompanyUser;
26
use LeadersLinked\Mapper\CompanyMapper;
5205 efrain 27
use LeadersLinked\Mapper\CompanyServiceMapper;
28
use LeadersLinked\Model\Service;
1 www 29
 
30
class Module
31
{
32
 
33
    /**
34
     *
35
     * @var boolean
36
     */
37
    private $isJson;
38
 
39
    /**
40
     *
41
     * @var boolean
42
     */
43
    private $isHtml;
44
 
45
    /**
46
     *
47
     * @var Acl
48
     */
49
    private $acl;
50
 
3639 efrain 51
 
1 www 52
 
53
    /**
54
     *
55
     * @var AdapterInterface
56
     */
57
    private $adapter;
58
 
59
 
60
    /**
61
     *
62
     * @var CacheAdapter
63
     */
64
    private $cache;
65
 
66
    /**
67
     *
68
     * @var CurrentUserPlugin
69
     */
3639 efrain 70
    private $currentUserPlugin;
1 www 71
 
72
 
73
    /**
3639 efrain 74
     *
75
     * @var CurrentNetworkPlugin
76
     */
77
    private $currentNetworkPlugin;
78
 
79
 
80
    /**
1 www 81
     *
82
     * @var array
83
     */
84
    private $routesAuthorized = [];
85
 
86
    /**
87
     *
88
     * @var boolean
89
     */
90
    private $authByHeaders = false;
91
 
92
    public function init(ModuleManager $moduleManager)
93
    {
94
        $events = $moduleManager->getEventManager();
95
        $events->attach(ModuleEvent::EVENT_MERGE_CONFIG, array($this, 'onMergeConfig'));
96
    }
97
 
98
    public function onMergeConfig(ModuleEvent $event)
99
    {
100
        $configListener = $event->getConfigListener();
101
        $config         = $configListener->getMergedConfig(false);
102
 
103
        $reader = new Ini();
104
        $data = $reader->fromFile('config/leaderslinked.ini');
105
 
106
        $prefix = 'leaderslinked';
107
        foreach($data as $section => $pairs)
108
        {
109
            foreach($pairs as $key => $value)
110
            {
111
                $config[$prefix . '.' . $section . '.' . $key] = $value;
112
            }
113
        }
114
        $configListener->setMergedConfig($config);
115
    }
116
 
117
 
118
    public function getConfig() : array
119
    {
120
        return include __DIR__ . '/../config/module.config.php';
121
    }
122
 
123
    public function onBootstrap(MvcEvent $event)
124
    {
125
        $serviceManager = $event->getApplication()->getServiceManager();
126
        $adapter = $serviceManager->get('leaders-linked-db');
127
       // $logger          = $serviceManager->get('Zend\Log\Logger');
128
 
129
 
130
        $session = $serviceManager->get('leaders-linked-session');
131
        $session->start();
132
 
133
 
134
        $translator = $serviceManager->get('MvcTranslator');
135
        $translator->addTranslationFile(
136
            'phpArray',
137
            __DIR__ . '/i18n/validate.php',
138
            'default'
139
            );
140
 
141
        $translator->addTranslationFile(
142
            'phpArray',
143
            __DIR__ . '/i18n/spanish.php',
144
            'default'
145
            );
146
 
147
        \Laminas\Validator\AbstractValidator::setDefaultTranslator($translator);
148
 
149
 
150
        $headers  = $event->getRequest()->getHeaders();
151
        if($headers->has('Accept')) {
152
            $accept = $headers->get('Accept');
153
            $prioritized = $accept->getPrioritized();
154
 
155
            foreach($prioritized as $key => $value) {
156
                $raw = trim($value->getRaw());
157
 
158
                if(!$this->isJson) {
159
                    $this->isJson = strpos($raw, 'json');
160
                }
161
 
162
            }
163
        } else {
164
            $accept = '';
165
        }
166
        if($headers->has('token')) {
167
            $device_uuid = filter_var($headers->get('token')->getFieldValue(), FILTER_SANITIZE_STRING);
168
        } else {
169
            $device_uuid = '';
170
        }
171
        if($headers->has('secret')) {
172
            $password = filter_var($headers->get('secret')->getFieldValue(), FILTER_SANITIZE_STRING);
173
        } else {
174
            $password = '';
175
        }
176
        if($headers->has('rand')) {
177
            $rand = filter_var($headers->get('rand')->getFieldValue(), FILTER_SANITIZE_NUMBER_INT);
178
        } else {
179
            $rand = 0;
180
        }
181
        if($headers->has('created')) {
182
            $timestamp = filter_var($headers->get('created')->getFieldValue(), FILTER_SANITIZE_STRING);
183
        } else {
184
            $timestamp = 0;
185
        }
186
 
187
 
3639 efrain 188
 
189
 
190
        $this->currentNetworkPlugin = new CurrentNetworkPlugin($adapter);
191
        if(!$this->currentNetworkPlugin->hasNetwork()) {
3790 efrain 192
            $this->isJson = true;
193
            $response = $event->getResponse();
194
            $this->sendResponse($response, ['success' => false, 'data' => '401 Unauthorized - Private network - not found', 'fatal' => true]);
3639 efrain 195
        }
196
 
197
        if($this->currentNetworkPlugin->getNetwork()->status == Network::STATUS_INACTIVE) {
3790 efrain 198
            $this->isJson = true;
199
            $response = $event->getResponse();
200
            $this->sendResponse($response, ['success' => false, 'data' => '401 Unauthorized - Private network - inactive', 'fatal' => true]);
201
 
3639 efrain 202
        }
203
 
204
 
1 www 205
        $this->authByHeaders = false;
206
        if($device_uuid && $password && $rand && $timestamp) {
207
            $this->authByHeaders = true;
208
 
209
 
210
            $this->isJson = true;
211
 
212
            $tokenAuthAdapter = new AuthTokenAdapter($adapter);
213
            $tokenAuthAdapter->setData($device_uuid, $password, $timestamp, $rand);
214
 
215
            $authService = new AuthenticationService();
216
            $result = $authService->authenticate($tokenAuthAdapter);
217
            if($result->getCode() != \Laminas\Authentication\Result::SUCCESS) {
218
                $response = $event->getResponse();
219
 
220
                $this->sendResponse($response, ['success' => false, 'data' => $result->getMessages()[0], 'fatal' => true]);
221
            }
210 efrain 222
 
223
 
224
 
225
 
226
 
1 www 227
        }
3639 efrain 228
 
1 www 229
 
3639 efrain 230
 
231
        if(empty($_SERVER['REDIRECT_URL'])) {
232
            if(empty($_SERVER['REQUEST_URI'])) {
233
                $routeName = '';
234
 
235
            } else {
236
                $routeName = $_SERVER['REQUEST_URI'];
237
            }
238
 
239
        } else {
240
            $routeName = $_SERVER['REDIRECT_URL'];
241
 
242
        }
243
 
210 efrain 244
 
3639 efrain 245
        $routeName = strtolower(trim($routeName));
246
        if(strlen($routeName) > 0 && substr($routeName, 0, 1) == '/') {
247
            $routeName = substr($routeName, 1);
248
        }
1 www 249
 
3639 efrain 250
        $this->isHtml = $this->isJson ? false : true;
251
        $this->currentUserPlugin = new CurrentUserPlugin($adapter);
1 www 252
 
210 efrain 253
 
3639 efrain 254
        if($this->authByHeaders && substr($routeName, 0, 8) == 'services') {
255
            $checkUserForNetwork = false;
256
        } else {
257
            if($this->currentUserPlugin->hasIdentity()) {
258
 
259
                $checkUserForNetwork = true;
260
            } else {
261
                $checkUserForNetwork = false;
262
            }
263
        }
264
 
265
        if($checkUserForNetwork) {
266
            if(!$routeName || in_array($routeName, ['signout', 'signin', 'home'])) {
267
                $checkUserForNetwork = false;
268
            }
269
        }
270
 
271
        if($checkUserForNetwork) {
272
 
273
 
274
 
275
            if($this->currentUserPlugin->getUser()->network_id != $this->currentNetworkPlugin->getNetworkId()) {
3790 efrain 276
 
277
                $this->isJson = true;
278
                $response = $event->getResponse();
279
                $this->sendResponse($response, ['success' => false, 'data' => '401 Unauthorized - The user is not part of this private network', 'fatal' => true]);
280
 
3639 efrain 281
            }
282
        }
283
 
284
 
285
 
1 www 286
        $this->initAcl($event);
287
        $eventManager = $event->getApplication()->getEventManager();
288
        $eventManager->attach(MvcEvent::EVENT_DISPATCH_ERROR, [$this,'onDispatchError'], 0);
289
        $eventManager->attach(MvcEvent::EVENT_RENDER_ERROR, [$this,'onRenderError'], 0);
290
 
291
        $sharedManager = $eventManager->getSharedManager();
292
        $sharedManager->attach(__NAMESPACE__, MvcEvent::EVENT_DISPATCH, [$this, 'authPreDispatch'], 100);
293
        $sharedManager->attach(__NAMESPACE__, MvcEvent::EVENT_DISPATCH, [$this, 'authPosDispatch'], -100);
294
    }
295
 
296
    public function initAcl(MvcEvent $event)
297
    {
298
 
3639 efrain 299
        $serviceManager = $event->getApplication()->getServiceManager();
300
        $adapter = $serviceManager->get('leaders-linked-db');
301
 
302
 
1 www 303
        require_once   (dirname(__DIR__) . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'acl.config.php');
304
 
305
 
306
        $this->acl = new Acl();
307
        $resources = getAclResources();
1979 efrain 308
 
1 www 309
        foreach($resources as $resourceName)
310
        {
311
            $this->acl->addResource(new GenericResource($resourceName));
312
        }
313
 
314
        $usertypes = getAclUsertype();
315
        foreach($usertypes as $usertype => $resources)
316
        {
317
            $this->acl->addRole(new GenericRole($usertype));
318
            foreach ($resources as $resourceName)
319
            {
320
                $this->acl->allow($usertype, $resourceName);
321
            }
322
        }
5205 efrain 323
 
1 www 324
 
3639 efrain 325
 
326
        if($this->currentUserPlugin->hasIdentity() && $this->currentUserPlugin->getUser()->is_super_user == User::IS_SUPER_USER_YES) {
327
 
328
            $resources =  getAclSuperAdmin();
329
            foreach($resources as $resourceName)
330
            {
331
                $this->acl->allow(UserType::ADMIN, $resourceName);
332
            }
333
        }
334
 
335
 
5205 efrain 336
        $allowDailyPulse = false;
337
 
338
        $companyMapper = CompanyMapper::getInstance($adapter);
339
        $company = $companyMapper->fetchDefaultForNetworkByNetworkId($this->currentNetworkPlugin->getNetwork()->id);
340
        if($company) {
341
            $companyUserMapper = CompanyUserMapper::getInstance($adapter);
342
            $companyUser = $companyUserMapper->fetchOneAcceptedByCompanyIdAndUserId($company->id,  $this->currentUserPlugin->getUserId());
343
 
344
 
345
            $companyServiceMapper = CompanyServiceMapper::getInstance($adapter);
346
            $companyService = $companyServiceMapper->fetchOneActiveByCompanyIdAndServiceId($company->id, Service::ENGAGEMENT_DAILY_PULSE);
347
 
348
 
349
            if($companyService && $companyUser) {
350
                $allowDailyPulse = true;
351
            }
352
        } else {
353
            $companyUser = '';
354
        }
355
 
356
        if($allowDailyPulse) {
357
            $usertype = $this->currentUserPlugin->getUserTypeId();
358
 
359
            $resources = getAclDailyPulse();
360
            foreach($resources as $resourceName)
361
            {
362
                $this->acl->allow($usertype, $resourceName);
363
            }
364
        }
365
 
366
 
3639 efrain 367
        if($this->currentNetworkPlugin->getNetwork()->default == Network::DEFAULT_YES) {
368
 
369
            $usertypes = getAclUsertypeDefaultNetwork();
370
            foreach($usertypes as $usertype => $resources)
371
            {
5205 efrain 372
 
3639 efrain 373
 
5205 efrain 374
 
3639 efrain 375
                foreach ($resources as $resourceName)
376
                {
377
                    $this->acl->allow($usertype, $resourceName);
378
                }
379
            }
380
 
381
 
382
        } else {
3647 efrain 383
 
3645 efrain 384
            if($this->currentUserPlugin->hasIdentity()) {
3639 efrain 385
 
5205 efrain 386
 
3645 efrain 387
                if($company) {
3639 efrain 388
 
5205 efrain 389
 
3645 efrain 390
                    if($companyUser) {
391
                        $usertype = $this->currentUserPlugin->getUserTypeId();
3639 efrain 392
 
3645 efrain 393
                        if($companyUser->creator == CompanyUser::CREATOR_YES) {
394
 
395
                            $resources =  getAclUsertypeOtherNetworkCreator();
396
                            foreach($resources as $resourceName)
397
                            {
398
                                $this->acl->allow($usertype, $resourceName);
399
                            }
400
 
3639 efrain 401
                        }
3645 efrain 402
                        if($companyUser->creator == CompanyUser::CREATOR_NO) {
403
                            $resources =  getAclUsertypeOtherNetworkNonCreator();
404
                            foreach($resources as $resourceName)
405
                            {
406
                                $this->acl->allow($usertype, $resourceName);
407
                            }
3639 efrain 408
                        }
409
                    }
410
                }
3647 efrain 411
            }
3639 efrain 412
        }
413
 
414
 
1 www 415
        $event->getViewModel()->setVariable('acl', $this->acl);
416
 
417
    }
418
 
419
    public function onDispatchError(MvcEvent $event)
420
    {
421
        $this->processError($event);
422
    }
423
 
424
    public function onRenderError(MvcEvent $event)
425
    {
426
        $this->processError($event);
427
    }
428
 
429
    public function sendResponse(\Laminas\Http\Response $response, $data)
430
    {
431
 
432
 
433
        if($this->isJson) {
434
            $headers = $response->getHeaders();
435
            $headers->clearHeaders();
436
            $headers->addHeaderLine('Content-type', 'application/json; charset=UTF-8');
437
 
438
            $response->setStatusCode(200);
439
            $response->setContent(json_encode($data));
440
            $response->send();
441
 
442
        } else {
443
            throw new \Exception($data['data']);
444
        }
445
        exit;
446
    }
447
 
448
    public function processError(MvcEvent $event)
449
    {
450
 
451
        $request =  $event->getRequest();
452
        if((method_exists($request, 'isXmlHttpRequest') && $request->isXmlHttpRequest()) || ($this->isJson && !$this->isHtml)) {
453
 
454
            $error = $event->getError();
455
            if (!$error) {
456
                return;
457
            }
458
 
459
            $response = $event->getResponse();
460
 
461
            if('error-exception' == $error) {
462
                $exception = $event->getParam('exception');
463
                error_log($exception->getCode() . ' ' . $exception->getMessage());
464
                error_log($exception->getTraceAsString());
465
 
466
 
467
                $data = [
468
                    'success' => false,
469
                    'data' => 'An error occurred during execution; please try again later.'
470
                ];
471
 
472
            } else if('error-router-no-match' == $error) {
473
                $data = [
474
                    'success' => false,
475
                    'data' => 'Resource not found.'
476
 
477
                ];
478
            } else if(' error-controller-not-found' == $error) {
479
                $data = [
480
                    'success' => false,
481
                    'data' => 'Controller not found.'
482
 
483
                ];
484
            } else {
485
                $data = [
486
                    'success' => false,
487
                    'data' => 'Unknow error.' , 'error' => $error
488
 
489
                ];
490
            }
491
 
492
            $this->sendResponse($response, $data);
493
        }
494
 
495
        $this->initAcl($event);
496
    }
497
 
498
 
499
    public function authPreDispatch(MvcEvent $event)
500
    {
210 efrain 501
 
502
 
503
 
504
 
1 www 505
        $serviceManager = $event->getApplication()->getServiceManager();
506
        $adapter = $serviceManager->get('leaders-linked-db');
507
 
210 efrain 508
        $routeName = $event->getRouteMatch()->getMatchedRouteName();
509
 
1 www 510
 
210 efrain 511
        $requestMethod = isset($_SERVER['REQUEST_METHOD']) ? trim(strtoupper($_SERVER['REQUEST_METHOD'])) : '';
512
 
513
        if($requestMethod == 'POST' || $requestMethod == 'PUT' || $requestMethod == 'DELETE') {
514
 
1979 efrain 515
 
1323 efrain 516
            if($this->authByHeaders && substr($routeName, 0, 8) == 'services') {
517
                $exclude = true;
518
            } else {
519
                $exclude = false;
520
 
521
                $usertypes = getAclUsertype();
522
 
523
 
524
                foreach($usertypes[UserType::GUEST] as $resourceName)
525
                {
526
                   if($routeName == $resourceName) {
527
                      $exclude = true;
528
                      break;
529
                    }
210 efrain 530
                }
531
            }
4131 efrain 532
 
4808 efrain 533
            $exclude = true;
1979 efrain 534
 
210 efrain 535
            if(!$exclude) {
536
                $httpToken = isset($_SERVER['HTTP_X_CSRF_TOKEN']) ? $_SERVER['HTTP_X_CSRF_TOKEN'] : '';
537
                $sessionToken = isset($_SESSION['token']) ? $_SESSION['token'] : uniqid();
538
 
539
                unset($_SESSION['token']);
540
                if ( $httpToken != $sessionToken) {
541
                    header("HTTP/1.1 401 Unauthorized");
542
                    exit;
543
                }
544
 
545
            }
546
        }
547
 
548
 
549
 
3639 efrain 550
        if($this->currentUserPlugin->hasIdentity())  {
551
            $user = $this->currentUserPlugin->getUser();
1 www 552
            $userTypeId = $user->usertype_id;
553
 
554
 
555
        }  else {
556
 
557
            $userTypeId = UserType::GUEST;
558
        }
559
 
210 efrain 560
 
1 www 561
        if($this->acl->isAllowed($userTypeId, $routeName)) {
3639 efrain 562
            $user = $this->currentUserPlugin->getUser();
210 efrain 563
 
1 www 564
 
565
            if($user) {
3086 efrain 566
 
567
                $updateLastActivity = true;
568
                if ('chat' == substr($routeName, 0, 4)) {
569
                    $updateLastActivity = false;
570
                }
571
                if ('inmail' == substr($routeName, 0, 6)) {
572
                    $updateLastActivity = false;
573
                }
574
                if ('check-session' == $routeName) {
575
                    $updateLastActivity = false;
576
                }
577
 
578
 
579
                if($updateLastActivity) {
580
                    $userMapper = UserMapper::getInstance($adapter);
581
                    $userMapper->updateLastActivity($user->id);
582
                }
1 www 583
            }
584
 
585
        } else {
210 efrain 586
 
1 www 587
            if($this->authByHeaders) {
588
                $response = $event->getResponse();
589
                $headers = $response->getHeaders();
590
                $headers->clearHeaders();
591
                $headers->addHeaderLine('Content-type', 'application/json; charset=UTF-8');
592
 
593
                $response->setStatusCode(401);
594
                $response->setContent(json_encode(['success' => false, 'data' => 'Unauthorized.', 'fatal' => true]));
595
                $response->send();
596
                exit;
597
 
210 efrain 598
            }
1 www 599
 
600
 
601
            //print_r($this->routesAuthorized);
602
           // echo 'sin permiso'; exit;
603
 
604
 
3639 efrain 605
            $this->currentUserPlugin->clearIdentity();
1 www 606
 
607
 
608
            if($this->isJson) {
609
                $response = $event->getResponse();
610
                $headers = $response->getHeaders();
611
                $headers->clearHeaders();
612
                $headers->addHeaderLine('Content-type', 'application/json; charset=UTF-8');
613
 
614
                $response->setStatusCode(200);
615
                $response->setContent(json_encode(['success' => false, 'data' => 'Unauthorized.', 'fatal' => true]));
616
                $response->send();
617
            } else {
618
                $url = $event->getRouter()->assemble([], ['name' => 'signout']);
619
 
620
                $response = $event->getResponse();
621
                $headers = $response->getHeaders();
622
                $headers->clearHeaders();
623
                $headers->addHeaderLine('Location', $url);
624
 
625
                $response->setStatusCode(302);
626
                $response->send();
627
            }
628
            exit;
629
        }
630
 
631
 
632
    }
633
 
634
 
635
    public function authPosDispatch(MvcEvent $event)
636
    {
637
 
638
    }
639
 
640
 
641
}