ACL Login update layout to work with PC/Smartphone

Updated login template and password change template block
This commit is contained in:
Clemens Schwaighofer
2024-12-09 16:20:21 +09:00
parent fe50a988a0
commit a56cbd8e97

View File

@@ -180,6 +180,7 @@ class Login
private array $login_template = [ private array $login_template = [
'strings' => [], 'strings' => [],
'password_change' => '', 'password_change' => '',
'password_forgot' => '',
'template' => '' 'template' => ''
]; ];
@@ -232,13 +233,12 @@ class Login
* @param \CoreLibs\Logging\Logging $log Logging class * @param \CoreLibs\Logging\Logging $log Logging class
* @param \CoreLibs\Create\Session $session Session interface class * @param \CoreLibs\Create\Session $session Session interface class
* @param array<string,mixed> $options Login ACL settings * @param array<string,mixed> $options Login ACL settings
* $auto_login [default true] DEPRECATED, moved into options
*/ */
public function __construct( public function __construct(
\CoreLibs\DB\IO $db, \CoreLibs\DB\IO $db,
\CoreLibs\Logging\Logging $log, \CoreLibs\Logging\Logging $log,
\CoreLibs\Create\Session $session, \CoreLibs\Create\Session $session,
array $options = [] array $options = [],
) { ) {
// attach db class // attach db class
$this->db = $db; $this->db = $db;
@@ -1601,6 +1601,10 @@ class Login
$this->login_template['strings']['LANGUAGE'] = $locales['lang'] ?? 'en'; $this->login_template['strings']['LANGUAGE'] = $locales['lang'] ?? 'en';
// if password change is okay // if password change is okay
// TODO: this should be a "forgot" password
// -> input email
// -> send to user with link + token
// -> validate token -> show change password
if ($this->password_change) { if ($this->password_change) {
$html_string_password_change = $this->login_template['password_change']; $html_string_password_change = $this->login_template['password_change'];
@@ -1617,14 +1621,14 @@ class Login
// print error messagae // print error messagae
if ($this->login_error) { if ($this->login_error) {
$html_string_password_change = str_replace( $html_string_password_change = str_replace(
'{ERROR_MSG}', ['{ERROR_VISIBLE}', '{ERROR_MSG}'],
$this->loginGetErrorMsg($this->login_error) . '<br>', ['login-visible', $this->loginGetErrorMsg($this->login_error)],
$html_string_password_change $html_string_password_change
); );
} else { } else {
$html_string_password_change = str_replace( $html_string_password_change = str_replace(
'{ERROR_MSG}', ['{ERROR_VISIBLE}', '{ERROR_MSG}'],
'<br>', ['login-hidden', ''],
$html_string_password_change $html_string_password_change
); );
} }
@@ -1632,8 +1636,11 @@ class Login
if ($this->change_password && !$this->password_change_ok) { if ($this->change_password && !$this->password_change_ok) {
$html_string_password_change = str_replace( $html_string_password_change = str_replace(
'{PASSWORD_CHANGE_SHOW}', '{PASSWORD_CHANGE_SHOW}',
'<script language="JavaScript">' <<<HTML
. 'ShowHideDiv(\'pw_change_div\');</script>', <script language="JavaScript">
ShowHideDiv('login_pw_change_div');
</script>
HTML,
$html_string_password_change $html_string_password_change
); );
} else { } else {
@@ -1660,18 +1667,22 @@ class Login
// print error messagae // print error messagae
if ($this->login_error) { if ($this->login_error) {
$html_string = str_replace( $html_string = str_replace(
'{ERROR_MSG}', ['{ERROR_VISIBLE}', '{ERROR_MSG}'],
$this->loginGetErrorMsg($this->login_error) . '<br>', ['login-visible', $this->loginGetErrorMsg($this->login_error)],
$html_string $html_string
); );
} elseif ($this->password_change_ok && $this->password_change) { } elseif ($this->password_change_ok && $this->password_change) {
$html_string = str_replace( $html_string = str_replace(
'{ERROR_MSG}', ['{ERROR_VISIBLE}', '{ERROR_MSG}'],
$this->loginGetErrorMsg(300) . '<br>', ['login-visible', $this->loginGetErrorMsg(300)],
$html_string $html_string
); );
} else { } else {
$html_string = str_replace('{ERROR_MSG}', '<br>', $html_string); $html_string = str_replace(
['{ERROR_VISIBLE}', '{ERROR_MSG}'],
['login-hidden', ''],
$html_string
);
} }
// create the replace array context // create the replace array context
@@ -1756,39 +1767,93 @@ class Login
'NEW_PASSWORD' => $this->l->__('New Password'), 'NEW_PASSWORD' => $this->l->__('New Password'),
'NEW_PASSWORD_CONFIRM' => $this->l->__('New Password confirm'), 'NEW_PASSWORD_CONFIRM' => $this->l->__('New Password confirm'),
'CLOSE' => $this->l->__('Close'), 'CLOSE' => $this->l->__('Close'),
'JS_SHOW_HIDE' => "function ShowHideDiv(id) { " 'JS_SHOW_HIDE' => <<<JAVASCRIPT
. "element = document.getElementById(id); " function ShowHideDiv(id) {
. "if (element.className == 'visible' || !element.className) element.className = 'hidden'; " element = document.getElementById(id);
. "else element.className = 'visible'; }", let visible = !!(
'PASSWORD_CHANGE_BUTTON' => '<input type="button" name="pw_change" value="' element.offsetWidth ||
. $strings['PASSWORD_CHANGE_BUTTON_VALUE'] element.offsetHeight ||
. '" OnClick="ShowHideDiv(\'pw_change_div\');">' element.getClientRects().length ||
window.getComputedStyle(element).visibility == "hidden"
);
if (visiblee) {
element.className = 'login-hidden';
} else {
element.className = 'login-visible';
}
}
JAVASCRIPT,
'PASSWORD_CHANGE_BUTTON' => str_replace(
'{PASSWORD_CHANGE_BUTTON_VALUE}',
$strings['PASSWORD_CHANGE_BUTTON_VALUE'],
// phpcs:disable Generic.Files.LineLength
<<<HTML
<input type="button" name="pw_change" value="{PASSWORD_CHANGE_BUTTON_VALUE}" OnClick="ShowHideDiv('login_pw_change_div'); return false;">
HTML
// phpcs:enable Generic.Files.LineLength
),
]); ]);
// TODO: submit or JS to set target page as ajax call // phpcs:disable Generic.Files.LineLength
// NOTE: for the HTML block I ignore line lengths
// phpcs:disable
$this->login_template['password_change'] = <<<HTML $this->login_template['password_change'] = <<<HTML
<div id="pw_change_div" class="hidden" style="position: absolute; top: 30px; left: 50px; width: 400px; height: 220px; background-color: white; border: 1px solid black; padding: 25px;"> <div id="loginPasswordChangeBox" class="login-password-change login-hidden">
<table> <div id="loginTitle" class="login-title">
<tr><td class="norm" align="center" colspan="2"><h3>{TITLE_PASSWORD_CHANGE}</h3></td></tr> {TITLE_PASSWORD_CHANGE}
<tr><td class="norm" colspan="2">{ERROR_MSG}</td></tr> </div>
<tr><td class="norm" align="right">{USERNAME}</td><td><input type="text" name="pw_username" value=""></td></tr> <div id="loginPasswordChangeError" class="login-error {ERROR_VISIBLE}">
<tr><td class="norm" align="right">{OLD_PASSWORD}</td> {ERROR_MSG}
<td><input type="password" name="pw_old_password" value=""></td></tr> </div>
<tr><td class="norm" align="right">{NEW_PASSWORD}</td> <div id="loginPasswordChange" class="login-data">
<td><input type="password" name="pw_new_password" value=""></td></tr> <div class="login-data-row">
<tr><td class="norm" align="right">{NEW_PASSWORD_CONFIRM}</td> <div class="login-data-left">
<td><input type="password" name="pw_new_password_confirm" value=""></td></tr> {USERNAME}
<tr><td></td> </div>
<td><input type="submit" name="change_password" value="{PASSWORD_CHANGE_BUTTON_VALUE}"> <div class="login-data-right">
<input type="button" name="pw_change" value="{CLOSE}" OnClick="ShowHideDiv('pw_change_div');"></td></tr> <input type="text" name="login_username" class="login-input-text">
</table> </div>
</div>
<div class="login-data-row">
<div class="login-data-left">
{OLD_PASSWORD}
</div>
<div class="login-data-right">
<input type="password" name="login_pw_old_password" class="login-input-text">
</div>
</div>
<div class="login-data-row">
<div class="login-data-left">
{NEW_PASSWORD}
</div>
<div class="login-data-right">
<input type="password" name="login_pw_new_password" class="login-input-text">
</div>
</div>
<div class="login-data-row">
<div class="login-data-left">
{NEW_PASSWORD_CONFIRM}
</div>
<div class="login-data-right">
<input type="password" name="login_pw_new_password_confirm" class="login-input-text">
</div>
</div>
<div class="login-data-row login-button-row">
<div class="login-data-left">
&nbsp;
</div>
<div class="login-data-right">
<button type="submit" name="login_change_password" class="login-button" value="{PASSWORD_CHANGE_BUTTON_VALUE}">{PASSWORD_CHANGE_BUTTON_VALUE}</button>
</div>
<div class="login-data-button">
<button type="button" name="login_pw_change" class="login-button" value="{CLOSE}" OnClick="ShowHideDiv('loginPasswordChangeBox'); return false;">{CLOSE}</button>
</div>
</div>
</div>
</div> </div>
{PASSWORD_CHANGE_SHOW} {PASSWORD_CHANGE_SHOW}
HTML; HTML;
// phpcs:enable // phpcs:enable Generic.Files.LineLength
} }
if ($this->password_forgot) { if ($this->password_forgot) {
// TODO: create a password forget request flow
} }
if (!$this->password_change && !$this->password_forgot) { if (!$this->password_change && !$this->password_forgot) {
$strings = array_merge($strings, [ $strings = array_merge($strings, [
@@ -1807,71 +1872,162 @@ HTML;
} }
// now check templates // now check templates
// TODO: submit or JS to set target page as ajax call
if (!$this->login_template['template']) { if (!$this->login_template['template']) {
// phpcs:disable Generic.Files.LineLength
$this->login_template['template'] = <<<HTML $this->login_template['template'] = <<<HTML
<!DOCTYPE html> <!DOCTYPE html>
<html lang="{LANGUAGE}"> <html lang="{LANGUAGE}">
<head> <head>
<title>{HTML_TITLE}</title> <meta charset="utf-8">
<style type="text/css"> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
.norm { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px; line-height: 15px; color: #000000} <meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0">
h3 { font-size: 18px; } <title>{HTML_TITLE}</title>
.visible { visibility: visible; } <style type="text/css">
.hidden { visibility: hidden; display: none; } body {
margin: 0;
padding: 0;
background-color: #ffffff;
width: 100%;
font-family: Verdana, Arial, Helvetica, sans-serif;
box-sizing: border-box;
}
.login-box {
margin: 50px 0;
width: 100%;
}
.login-title {
font-size: 2em;
padding: 1% 0 1% 10%;
background-color: hsl(0, 0%, 90%);
}
.login-error {
margin: 2% 5%;
}
.login-data {
margin: 0 5% 5% 5%;
}
.login-data-row {
display: flex;
justify-content: flex-start;
padding: 5px 0;
}
.login-data-row .login-data-left {
width: 10%;
font-size: 0.8em;
text-align: right;
padding-right: 5px;
margin: auto 0;
}
.login-data-row .login-data-right {
width: 20%;
}
.login-data-row .login-data-button {
width: 70%;
text-align: right;
}
input.login-input-text {
font-size: 1.5em;
}
button.login-button {
font-size: 1.5em;
}
.login-visible {
visibility: visible;
}
.login-hidden {
visibility: hidden;
display: none;
}
.login-password-change {
position: absolute;
top: 10%;
left: 10%;
width: 80%;
background-color: white;
border: 1px solid black;
}
@media only screen and ( max-width: 749px ) {
.login-box {
margin: 5% 0;
}
.login-data {
margin: 0 5% 5% 5%;
}
.login-error {
margin: 10% 5%;
}
.login-data-row {
display: block;
}
.login-data-row .login-data-left,
.login-data-row .login-data-right,
.login-data-row .login-data-button {
width: auto;
}
.login-data-row .login-data-left {
text-align: left;
margin-bottom: 2%;
}
.login-data-row .login-data-button {
text-align: left;
margin-top: 5%;
}
.login-password-change {
top: 5%;
left: 5%;
width: 90%;
}
}
</style> </style>
<script language="JavaScript"> <script language="JavaScript">
<!--
{JS_SHOW_HIDE} {JS_SHOW_HIDE}
//--> </script>
</script>
{LOGOUT_TARGET} {LOGOUT_TARGET}
</head> </head>
<body bgcolor="#FFFFFF"> <body bgcolor="#FFFFFF">
<br>
<br>
<br>
<form method="post"> <form method="post">
<table width="500" border="0" cellpadding="2" cellspacing="1"> <div id="loginBox" class="login-box">
<tr> <div id="loginTitle" class="login-title">
<td class="norm" align="right"> {TITLE}
<h3>{TITLE}</h3> </div>
</td> <div id="loginError" class="login-error {ERROR_VISIBLE}">
<td>&nbsp;</td> {ERROR_MSG}
</tr> </div>
<tr> <div id="loginData" class="login-data">
<td class="norm" colspan="2" align="center"> <div class="login-data-row">
{ERROR_MSG} <div class="login-data-left">
</td> {USERNAME}
</tr> </div>
<tr> <div class="login-data-right">
<td align="right" class="norm">{USERNAME}</td> <input type="text" name="login_username" class="login-input-text">
<td><input type="text" name="login_username"></td> </div>
</tr> </div>
<tr> <div class="login-data-row">
<td align="right" class="norm">{PASSWORD}</td> <div class="login-data-left">
<td><input type="password" name="login_password"></td> {PASSWORD}
</tr> </div>
<tr> <div class="login-data-right">
<td align="right"></td> <input type="password" name="login_password" class="login-input-text">
<td> </div>
<input type="submit" name="login_login" value="{LOGIN}"> </div>
{PASSWORD_CHANGE_BUTTON} <div class="login-data-row login-button-row">
</td> <div class="login-data-left">
</tr> &nbsp;
<tr> </div>
<td align="right"> <div class="login-data-right">
<br><br> <button type="submit" name="login_login" class="login-button" value="{LOGIN}">{LOGIN}</button>
</td> {PASSWORD_CHANGE_BUTTON}
<td>&nbsp;</td> </div>
</tr> </div>
</table> </div>
{PASSWORD_CHANGE_DIV} {PASSWORD_CHANGE_DIV}
</div>
</form> </form>
</body> </body>
</html> </html>
HTML; HTML;
// phpcs:enable Generic.Files.LineLength
} }
} }
@@ -2167,11 +2323,11 @@ HTML;
$this->password = $_POST['login_password'] ?? ''; $this->password = $_POST['login_password'] ?? '';
$this->logout = $_POST['login_logout'] ?? ''; $this->logout = $_POST['login_logout'] ?? '';
// password change vars // password change vars
$this->change_password = $_POST['change_password'] ?? ''; $this->change_password = $_POST['login_change_password'] ?? '';
$this->pw_username = $_POST['pw_username'] ?? ''; $this->pw_username = $_POST['login_pw_username'] ?? '';
$this->pw_old_password = $_POST['pw_old_password'] ?? ''; $this->pw_old_password = $_POST['login_pw_old_password'] ?? '';
$this->pw_new_password = $_POST['pw_new_password'] ?? ''; $this->pw_new_password = $_POST['login_pw_new_password'] ?? '';
$this->pw_new_password_confirm = $_POST['pw_new_password_confirm'] ?? ''; $this->pw_new_password_confirm = $_POST['login_pw_new_password_confirm'] ?? '';
// disallow user list for password change // disallow user list for password change
$this->pw_change_deny_users = ['admin']; $this->pw_change_deny_users = ['admin'];
// max login counts before error reporting // max login counts before error reporting