Customisable email text, define base path for the URL when behind a reverse proxy, upgrade to PHP 8, no more empty member entries in groups, various tweaks and enhancements.

This commit is contained in:
Brian Lycett 2021-05-19 08:55:07 +01:00
commit d8eb7ae81d
10 changed files with 156 additions and 65 deletions

View File

@ -53,7 +53,7 @@ docker run \
-e "LDAP_ADMIN_BIND_PWD=secret"\
-e "LDAP_IGNORE_CERT_ERRORS=true" \
-e "EMAIL_DOMAIN=ldapusermanager.org" \
wheelybird/ldap-user-manager:v1.6
wheelybird/ldap-user-manager:v1.7
```
Change the variable values to suit your environment. Now go to https://lum.example.com/setup.
@ -152,17 +152,28 @@ To send emails you'll need to use an existing SMTP server. Email sending will b
* `SMTP_PASSWORD` (no default): The password to use when the SMTP server requires authentication.
* `SMTP_USE_TLS` (default: *FALSE*): Set to TRUE if the SMTP server requires TLS to be enabled.
* `SMTP_USE_TLS` (default: *FALSE*): Set to TRUE if the SMTP server requires TLS to be enabled. Overrides `SMTP_USE_TLS`.
* `SMTP_USE_SSL` (default: *FALSE*): Set to TRUE if the SMTP server requires SSL to be enabled. This will be unset if `SMTP_USE_TLS` is `TRUE`.
* `EMAIL_FROM_ADDRESS` (default: *admin@`EMAIL_DOMAIN`*): The FROM email address used when sending out emails. The default domain is taken from `EMAIL_DOMAIN` under **User account settings**.
* `EMAIL_FROM_NAME` (default: *`SITE_NAME`*): The FROM name used when sending out emails. The default name is taken from `SITE_NAME` under **Organisation settings**.
* `MAIL_SUBJECT` (default: *Your $ORGANISATION_NAME account has been created.*): The mail subject for new account emails.
* `NEW_ACCOUNT_EMAIL_SUBJECT`, `NEW_ACCOUNT_EMAIL_BODY`, `RESET_PASSWORD_EMAIL_SUBJECT` & `RESET_PASSWORD_EMAIL_BODY`: Change the email contents for emails sent to users when you create an account or reset a password. See [Sending emails](#sending_emails) for full details.
**Account requests**
#### Account request settings
* `ACCOUNT_REQUESTS_ENABLED` (default: *FALSE*): Set to TRUE in order to enable a form that people can fill in to request an account. This will send an email to `ACCOUNT_REQUESTS_EMAIL` with their details and a link to the account creation page where the details will be filled in automatically. You'll need to set up email sending (see **Email sending**, above) for this to work. If this is enabled but email sending isn't then requests will be disabled and an error message sent to the logs.
* `ACCOUNT_REQUESTS_EMAIL` (default: *`EMAIL_FROM_ADDRESS`*): This is the email address that any requests for a new account are sent to.
* `ACCOUNT_REQUESTS_ENABLED` (default: *FALSE*): Set to TRUE in order to enable a form that people can fill in to request an account. This will send an email to `ACCOUNT_REQUESTS_EMAIL` with their details and a link to the account creation page where the details will be filled in automatically. You'll need to set up email sending (see **Email sending**, above) for this to work. If this is enabled but email sending isn't then requests will be disabled and an error message sent to the logs.
* `ACCOUNT_REQUESTS_EMAIL` (default: *{EMAIL_FROM_ADDRESS}*): This is the email address that any requests for a new account are sent to.
**Site security settings**
#### Website security
@ -237,6 +248,26 @@ If you haven't passed in those settings or if the account you've created has no
When the account is created you'll be told if the email was sent or not but be aware that just because your SMTP server accepted the email it doesn't mean that it was able to deliver it. If you get a message saying the email wasn't sent then check the logs for the error. You can increase the log level (`SMTP_LOG_LEVEL`) to above 0 in order to see SMTP debug logs.
You can set the email subject and text for new account and password reset emails via the `NEW_ACCOUNT_EMAIL_SUBJECT`, `NEW_ACCOUNT_EMAIL_BODY`, `RESET_PASSWORD_EMAIL_SUBJECT` and `RESET_PASSWORD_EMAIL_BODY` variables. These variables are parsed before sending and the following macros will be replaced with the relevant information:
* `{password}` : the new password for the account
* `{login}` : the user's login (the value of the attribute defined by `LDAP_ACCOUNT_ATTRIBUTE`. See [Account names](#account-names) for more information.
* `{first_name}` : the user's first name
* `{last_name}` : the user's surname
* `{organisation}` : the value set by `ORGANISATION_NAME`
* `{site_url}` : a link to the user manager site using the values set by `SERVER_HOSTNAME/SERVER_PATH`
* `{change_password_url}` : a link to the self-service password change page `SERVER_HOSTNAME/SERVER_PATH/change_password`
The email body should be in HTML. As an example, the default email subject on creating a new account is `Your {organisation} account has been created.` and the email body is
```
You've been set up with an account for {organisation}. Your credentials are:
<p>
Login: {login}<br>
Password: {password}
<p>
You should log into {change_password_url} and change the password as soon as possible.
```
***
## Username format
@ -245,10 +276,10 @@ When entering a person's name the system username is automatically filled-in bas
The default is `{first_name}-{last_name}` with which *Jonathan Testperson*'s username would be *jonathan-testperson*.
Currently the available macros are:
* `{first_name}` : the first name in lowercase
* `{first_name_initial}` : the first letter of the first name in lowercase
* `{last_name}`: the last name in lowercase
* `{last_name_initial}`: the first initial of the last name in lowercase
* `{first_name}` : the first name in lowercase
* `{first_name_initial}` : the first letter of the first name in lowercase
* `{last_name}`: the last name in lowercase
* `{last_name_initial}`: the first initial of the last name in lowercase
Anything else in the `USERNAME_FORMAT` string is left unmodified. If `ENFORCE_SAFE_SYSTEM_NAMES` is set then the username is also checked for validity against `USERNAME_REGEX`. This is to ensure that there aren't any characters forbidden when using LDAP to create server or email accounts.

View File

@ -72,7 +72,7 @@ render_js_username_check();
<div class="form-inline" id="new_group_div">
<form action="<?php print "${THIS_MODULE_PATH}"; ?>/show_group.php" method="post">
<input type="hidden" name="new_group">
<button id="show_new_group" class="form-control btn btn-default" type="button" onclick="show_new_group_form();">New group</button>
<span class="badge badge-secondary" style="font-size:1.9rem;"><?php print count($groups);?> group<?php if (count($groups) != 1) { print "s"; }?></span> &nbsp; <button id="show_new_group" class="form-control btn btn-default" type="button" onclick="show_new_group_form();">New group</button>
<input type="text" class="form-control invisible" name="group_name" id="group_name" placeholder="Group name" onkeyup="check_entity_name_validity(document.getElementById('group_name').value,'new_group_div');"><button id="add_group" class="form-control btn btn-primary btn-sm invisible" type="submit">Add</button>
</form>
</div>

View File

@ -51,8 +51,8 @@ $people = ldap_get_user_list($ldap_connection);
?>
<div class="container">
<form action="<?php print "${THIS_MODULE_PATH}"; ?>/new_user.php" method="post">
<button id="add_group" class="btn btn-default" type="submit">New user</button>
<form action="<?php print $THIS_MODULE_PATH; ?>/new_user.php" method="post">
<span class="badge badge-secondary" style="font-size:1.9rem;"><?php print count($people);?> account<?php if (count($people) != 1) { print "s"; }?></span> &nbsp; <button id="add_group" class="btn btn-default" type="submit">New user</button>
</form>
<table class="table table-striped">
<thead>

View File

@ -122,19 +122,12 @@ if (isset($_POST['create_account'])) {
if (isset($send_user_email) and $send_user_email == TRUE) {
$mail_subject = "Your $ORGANISATION_NAME account has been created.";
$mail_body = <<<EoT
You've been set up with an account for $ORGANISATION_NAME. Your credentials are:
Username: $account_identifier
Password: $password
You should change your password as soon as possible. Go to ${SITE_PROTOCOL}${SERVER_HOSTNAME}${SERVER_PATH}change_password and log in using your new credentials. This will take you to a page where you can change your password.
EoT;
include_once "mail_functions.inc.php";
$sent_email = send_email($mail,"$first_name $last_name",$mail_subject,$mail_body);
$mail_body = parse_mail_text($new_account_mail_body, $password, $account_identifier, $givenname, $sn);
$mail_subject = parse_mail_text($new_account_mail_subject, $password, $account_identifier, $givenname, $sn);
$sent_email = send_email($mail,"$givenname $sn",$mail_subject,$mail_body);
$creation_message = "The account was created";
if ($sent_email) {
$creation_message .= " and an email sent to $mail.";
@ -152,6 +145,10 @@ EoT;
</div>
<?php
}
#Tidy up empty uniquemember entries left over from the setup wizard
$USER_ID="tmp_admin";
ldap_delete_member_from_group($ldap_connection, $LDAP['admins_group'], "");
if (isset($DEFAULT_USER_GROUP)) { ldap_delete_member_from_group($ldap_connection, $DEFAULT_USER_GROUP, ""); }
}
?>

View File

@ -37,16 +37,30 @@ render_footer();
exit(0);
}
if (isset($_POST['new_group'])) {
$group_add = ldap_new_group($ldap_connection,$group_cn);
}
######################################################################################
if (isset($_POST['new_group'])) {
$new_group = TRUE;
$current_members = array();
$full_dn = "Add members to create the new group";
$has_been = "";
}
elseif (isset($_POST['initialise_group'])) {
$new_group = FALSE;
$initialise_group = TRUE;
$current_members = array();
$full_dn = "cn=$group_cn,${LDAP['group_dn']}";
$has_been = "created";
}
else {
$new_group = FALSE;
$current_members = ldap_get_group_members($ldap_connection,$group_cn);
$full_dn = ldap_get_dn_of_group($ldap_connection,$group_cn);
$has_been = "updated";
}
$current_members = ldap_get_group_members($ldap_connection,$group_cn);
$full_dn = ldap_get_dn_of_group($ldap_connection,$group_cn);
$all_accounts = ldap_get_user_list($ldap_connection);
$all_people = array();
@ -68,12 +82,23 @@ if (isset($_POST["update_members"])) {
}
if ($group_cn == $LDAP['admins_group'] and !array_search($USER_ID, $updated_membership)){
array_push($updated_membership,$USER_ID);
array_push($updated_membership,$USER_ID);
}
$members_to_del = array_diff($current_members,$updated_membership);
$members_to_add = array_diff($updated_membership,$current_members);
if ($initialise_group == TRUE) {
if ($LDAP['rfc2307bis_check_run'] != TRUE) { $rfc2307bis_available = ldap_detect_rfc2307bis($ldap_connection); }
if ($rfc2307bis_available == TRUE) {
$initial_member = array_shift($members_to_add);
}
else {
$initial_member = "";
}
$group_add = ldap_new_group($ldap_connection,$group_cn,$initial_member);
}
foreach ($members_to_del as $this_member) {
ldap_delete_member_from_group($ldap_connection,$group_cn,$this_member);
}
@ -92,7 +117,7 @@ if (isset($_POST["update_members"])) {
</script>
<div class="alert alert-success" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="TRUE">&times;</span></button>
<p class="text-center">The group has been updated.</p>
<p class="text-center">The group has been <?php print $has_been; ?>.</p>
</div>
<?php
@ -263,6 +288,7 @@ ldap_close($ldap_connection);
<form id="group_members" action="<?php print $CURRENT_PAGE; ?>" method="post">
<input type="hidden" name="update_members">
<input type="hidden" name="group_name" value="<?php print urlencode($group_cn); ?>">
<?php if ($new_group == TRUE) { ?><input type="hidden" name="initialise_group"><?php } ?>
</form>
<button id="submit_members" class="btn btn-info" disabled type="submit" onclick="update_form_with_users()">Save</button>
</div>

View File

@ -107,18 +107,11 @@ if ($ldap_search) {
$sent_email_message="";
if ($updated_account and isset($mail) and $can_send_email == TRUE and isset($_POST['send_email'])) {
$mail_subject = "Your $ORGANISATION_NAME password has been reset.";
$mail_body = <<<EoT
Your password for $ORGANISATION_NAME has been reset. Your new credentials are:
Username: $account_identifier
Password: $password
You should change your password as soon as possible. Go to ${SITE_PROTOCOL}${SERVER_HOSTNAME}${SERVER_PATH}change_password and log in using your new credentials. This will take you to a page where you can change your password.
EoT;
include_once "mail_functions.inc.php";
$mail_body = parse_mail_text($new_account_mail_body, $password, $account_identifier, $givenname, $sn);
$mail_subject = parse_mail_text($new_account_mail_subject, $password, $account_identifier, $givenname, $sn);
$sent_email = send_email($mail,"$givenname $sn",$mail_subject,$mail_body);
if ($sent_email) {
$sent_email_message .= " An email sent to $mail.";

View File

@ -74,7 +74,9 @@
$SMTP['user'] = (getenv('SMTP_USERNAME') ? getenv('SMTP_USERNAME') : NULL);
$SMTP['pass'] = (getenv('SMTP_PASSWORD') ? getenv('SMTP_PASSWORD') : NULL);
$SMTP['port'] = (getenv('SMTP_HOST_PORT') ? getenv('SMTP_HOST_PORT') : 25);
$SMTP['ssl'] = ((strcasecmp(getenv('SMTP_USE_SSL'),'TRUE') == 0) ? TRUE : FALSE);
$SMTP['tls'] = ((strcasecmp(getenv('SMTP_USE_TLS'),'TRUE') == 0) ? TRUE : FALSE);
if ($SMTP['tls'] == TRUE) { $SMTP['ssl'] = FALSE; }
$SMTP['debug_level'] = getenv('SMTP_LOG_LEVEL');
if (!is_numeric($SMTP['debug_level']) or $SMTP['debug_level'] >4 or $SMTP['debug_level'] <0) { $SMTP['debug_level'] = 0; }
@ -88,7 +90,6 @@
if ($SMTP['host'] != "") { $EMAIL_SENDING_ENABLED = TRUE; } else { $EMAIL_SENDING_ENABLED = FALSE; }
###
$ACCOUNT_REQUESTS_ENABLED = ((strcasecmp(getenv('ACCOUNT_REQUESTS_ENABLED'),'TRUE') == 0) ? TRUE : FALSE);

View File

@ -415,7 +415,7 @@ function ldap_get_group_list($ldap_connection,$start=0,$entries=NULL,$sort="asc"
$ldap_search = @ ldap_search($ldap_connection, "${LDAP['group_dn']}", $this_filter);
$result = @ ldap_get_entries($ldap_connection, $ldap_search);
if ($LDAP_DEBUG == TRUE) { error_log("$log_prefix: LDAP returned ${result['count']} groups for ${LDAP['group_dn']} when using this filter: $this_filter",0); }
if ($LDAP_DEBUG == TRUE) { error_log("$log_prefix LDAP returned ${result['count']} groups for ${LDAP['group_dn']} when using this filter: $this_filter",0); }
$records = array();
foreach ($result as $record) {
@ -481,7 +481,7 @@ function ldap_get_group_members($ldap_connection,$group_name,$start=0,$entries=N
if ($key !== 'count' and !empty($value)) {
$this_member = preg_replace("/^.*?=(.*?),.*/", "$1", $value);
array_push($records, $this_member);
if ($LDAP_DEBUG == TRUE) { error_log("$log_prefix: ${value} is a member",0); }
if ($LDAP_DEBUG == TRUE) { error_log("$log_prefix ${value} is a member",0); }
}
}
@ -567,7 +567,7 @@ function ldap_user_group_membership($ldap_connection,$username) {
##################################
function ldap_new_group($ldap_connection,$group_name) {
function ldap_new_group($ldap_connection,$group_name,$initial_member="") {
global $log_prefix, $LDAP, $LDAP_DEBUG;
@ -575,7 +575,10 @@ function ldap_new_group($ldap_connection,$group_name) {
if (isset($group_name)) {
$ldap_search_query = "(cn=" . ldap_escape($group_name, "", LDAP_ESCAPE_FILTER) . ",${LDAP['group_dn']})";
$new_group = ldap_escape($group_name, "", LDAP_ESCAPE_FILTER);
$initial_member = ldap_escape($initial_member, "", LDAP_ESCAPE_FILTER);
$ldap_search_query = "(cn=$new_group,${LDAP['group_dn']})";
$ldap_search = @ ldap_search($ldap_connection, "${LDAP['group_dn']}", $ldap_search_query);
$result = @ ldap_get_entries($ldap_connection, $ldap_search);
@ -586,25 +589,26 @@ function ldap_new_group($ldap_connection,$group_name) {
if ($rfc2307bis_available == FALSE) {
$new_group_array=array( 'objectClass' => array('top','posixGroup'),
'cn' => $group_name,
'cn' => $new_group,
'gidNumber' => $new_gid
);
}
else {
if ($LDAP['group_membership_uses_uid'] == FALSE) { $initial_member = "${LDAP['account_attribute']}=$initial_member,${LDAP['user_dn']}"; }
$new_group_array=array( 'objectClass' => array('top','groupOfUniqueNames','posixGroup'),
'cn' => $group_name,
'cn' => $new_group,
'gidNumber' => $new_gid,
$LDAP['group_membership_attribute'] => ''
$LDAP['group_membership_attribute'] => $initial_member
);
}
$group_dn="cn=$group_name,${LDAP['group_dn']}";
$group_dn="cn=$new_group,${LDAP['group_dn']}";
$add_group = @ ldap_add($ldap_connection, $group_dn, $new_group_array);
if (! $add_group ) {
$this_error="$log_prefix LDAP: unable to add new group (${group_dn}): " . ldap_error($ldap_connection);
if ($LDAP_DEBUG == TRUE) { error_log("$log_prefix: DEBUG add_group array: ". print_r($new_group_array,true),0); }
if ($LDAP_DEBUG == TRUE) { error_log("$log_prefix DEBUG add_group array: ". print_r($new_group_array,true),0); }
error_log($this_error,0);
}
else {
@ -901,7 +905,7 @@ function ldap_delete_member_from_group($ldap_connection,$group_name,$username) {
$group_dn = "cn=" . ldap_escape($group_name, "", LDAP_ESCAPE_FILTER) . ",${LDAP['group_dn']}";
if ($LDAP['group_membership_uses_uid'] == FALSE) {
if ($LDAP['group_membership_uses_uid'] == FALSE and $username != "") {
$username = "${LDAP['account_attribute']}=$username,${LDAP['user_dn']}";
}
@ -909,11 +913,11 @@ function ldap_delete_member_from_group($ldap_connection,$group_name,$username) {
$update = @ ldap_mod_del($ldap_connection,$group_dn,$group_update);
if ($update) {
error_log("$log_prefix Removed $username from $group_name",0);
error_log("$log_prefix Removed '$username' from $group_name",0);
return TRUE;
}
else {
error_log("$log_prefix Couldn't remove $username from ${group_name}: " . ldap_error($ldap_connection),0);
error_log("$log_prefix Couldn't remove '$username' from ${group_name}: " . ldap_error($ldap_connection),0);
return FALSE;
}
}

View File

@ -4,11 +4,49 @@ require_once "/opt/PHPMailer/src/PHPMailer.php";
require_once "/opt/PHPMailer/src/SMTP.php";
require_once "/opt/PHPMailer/src/Exception.php";
#Default email text
$new_account_mail_subject = (getenv('NEW_ACCOUNT_EMAIL_SUBJECT') ? getenv('NEW_ACCOUNT_EMAIL_SUBJECT') : "Your {organisation} account has been created.");
$new_account_mail_body = getenv('NEW_ACCOUNT_EMAIL_BODY') ?: <<<EoNA
You've been set up with an account for {organisation}. Your credentials are:
<p>
Login: {login}<br>
Password: {password}
<p>
You should log into <a href="{change_password_url}">{change_password_url}</a> and change the password as soon as possible.
EoNA;
$reset_password_mail_subject = (getenv('RESET_PASSWORD_EMAIL_SUBJECT') ? getenv('RESET_PASSWORD_EMAIL_SUBJECT') : "Your {organisation} password has been reset.");
$reset_password_mail_body = getenv('RESET_PASSWORD_EMAIL_BODY') ?: <<<EoRP
Your password for {organisation} has been reset. Your new password is {password}
<p>
You should log into <a href="{change_password_url}">{change_password_url}</a> and change this password as soon as possible.
EoRP;
function parse_mail_text($template,$password,$login,$first_name,$last_name) {
global $ORGANISATION_NAME, $SITE_PROTOCOL, $SERVER_HOSTNAME, $SERVER_PATH;
$template = str_replace("{password}", $password, $template);
$template = str_replace("{login}", $login, $template);
$template = str_replace("{first_name}", $first_name, $template);
$template = str_replace("{last_name}", $last_name, $template);
$template = str_replace("{organisation}", $ORGANISATION_NAME, $template);
$template = str_replace("{site_url}", "${SITE_PROTOCOL}${SERVER_HOSTNAME}${SERVER_PATH}", $template);
$template = str_replace("{change_password_url}", "${SITE_PROTOCOL}${SERVER_HOSTNAME}${SERVER_PATH}change_password", $template);
return $template;
}
function send_email($recipient_email,$recipient_name,$subject,$body) {
global $EMAIL, $SMTP, $log_prefix;
$mail = new PHPMailer\PHPMailer\PHPMailer();
$mail->CharSet = 'UTF-8';
$mail->isSMTP();
$mail->SMTPDebug = $SMTP['debug_level'];
@ -23,12 +61,14 @@ function send_email($recipient_email,$recipient_name,$subject,$body) {
$mail->Password = $SMTP['pass'];
}
if ($EMAIL['tls'] == TRUE) { $mail->SMTPSecure = "tls"; }
if ($SMTP['tls'] == TRUE) { $mail->SMTPSecure = 'tls'; }
if ($SMTP['ssl'] == TRUE) { $mail->SMTPSecure = 'ssl'; }
$mail->setFrom($EMAIL['from_address'], $EMAIL['from_name']);
$mail->addAddress($recipient_email, $recipient_name);
$mail->Subject = $subject;
$mail->Body = $body;
$mail->IsHTML(true);
if (!$mail->Send()) {
error_log("$log_prefix SMTP: Unable to send email: " . $mail->ErrorInfo);

View File

@ -72,14 +72,13 @@ if (!isset($notes)) { $notes = "n/a"; }
$mail_body = <<<EoT
A request for an $ORGANISATION_NAME account has been sent:
First name: $firstname
Last name: $lastname
Email: $email
Notes: $notes
You can create the account at $link_url
<p>
First name: <b>$firstname</b><br>
Last name: <b>$lastname</b><br>
Email: <b>$email</b><br>
Notes: <pre>$notes</pre><br>
<p>
<a href="$link_url">Create this account.</a>
EoT;
include_once "mail_functions.inc.php";