Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
83.81% covered (warning)
83.81%
88 / 105
0.00% covered (danger)
0.00%
0 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
Index
83.81% covered (warning)
83.81%
88 / 105
0.00% covered (danger)
0.00%
0 / 3
20.53
0.00% covered (danger)
0.00%
0 / 1
 readResponse
95.00% covered (success)
95.00%
38 / 40
0.00% covered (danger)
0.00%
0 / 1
8
 testLogin
75.44% covered (warning)
75.44%
43 / 57
0.00% covered (danger)
0.00%
0 / 1
6.53
 getProviderList
87.50% covered (warning)
87.50%
7 / 8
0.00% covered (danger)
0.00%
0 / 1
5.05
1<?php
2
3/**
4 * @package Zmsstatistic
5 * @copyright BerlinOnline Stadtportal GmbH & Co. KG
6 **/
7
8namespace BO\Zmsstatistic;
9
10use BO\Zmsclient\ModuleAccess;
11use BO\Zmsentities\Workstation;
12
13class Index extends BaseController
14{
15    protected $withAccess = false;
16
17    /**
18     * @SuppressWarnings(Param)
19     * @return \Psr\Http\Message\ResponseInterface
20     */
21    #[\Override]
22    public function readResponse(
23        \Psr\Http\Message\RequestInterface $request,
24        \Psr\Http\Message\ResponseInterface $response,
25        array $args
26    ): \Psr\Http\Message\ResponseInterface {
27        try {
28            $workstation = \App::$http->readGetResult('/workstation/')->getEntity();
29        } catch (\Exception $workstationexception) {
30            $workstation = null;
31        }
32
33        $config = \App::$http->readGetResult('/config/', [], \App::CONFIG_SECURE_TOKEN)->getEntity();
34        $input = $request->getParsedBody();
35        $oidclogin = $request->getAttribute('validator')->getParameter('oidclogin')->isString()->getValue();
36        if ($request->getMethod() === 'POST') {
37            $loginData = $this->testLogin($input);
38            if ($loginData instanceof Workstation && $loginData->offsetExists('authkey')) {
39                \BO\Zmsclient\Auth::setKey($loginData->authkey);
40                return ModuleAccess::rejectWrongModuleAccess(ModuleAccess::MODULE_STATISTIC, $loginData, $response)
41                    ?? \BO\Slim\Render::redirect('workstationSelect', array(), array());
42            }
43
44            return \BO\Slim\Render::withHtml(
45                $response,
46                'page/index.twig',
47                array(
48                    'title' => 'Anmeldung gescheitert',
49                    'loginfailed' => true,
50                    'workstation' => null,
51                    'exception' => $loginData,
52                    'oidcproviderlist' => $this->getProviderList($config),
53                    'oidclogin' => $oidclogin,
54                    'showloginform' => (! $oidclogin)
55                )
56            );
57        } else {
58            if ($workstation instanceof Workstation && $workstation->hasId()) {
59                if ($wrongModuleResponse = ModuleAccess::rejectWrongModuleAccess(ModuleAccess::MODULE_STATISTIC, $workstation, $response)) {
60                    return $wrongModuleResponse;
61                }
62            }
63            return \BO\Slim\Render::withHtml(
64                $response,
65                'page/index.twig',
66                array(
67                    'title' => 'Anmeldung',
68                    'config' => $config,
69                    'workstation' => $workstation,
70                    'oidcproviderlist' => $this->getProviderList($config),
71                    'oidclogin' => $oidclogin,
72                    'showloginform' => (! $oidclogin)
73                )
74            );
75        }
76    }
77
78    #[\Override]
79    protected function testLogin($input)
80    {
81        $userAccount = new \BO\Zmsentities\Useraccount(array(
82            'id' => $input['loginName'],
83            'password' => $input['password'],
84            'departments' => array('id' => 0) // required in schema validation
85        ));
86        try {
87            /** @var \BO\Zmsentities\Workstation $workstation */
88            $workstation = \App::$http->readPostResult('/workstation/login/', $userAccount)->getEntity();
89
90            $sessionHash = hash('sha256', $workstation->authkey);
91            \App::$log->info('Login successful', [
92                'event' => 'auth_login_success',
93                'timestamp' => date('c'),
94                'username' => $userAccount->id,
95                'hashed_session_token' => $sessionHash,
96                'application' => 'zmsstatistic'
97            ]);
98
99            return $workstation;
100        } catch (\BO\Zmsclient\Exception $exception) {
101            $template = Helper\TwigExceptionHandler::getExceptionTemplate($exception);
102            if ('BO\Zmsentities\Exception\SchemaValidation' == $exception->template) {
103                $exceptionData = [
104                  'template' => 'exception/bo/zmsapi/exception/useraccount/invalidcredentials.twig'
105                ];
106                $exceptionData['data']['password']['messages'] = [
107                    'Der Nutzername oder das Passwort wurden falsch eingegeben'
108                ];
109                \App::$log->info('Login failed - invalid credentials', [
110                    'event' => 'auth_login_failed',
111                    'timestamp' => date('c'),
112                    'username' => $userAccount->id,
113                    'error_type' => 'invalid_credentials',
114                    'application' => 'zmsstatistic'
115                ]);
116            } elseif ('BO\Zmsapi\Exception\Useraccount\UserAlreadyLoggedIn' == $exception->template) {
117                \BO\Zmsclient\Auth::setKey($exception->data['authkey'], time() + \App::SESSION_DURATION);
118                \App::$log->info('User already logged in - reusing existing session', [
119                    'event' => 'auth_session_reuse',
120                    'timestamp' => date('c'),
121                    'username' => $userAccount->id,
122                    'hashed_session_token' => hash('sha256', $exception->data['authkey']),
123                    'application' => 'zmsstatistic'
124                ]);
125                throw $exception;
126            } elseif (
127                '' != $exception->template
128                && \App::$slim->getContainer()->get('view')->getLoader()->exists($template)
129            ) {
130                $exceptionData = [
131                  'template' => $template,
132                  'data' => $exception->data
133                ];
134                \App::$log->info('Login failed - other error', [
135                    'event' => 'auth_login_failed',
136                    'timestamp' => date('c'),
137                    'username' => $userAccount->id,
138                    'error_type' => 'other',
139                    'error_message' => $exception->getMessage(),
140                    'application' => 'zmsstatistic'
141                ]);
142            } else {
143                throw $exception;
144            }
145        }
146        return $exceptionData;
147    }
148    protected function getProviderList($config)
149    {
150        $allowedProviderList = explode(',', $config->getPreference('oidc', 'provider') ?? '');
151        $oidcproviderlist = [];
152        foreach (\BO\Slim\Middleware\OAuthMiddleware::$authInstances as $provider => $authInstance) {
153            if (
154                0 < count($allowedProviderList) &&
155                class_exists($authInstance) &&
156                in_array($provider, $allowedProviderList)
157            ) {
158                $oidcproviderlist[] = $provider;
159            }
160        }
161        return $oidcproviderlist;
162    }
163}