Subversion Repositories oidplus

Rev

Rev 1050 | Rev 1108 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
635 daniel-mar 1
<?php
2
 
3
/*
4
 * OIDplus 2.0
1086 daniel-mar 5
 * Copyright 2019 - 2023 Daniel Marschall, ViaThinkSoft
635 daniel-mar 6
 *
7
 * Licensed under the Apache License, Version 2.0 (the "License");
8
 * you may not use this file except in compliance with the License.
9
 * You may obtain a copy of the License at
10
 *
11
 *     http://www.apache.org/licenses/LICENSE-2.0
12
 *
13
 * Unless required by applicable law or agreed to in writing, software
14
 * distributed under the License is distributed on an "AS IS" BASIS,
15
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 * See the License for the specific language governing permissions and
17
 * limitations under the License.
18
 */
19
 
1050 daniel-mar 20
namespace ViaThinkSoft\OIDplus;
635 daniel-mar 21
 
1086 daniel-mar 22
// phpcs:disable PSR1.Files.SideEffects
23
\defined('INSIDE_OIDPLUS') or die;
24
// phpcs:enable PSR1.Files.SideEffects
25
 
635 daniel-mar 26
class OIDplusPagePublicLogin extends OIDplusPagePluginPublic {
27
 
28
        public function action($actionID, $params) {
29
                // === RA LOGIN/LOGOUT ===
30
 
31
                if ($actionID == 'ra_login') {
702 daniel-mar 32
                        OIDplus::getActiveCaptchaPlugin()->captchaVerify($params, 'captcha');
635 daniel-mar 33
 
34
                        _CheckParamExists($params, 'email');
35
                        _CheckParamExists($params, 'password');
36
 
37
                        $email = $params['email'];
38
                        $ra = new OIDplusRA($email);
39
 
40
                        if (empty($email)) {
41
                                throw new OIDplusException(_L('Please enter a valid email address'));
42
                        }
43
 
44
                        if ($ra->checkPassword($params['password'])) {
45
                                $remember_me = isset($params['remember_me']) && ($params['remember_me']);
46
                                OIDplus::authUtils()->raLoginEx($email, $remember_me, 'Regular login');
47
 
48
                                OIDplus::db()->query("UPDATE ###ra set last_login = ".OIDplus::db()->sqlDate()." where email = ?", array($email));
49
 
50
                                return array("status" => 0);
51
                        } else {
52
                                if (OIDplus::config()->getValue('log_failed_ra_logins', false)) {
53
                                        if ($ra->existing()) {
54
                                                OIDplus::logger()->log("[WARN]A!", "Failed login to RA account '$email' (wrong password)");
55
                                        } else {
56
                                                OIDplus::logger()->log("[WARN]A!", "Failed login to RA account '$email' (RA not existing)");
57
                                        }
58
                                }
59
                                throw new OIDplusException(_L('Wrong password or user not registered'));
60
                        }
61
 
62
                } else if ($actionID == 'ra_logout') {
63
 
64
                        _CheckParamExists($params, 'email');
65
 
66
                        $email = $params['email'];
67
 
68
                        OIDplus::authUtils()->raLogoutEx($email);
69
 
70
                        return array("status" => 0);
71
                }
72
 
73
                // === ADMIN LOGIN/LOGOUT ===
74
 
75
                else if ($actionID == 'admin_login') {
702 daniel-mar 76
                        OIDplus::getActiveCaptchaPlugin()->captchaVerify($params, 'captcha');
635 daniel-mar 77
 
78
                        _CheckParamExists($params, 'password');
79
                        if (OIDplus::authUtils()->adminCheckPassword($params['password'])) {
80
                                $remember_me = isset($params['remember_me']) && ($params['remember_me']);
81
                                OIDplus::authUtils()->adminLoginEx($remember_me, 'Regular login');
82
 
83
                                // TODO: Write a "last login" entry in config table?
84
 
85
                                return array("status" => 0);
86
                        } else {
87
                                if (OIDplus::config()->getValue('log_failed_admin_logins', false)) {
88
                                        OIDplus::logger()->log("[WARN]A!", "Failed login to admin account");
89
                                }
90
                                throw new OIDplusException(_L('Wrong password'));
91
                        }
92
                }
93
                else if ($actionID == 'admin_logout') {
94
                        OIDplus::authUtils()->adminLogoutEx();
95
 
96
                        return array("status" => 0);
97
                }
98
                else {
99
                        throw new OIDplusException(_L('Unknown action ID'));
100
                }
101
        }
102
 
103
        public function init($html=true) {
104
                OIDplus::config()->prepareConfigKey('log_failed_ra_logins', 'Log failed RA logins', '0', OIDplusConfig::PROTECTION_EDITABLE, function($value) {
105
                        if (!is_numeric($value) || (($value != 0) && (($value != 1)))) {
106
                                throw new OIDplusException(_L('Valid values: 0 (off) or 1 (on).'));
107
                        }
108
                });
109
                OIDplus::config()->prepareConfigKey('log_failed_admin_logins', 'Log failed Admin logins', '0', OIDplusConfig::PROTECTION_EDITABLE, function($value) {
110
                        if (!is_numeric($value) || (($value != 0) && (($value != 1)))) {
111
                                throw new OIDplusException(_L('Valid values: 0 (off) or 1 (on).'));
112
                        }
113
                });
114
        }
115
 
116
        public function gui($id, &$out, &$handled) {
117
                $ary = explode('$', $id);
118
                $desired_ra = '';
119
                if (isset($ary[1])) {
120
                        $id = $ary[0];
121
                        $tab = $ary[1];
122
                        if (isset($ary[2])) {
123
                                $desired_ra = $ary[2];
124
                        }
125
                } else {
126
                        $tab = 'ra';
127
                }
128
                if ($id === 'oidplus:login') {
129
                        $handled = true;
130
                        $out['title'] = _L('Login');
801 daniel-mar 131
                        $out['icon']  = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/login_icon.png';
635 daniel-mar 132
 
133
                        $out['text'] = '';
134
 
135
                        $out['text'] .= '<noscript>';
136
                        $out['text'] .= '<p>'._L('You need to enable JavaScript to use the login area.').'</p>';
137
                        $out['text'] .= '</noscript>';
138
 
139
                        $out['text'] .= '<div id="loginArea" style="visibility: hidden"><div id="loginTab" class="container" style="width:100%;">';
702 daniel-mar 140
 
141
                        $out['text'] .= OIDplus::getActiveCaptchaPlugin()->captchaGenerate(_L('Before logging in, please solve the following CAPTCHA'));
635 daniel-mar 142
                        $out['text'] .= '<br>';
143
 
144
                        // ---------------- Tab control
145
                        $out['text'] .= OIDplus::gui()->tabBarStart();
146
                        $out['text'] .= OIDplus::gui()->tabBarElement('ra',    _L('Login as RA'),            $tab === 'ra');
147
                        $out['text'] .= OIDplus::gui()->tabBarElement('admin', _L('Login as administrator'), $tab === 'admin');
148
                        $out['text'] .= OIDplus::gui()->tabBarEnd();
149
                        $out['text'] .= OIDplus::gui()->tabContentStart();
150
                        // ---------------- "RA" tab
151
                        $tabcont = '<h2>'._L('Login as RA').'</h2>';
152
                        $login_list = OIDplus::authUtils()->loggedInRaList();
153
                        if (count($login_list) > 0) {
154
                                foreach ($login_list as $x) {
155
                                        $tabcont .= '<p>'._L('You are logged in as %1','<b>'.$x->raEmail().'</b>').' (<a href="#" onclick="return OIDplusPagePublicLogin.raLogout('.js_escape($x->raEmail()).');">'._L('Logout').'</a>)</p>';
156
                                }
157
                                $tabcont .= '<p>'._L('If you have more accounts, you can log in with another account here.').'</p>';
158
                        } else {
159
                                $tabcont .= '<p>'._L('Enter your email address and your password to log in as Registration Authority.').'</p>';
160
                        }
161
                        $tabcont .= '<form action="javascript:void(0);" onsubmit="return OIDplusPagePublicLogin.raLoginOnSubmit(this);">';
162
                        $tabcont .= '<div><label class="padding_label">'._L('E-Mail').':</label><input type="text" name="email" value="'.htmlentities($desired_ra).'" id="raLoginEMail"></div>';
163
                        $tabcont .= '<div><label class="padding_label">'._L('Password').':</label><input type="password" name="password" value="" id="raLoginPassword"></div>';
164
                        if (OIDplus::baseConfig()->getValue('JWT_ALLOW_LOGIN_USER', true)) {
165
                                if ((OIDplus::authUtils()->getAuthMethod() === OIDplusAuthContentStoreJWT::class)) {
166
                                        if (OIDplus::authUtils()->getExtendedAttribute('oidplus_generator',-1) === OIDplusAuthContentStoreJWT::JWT_GENERATOR_LOGIN) {
167
                                                $att = 'disabled checked';
168
                                        } else {
169
                                                $att = 'disabled';
170
                                        }
171
                                } else if ((OIDplus::authUtils()->getAuthMethod() === OIDplusAuthContentStoreSession::class)) {
172
                                        $att = 'disabled';
173
                                } else {
174
                                        $att = '';
175
                                }
176
                                $tabcont .= '<div><input '.$att.' type="checkbox" value="1" id="remember_me_ra" name="remember_me_ra"> <label for="remember_me_ra">'._L('Remember me').'</label></div>';
177
                        }
178
                        $tabcont .= '<br><input type="submit" value="'._L('Login').'"><br><br>';
179
                        $tabcont .= '</form>';
180
                        $tabcont .= '<p><a '.OIDplus::gui()->link('oidplus:forgot_password').'>'._L('Forgot password?').'</a><br>';
181
 
182
                        $invitePlugin = OIDplus::getPluginByOid('1.3.6.1.4.1.37476.2.5.2.4.2.92'); // OIDplusPageRaInvite
183
                        if (!is_null($invitePlugin) && OIDplus::config()->getValue('ra_invitation_enabled')) {
184
                                $tabcont .= '<abbr title="'._L('To receive login data, the superior RA needs to send you an invitation. After creating or updating your OID, the system will ask them if they want to send you an invitation. If they accept, you will receive an email with an activation link. Alternatively, the system admin can create your account manually in the administrator control panel.').'">'._L('How to register?').'</abbr></p>';
185
                        } else {
186
                                $tabcont .= '<abbr title="'._L('Since invitations are disabled at this OIDplus system, the system administrator needs to create your account manually in the administrator control panel.').'">'._L('How to register?').'</abbr></p>';
187
                        }
188
 
189
                        if ($tab === 'ra') {
190
                                $alt_logins_html = array();
1005 daniel-mar 191
                                foreach (OIDplus::getAllPlugins() as $plugin) {
635 daniel-mar 192
                                        if ($plugin->implementsFeature('1.3.6.1.4.1.37476.2.5.2.3.5')) {
193
                                                $logins = $plugin->alternativeLoginMethods();
194
                                                foreach ($logins as $data) {
195
                                                        if (isset($data[2]) && !empty($data[2])) {
196
                                                                $img = '<img src="'.$data[2].'" alt="'.htmlentities($data[1]).'"> ';
197
                                                        } else {
198
                                                                $img = '';
199
                                                        }
200
                                                        $alt_logins_html[] = $img.'<a '.OIDplus::gui()->link($data[0]).'>'.htmlentities($data[1]).'</a>';
201
                                                }
202
                                        }
203
                                }
204
                                if (count($alt_logins_html) > 0) {
205
                                        $tabcont .= '<p>'._L('Alternative login methods').':<br>';
206
                                        foreach ($alt_logins_html as $alt_login) {
207
                                                $tabcont .= $alt_login.'<br>';
208
                                        }
209
                                        $tabcont .= '</p>';
210
                                }
211
                        }
212
 
213
                        $out['text'] .= OIDplus::gui()->tabContentPage('ra', $tabcont, $tab === 'ra');
214
                        // ---------------- "Administrator" tab
215
                        $tabcont = '<h2>'._L('Login as administrator').'</h2>';
216
                        if (OIDplus::authUtils()->isAdminLoggedIn()) {
217
                                $tabcont .= '<p>'._L('You are logged in as administrator.').'</p>';
218
                                $tabcont .= '<a href="#" onclick="return OIDplusPagePublicLogin.adminLogout();">'._L('Logout').'</a>';
219
                        } else {
220
                                $tabcont .= '<form action="javascript:void(0);" onsubmit="return OIDplusPagePublicLogin.adminLoginOnSubmit(this);">';
221
                                $tabcont .= '<div><label class="padding_label">'._L('Password').':</label><input type="password" name="password" value="" id="adminLoginPassword"></div>';
222
                                if (OIDplus::baseConfig()->getValue('JWT_ALLOW_LOGIN_ADMIN', true)) {
223
                                        if ((OIDplus::authUtils()->getAuthMethod() === OIDplusAuthContentStoreJWT::class)) {
224
                                                if (OIDplus::authUtils()->getExtendedAttribute('oidplus_generator',-1) === OIDplusAuthContentStoreJWT::JWT_GENERATOR_LOGIN) {
225
                                                        $att = 'disabled checked';
226
                                                } else {
227
                                                        $att = 'disabled';
228
                                                }
229
                                        } else if ((OIDplus::authUtils()->getAuthMethod() === OIDplusAuthContentStoreSession::class)) {
230
                                                $att = 'disabled';
231
                                        } else {
232
                                                $att = '';
233
                                        }
234
                                        $tabcont .= '<div><input '.$att.' type="checkbox" value="1" id="remember_me_admin" name="remember_me_admin"> <label for="remember_me_admin">'._L('Remember me').'</label></div>';
235
                                }
236
                                $tabcont .= '<br><input type="submit" value="'._L('Login').'"><br><br>';
237
                                $tabcont .= '</form>';
238
                                $tabcont .= '<p><a '.OIDplus::gui()->link('oidplus:forgot_password_admin').'>'._L('Forgot password?').'</a><br>';
239
                        }
240
                        $out['text'] .= OIDplus::gui()->tabContentPage('admin', $tabcont, $tab === 'admin');
241
                        $out['text'] .= OIDplus::gui()->tabContentEnd();
242
                        // ---------------- Tab control END
243
 
244
                        $out['text'] .= '</div><br>';
245
 
246
                        $mins = ceil(OIDplus::baseConfig()->getValue('SESSION_LIFETIME', 30*60)/60);
247
                        $out['text'] .= '<p><font size="-1">'._L('<i>Privacy information</i>: By using the login functionality, you are accepting that a "session cookie" is temporarily stored in your browser. The session cookie is a small text file that is sent to this website every time you visit it, to identify you as an already logged in user. It does not track any of your online activities outside OIDplus. The cookie will be destroyed when you log out or after an inactivity of %1 minutes (except if the "Remember me" option is used).', $mins);
248
                        $privacy_document_file = 'OIDplus/privacy_documentation.html';
249
                        $resourcePlugin = OIDplus::getPluginByOid('1.3.6.1.4.1.37476.2.5.2.4.1.500'); // OIDplusPagePublicResources
250
                        if (!is_null($resourcePlugin) && file_exists(OIDplus::localpath().'res/'.$privacy_document_file)) {
251
                                $out['text'] .= ' <a '.OIDplus::gui()->link('oidplus:resources$'.$privacy_document_file.'#cookies').'>'._L('More information about the cookies used').'</a>';
252
                        }
253
                        $out['text'] .= '</font></p></div>';
254
 
255
                        $out['text'] .= '<script>$("#loginArea")[0].style.visibility = "visible";</script>';
256
                }
257
        }
258
 
259
        public function publicSitemap(&$out) {
260
                $out[] = 'oidplus:login';
261
        }
262
 
263
        public function tree(&$json, $ra_email=null, $nonjs=false, $req_goto='') {
264
                $loginChildren = array();
265
 
266
                if (OIDplus::authUtils()->isAdminLoggedIn()) {
267
                        $ra_roots = array();
268
 
269
                        foreach (OIDplus::getPagePlugins() as $plugin) {
270
                                if (is_subclass_of($plugin, OIDplusPagePluginAdmin::class)) {
271
                                        $plugin->tree($ra_roots);
272
                                }
273
                        }
274
 
275
                        $ra_roots[] = array(
276
                                'id'       => 'oidplus:logout$admin',
801 daniel-mar 277
                                'icon'     => OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/logout_icon16.png',
635 daniel-mar 278
                                'conditionalselect' => 'OIDplusPagePublicLogin.adminLogout(); false;',
279
                                'text'     => _L('Log out')
280
                        );
281
                        $loginChildren[] = array(
282
                                'id'       => 'oidplus:dummy$'.md5((string)rand()),
283
                                'text'     => _L("Logged in as <b>admin</b>"),
801 daniel-mar 284
                                'icon'     => OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/admin_icon16.png',
635 daniel-mar 285
                                'conditionalselect' => 'false', // dummy node that can't be selected
286
                                'state'    => array("opened" => true),
287
                                'children' => $ra_roots
288
                        );
289
                }
290
 
291
                foreach (OIDplus::authUtils()->loggedInRaList() as $ra) {
292
                        $ra_email = $ra->raEmail();
293
                        $ra_roots = array();
294
 
295
                        foreach (OIDplus::getPagePlugins() as $plugin) {
296
                                if (is_subclass_of($plugin, OIDplusPagePluginRa::class)) {
297
                                        $plugin->tree($ra_roots, $ra_email);
298
                                }
299
                        }
300
 
301
                        $ra_roots[] = array(
302
                                'id'       => 'oidplus:logout$'.$ra_email,
303
                                'conditionalselect' => 'OIDplusPagePublicLogin.raLogout('.js_escape($ra_email).'); false;',
801 daniel-mar 304
                                'icon'     => OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/logout_icon16.png',
635 daniel-mar 305
                                'text'     => _L('Log out')
306
                        );
307
                        foreach (OIDplusObject::getRaRoots($ra_email) as $loc_root) {
308
                                $ico = $loc_root->getIcon();
309
                                $ra_roots[] = array(
310
                                        'id' => 'oidplus:raroot$'.$loc_root->nodeId(),
311
                                        'text' => _L('Jump to RA root %1',$loc_root->objectTypeTitleShort().' '.$loc_root->crudShowId(OIDplusObject::parse($loc_root::root()))),
312
                                        'conditionalselect' => 'openOidInPanel('.js_escape($loc_root->nodeId()).', true); false;',
801 daniel-mar 313
                                        'icon' => !is_null($ico) ? $ico : OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/link_icon16.png'
635 daniel-mar 314
                                );
315
                        }
316
                        $ra_email_or_name = (new OIDplusRA($ra_email))->raName();
317
                        if ($ra_email_or_name == '') {
318
                                $ra_email_html = htmlentities($ra_email);
319
                                $ra_email_or_name = '<b>'.$ra_email_html.'</b>';
320
                        } else {
321
                                $ra_email_html = htmlentities($ra_email);
322
                                $ra_email_or_name_html = htmlentities($ra_email_or_name);
323
                                $ra_email_or_name = "<b>$ra_email_or_name_html</b> ($ra_email_html)";
324
                        }
325
                        $loginChildren[] = array(
326
                                'id'       => 'oidplus:dummy$'.md5((string)rand()),
327
                                'text'     => _L('Logged in as %1',$ra_email_or_name),
801 daniel-mar 328
                                'icon'     => OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/ra_icon16.png',
635 daniel-mar 329
                                'conditionalselect' => 'false', // dummy node that can't be selected
330
                                'state'    => array("opened" => true),
331
                                'children' => $ra_roots
332
                        );
333
                }
334
 
335
                $json[] = array(
336
                        'id'       => 'oidplus:login',
801 daniel-mar 337
                        'icon'     => OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/login_icon16.png',
635 daniel-mar 338
                        'text'     => _L('Login'),
339
                        'state'    => array("opened" => count($loginChildren)>0),
340
                        'children' => $loginChildren
341
                );
342
 
343
                return true;
344
        }
345
 
346
        public function tree_search($request) {
347
                return false;
348
        }
349
}