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