<?php
/**
* SeekQuarry/Yioop --
* Open Source Pure PHP Search Engine, Crawler, and Indexer
*
* Copyright (C) 2009 - 2026 Chris Pollett chris@pollett.org
*
* LICENSE:
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* END LICENSE
*
* @author Sreenidhi Muralidharan
* @license https://www.gnu.org/licenses/ GPL3
* @link https://www.seekquarry.com/
* @copyright 2009 - 2026
* @filesource
*/
namespace seekquarry\yioop\views\elements;
use seekquarry\yioop as B;
use seekquarry\yioop\configs as C;
/**
* Element used to handle configurations of Yioop related to authentication,
* captchas, and recovery of missing passwords
*
* @author Sreenidhi Muralidharan/Chris Pollett
*/
class SecurityElement extends Element
{
/**
* Method that draws forms to to select either among a text or a
* graphical captcha
*
* @param array $data holds data on the profile elements which have been
* filled in as well as data about which form fields to display
*/
public function render($data)
{
$admin_url = htmlentities(B\controllerUrl('admin', true));
$localize_url = $admin_url .C\p('CSRF_TOKEN')."=".
$data[C\p('CSRF_TOKEN')] .
"&a=manageLocales&arg=editstrings&selectlocale=" .
$data['LOCALE_TAG'];
?>
<div class = "current-activity">
<h2><?= tl('security_element_session_captcha') ?></h2>
<form class="top-margin" method="post">
<input type="hidden" name="c" value="admin" >
<input type="hidden" name="a" value="security" >
<input type="hidden" name="<?= C\p('CSRF_TOKEN') ?>" value="<?=
$data[C\p('CSRF_TOKEN')] ?>" >
<input type="hidden" name="arg" value="updatetypes" >
<div class="top-margin">
<fieldset>
<legend><b><?=
tl('security_element_session').
" " . $this->view->helper("helpbutton")->render(
"Session Parameters", $data[C\p('CSRF_TOKEN')])
?>
</b></legend>
<div class="top-margin"><b><label for="timezone"><?=
tl('security_element_site_timezone') ?></label></b>
<input type="text" id="timezone"
name="TIMEZONE" class="extra-wide-field" value='<?=
$data["TIMEZONE"] ?>' ></div>
<div class="top-margin"><b><label for="token-name"><?=
tl('security_element_token_name') ?></label></b>
<input type="text" id="token-name"
name="CSRF_TOKEN" class="extra-wide-field" value='<?=
$data["CSRF_TOKEN"] ?>' ></div>
<div class="top-margin"><b><label for="cookie-name"><?=
tl('security_element_session_name') ?></label></b>
<input type="text" id="cookie-name"
name="SESSION_NAME" class="extra-wide-field" value='<?=
$data["SESSION_NAME"] ?>' ></div>
<div class="top-margin"><b><label for="autologout"><?=
tl('security_element_autologout')?></label></b>
<?php
$this->view->helper("options")->render(
"autologout", "AUTOLOGOUT", $data['AUTOLOGOUT_TIMES'],
$data['AUTOLOGOUT']);?></div>
<div class="top-margin"><b><label for="consent-expires"><?=
tl('security_element_consent_expires')?></label></b>
<?php
$this->view->helper("options")->render(
"consent-expires", "COOKIE_LIFETIME",
$data['COOKIE_LIFETIMES'], $data['COOKIE_LIFETIME']);
?></div>
</fieldset>
</div>
<div class="top-margin">
<fieldset>
<legend><b><label
for="privacy-mode"><?=tl('security_element_privacy') ?>
</label>
<?= tl($this->view->helper("helpbutton")->render(
"Privacy", $data[C\p('CSRF_TOKEN')]))
?></b>
</legend>
<table>
<tr><td>
<label><b><?=
tl('security_element_differential_privacy')?></b></label>
</td><td>
<?php
if (empty($data['DIFFERENTIAL_PRIVACY'])) {
$data['DIFFERENTIAL_PRIVACY'] = 0;
}
$this->view->helper("options")->render("privacy-mode",
"DIFFERENTIAL_PRIVACY", $data['PRIVACY_MODES'],
$data['DIFFERENTIAL_PRIVACY']);
?>
</td></tr><tr><td>
<label for="group-analytics-mode"><b><?php
e(tl('security_element_group_analytics'));
?></b>
</label>
</td><td>
<?php
if (empty($data['GROUP_ANALYTICS_MODE'])) {
$data['GROUP_ANALYTICS_MODE'] = 0;
}
$this->view->helper("options")->render("group-analytics-mode",
"GROUP_ANALYTICS_MODE", $data['GROUP_ANALYTICS_MODES'],
$data['GROUP_ANALYTICS_MODE']);
?>
</td></tr><tr><td>
<label
for="search-analytics-mode"><b><?php
e(tl('security_element_search_analytics'));
?></b>
</label>
</td><td>
<?php
if (empty($data['SEARCH_ANALYTICS_MODE'])) {
$data['SEARCH_ANALYTICS_MODE'] = 0;
}
$this->view->helper("options")->render("search-analytics-mode",
"SEARCH_ANALYTICS_MODE", $data['SEARCH_ANALYTICS_MODES'],
$data['SEARCH_ANALYTICS_MODE']);
?>
</td></tr></table>
</fieldset>
</div>
<div class="top-margin">
<fieldset>
<legend><b><?=tl('security_element_authentication')
?> <?=$this->view->helper("helpbutton")->render(
"Authentication", $data[C\p('CSRF_TOKEN')])
?></b>
</legend>
<div class="top-margin"><b><label for="auth-method"><?=
tl('security_element_auth_method') ?></label></b>
<?php
$this->view->helper("options")->render("auth-method",
"AUTH_METHOD", $data['AUTH_METHODS'],
$data['AUTH_METHOD'],
'toggleClass("local-auth-section", "none");' .
'toggleClass("ldap-section", "none");' .
'elt("recovery-mode").disabled = ' .
'(this.value == ' . C\LDAP_AUTHENTICATION . ');' .
'elt("recovery-mode-off").disabled = ' .
'(this.value != ' . C\LDAP_AUTHENTICATION . ');' .
'if (this.value == ' . C\LDAP_AUTHENTICATION . ') {' .
'elt("recovery-mode").value = ' . C\NO_RECOVERY . ';}');
?></div>
<div id="local-auth-section"<?=
($data['AUTH_METHOD'] == C\LDAP_AUTHENTICATION) ?
' class="none"' : '' ?>>
<div class="top-margin"><b><?=
tl('security_element_password_rules') ?></b></div>
<div><input type="checkbox" id="password-require-lowercase"
name="PASSWORD_REQUIRE_LOWERCASE" value="true" <?=
!empty($data['PASSWORD_REQUIRE_LOWERCASE']) ?
"checked='checked'" : "" ?> ><label
for="password-require-lowercase"><?=
tl('security_element_require_lowercase') ?></label></div>
<div><input type="checkbox" id="password-require-uppercase"
name="PASSWORD_REQUIRE_UPPERCASE" value="true" <?=
!empty($data['PASSWORD_REQUIRE_UPPERCASE']) ?
"checked='checked'" : "" ?> ><label
for="password-require-uppercase"><?=
tl('security_element_require_uppercase') ?></label></div>
<div><input type="checkbox" id="password-require-digit"
name="PASSWORD_REQUIRE_DIGIT" value="true" <?=
!empty($data['PASSWORD_REQUIRE_DIGIT']) ?
"checked='checked'" : "" ?> ><label
for="password-require-digit"><?=
tl('security_element_require_digit') ?></label></div>
<div><input type="checkbox" id="password-require-symbol"
name="PASSWORD_REQUIRE_SYMBOL" value="true" <?=
!empty($data['PASSWORD_REQUIRE_SYMBOL']) ?
"checked='checked'" : "" ?> ><label
for="password-require-symbol"><?=
tl('security_element_require_symbol') ?></label></div>
<div class="top-margin"><b><label for="password-min-len"><?=
tl('security_element_password_min_len') ?></label></b>
<input type="text" id="password-min-len"
name="PASSWORD_MIN_LEN" class="very-narrow-field" value='<?=
$data['PASSWORD_MIN_LEN'] ?>' ></div>
</div>
<div id="ldap-section"<?=
($data['AUTH_METHOD'] == C\LDAP_AUTHENTICATION) ?
'' : ' class="none"' ?>>
<?php $auth_missing = $data['AUTHENTICATION_MISSING'] ?? []; ?>
<div class="top-margin"><b><label
for="ldap-controller-add"><?=
tl('security_element_ldap_controllers')
?></label></b>
<?php
$controller_csv = trim((string)
($data['LDAP_CONTROLLERS'] ?? ''));
$controller_entries = ($controller_csv === '') ? [] :
array_filter(array_map('trim',
explode(',', $controller_csv)));
?>
<ul class="mail-domain-list" id="ldap-controller-list"
><?php
foreach ($controller_entries as $controller) {
?><li class="mail-domain-item managed-csv-item"
><span class="mail-domain-text managed-csv-text"
><?= $controller
?></span><button type="button"
class="managed-csv-remove mail-domain-remove"
title="<?= tl(
'security_element_ldap_controller_remove'
) ?>">×</button></li><?php
}
?></ul>
<div class="mail-domain-add-row">
<input type="text" id="ldap-controller-add"
class="wide-field" >
<button type="button" id="ldap-controller-add-button"
class="button-box" data-remove-label="<?= tl(
'security_element_ldap_controller_remove'
) ?>"><?= tl(
'security_element_ldap_controller_add'
) ?></button><?php
if (in_array('LDAP_CONTROLLERS', $auth_missing)) {
?><span class="required-star<?=
(!empty($controller_entries)) ? ' none' : ''
?>" id="ldap-controllers-star">*</span><?php
} ?>
</div>
<input type="hidden" id="ldap-controllers"
name="LDAP_CONTROLLERS"
value="<?= $controller_csv ?>" >
</div>
<div class="top-margin"><b><label
for="ldap-account-suffix"><?=
tl('security_element_ldap_account_suffix')
?></label></b>
<input type="text" id="ldap-account-suffix"
name="LDAP_ACCOUNT_SUFFIX" class="wide-field"
value="<?= $data['LDAP_ACCOUNT_SUFFIX'] ?? '' ?>"
><?php e(in_array('LDAP_ACCOUNT_SUFFIX', $auth_missing)
? '<span class="required-star">*</span>' : ''); ?>
</div>
<div class="top-margin"><b><label for="ldap-base-dn"><?=
tl('security_element_ldap_base_dn')
?></label></b>
<input type="text" id="ldap-base-dn"
name="LDAP_BASE_DN" class="wide-field"
value="<?= $data['LDAP_BASE_DN'] ?? '' ?>"
><?php e(in_array('LDAP_BASE_DN', $auth_missing)
? '<span class="required-star">*</span>' : ''); ?>
</div>
<div class="top-margin"><?=
tl('security_element_ldap_root_intro') ?></div>
<div class="top-margin"><b><label for="ldap-root-name"><?=
tl('security_element_ldap_root_name')
?></label></b>
<input type="text" id="ldap-root-name"
name="LDAP_ROOT_NAME" class="wide-field" value=""
autocomplete="off" ><?php
e(in_array('LDAP_ROOT_NAME', $auth_missing)
? '<span class="required-star">*</span>' : ''); ?>
</div>
<div class="top-margin"><b><label
for="ldap-root-password"><?=
tl('security_element_ldap_root_password')
?></label></b>
<input type="password" id="ldap-root-password"
name="LDAP_ROOT_PASSWORD" class="wide-field" value=""
autocomplete="off" ><?php
e(in_array('LDAP_ROOT_PASSWORD', $auth_missing)
? '<span class="required-star">*</span>' : ''); ?>
</div>
<?php if (!empty($data['LDAP_PROBLEMS'])) {
$problem_messages = [
'no_servers' =>
tl('security_element_ldap_problem_no_servers'),
'no_suffix' =>
tl('security_element_ldap_problem_no_suffix'),
'no_base_dn' =>
tl('security_element_ldap_problem_no_base_dn'),
'email_conflicts' => tl(
'security_element_ldap_problem_email_conflicts'),
'root_no_email' => tl(
'security_element_ldap_problem_root_no_email'),
];
?>
<div class="top-margin red">
<?= tl('security_element_ldap_problem_intro') ?>
<ul><?php
foreach ($data['LDAP_PROBLEMS'] as $problem) {
$problem_text = $problem_messages[$problem] ?? '';
if ($problem_text === '') {
continue;
}
?><li><?= $problem_text ?><?php
if ($problem == 'email_conflicts') {
?> <a href="<?= $admin_url .
C\p('CSRF_TOKEN') . "=" .
$data[C\p('CSRF_TOKEN')] . "&a=security" .
"&arg=downloadconflicts" ?>"><?=
tl('security_element_ldap_download_conflicts')
?></a><?php
}
?></li><?php
}
?></ul>
</div>
<?php } ?>
</div>
<div class="top-margin"><b><label for="recovery-mode"><?=
tl('security_element_account_recovery') ?></label></b>
<?php
$recovery_is_ldap =
$data['AUTH_METHOD'] == C\LDAP_AUTHENTICATION;
$recovery_selected = ($recovery_is_ldap) ? C\NO_RECOVERY :
$data['RECOVERY_MODE'];
$recovery_attributes = ($recovery_is_ldap) ?
['disabled' => 'disabled'] : [];
$this->view->helper("options")->render("recovery-mode",
"RECOVERY_MODE", $data['RECOVERY_MODES'],
$recovery_selected, false, $recovery_attributes);
/* A disabled select submits nothing, so under LDAP this
hidden field carries the off value in its place; when
the method is not LDAP it is disabled and the select
submits instead, so exactly one sends RECOVERY_MODE. */
?><input type="hidden" id="recovery-mode-off"
name="RECOVERY_MODE" value="<?= C\NO_RECOVERY ?>"<?=
($recovery_is_ldap) ? '' : ' disabled="disabled"'
?> ></div>
</fieldset>
</div>
<div class="top-margin center"><button
class="button-box" type="submit"><?=tl('security_element_save')
?></button>
</div>
</form>
<script>
window.onload = function()
{
initManagedCsvList("ldap-controller-list", "ldap-controller-add",
"ldap-controller-add-button", "ldap-controllers",
function(count) {
setClass("ldap-controllers-star", count > 0, "none");
});
}
</script>
</div>
<?php
}
}