diff --git a/lam/HISTORY b/lam/HISTORY
index cf8e5e9b..2381fb86 100644
--- a/lam/HISTORY
+++ b/lam/HISTORY
@@ -5,6 +5,7 @@ March 2019
- LAM Pro:
-> New self service fields: Mail routing (Local address) and Windows (Proxy-Addresses)
-> Bind DLZ: support DNAME+XFR records and descriptions in records (requires latest LDAP schema)
+ -> Cron jobs: added Shadow account expiration notification jobs
- Fixed bugs:
-> Allow tree-only configurations without any other tab
diff --git a/lam/docs/manual-sources/chapter-configuration.xml b/lam/docs/manual-sources/chapter-configuration.xml
index b0aa378f..974cb3fb 100644
--- a/lam/docs/manual-sources/chapter-configuration.xml
+++ b/lam/docs/manual-sources/chapter-configuration.xml
@@ -969,6 +969,11 @@ mysql> GRANT ALL PRIVILEGES ON lam_cron.* TO 'lam_cron'@'localhost';
move expired accounts
+
+ Shadow:
+ Notify users about account expiration
+
+
Windows: Notify
users about password expiration
@@ -1364,6 +1369,90 @@ mysql> GRANT ALL PRIVILEGES ON lam_cron.* TO 'lam_cron'@'localhost';
+
+ Shadow: Notify users about account expiration
+
+ This will send your users an email reminder before their whole
+ account expires.
+
+ You need to activate the Shadow module for users to be able to
+ add this job. The job can be added multiple times (e.g. to send a
+ second warning at a later time).
+
+
+
+
+
+
+ Options
+
+
+
+
+ Option
+
+ Description
+
+
+
+ From address
+
+ The email address to set as FROM.
+
+
+
+ Reply-to address
+
+ Optional Reply-to address for email.
+
+
+
+ CC address
+
+ Optional CC mail address.
+
+
+
+ BCC address
+
+ Optional BCC mail address.
+
+
+
+ Subject
+
+ The email subject line. Supports wildcards, see
+ below.
+
+
+
+ Text
+
+ The email body text. Supports wildcards, see
+ below.
+
+
+
+ Notification period
+
+ Number of days to notify before account
+ expires.
+
+
+
+
Wildcards:
+
+ You can enter LDAP attributes as wildcards in the form
+ @@ATTRIBUTE_NAME@@. E.g. to add the user's common name use "@@cn@@".
+ For the common name it would be "@@cn@@".
+
+ There are also two special wildcards for the expiration date.
+ @@EXPIRE_DATE_DDMMYYYY@@ will print the date as e.g. "31.12.2016".
+ @@EXPIRE_DATE_YYYYMMDD@@ will print the date as e.g.
+ "2016-12-31".
+
+
Windows: Notify users about password expiration
diff --git a/lam/docs/manual-sources/images/jobs_shadow3.png b/lam/docs/manual-sources/images/jobs_shadow3.png
new file mode 100644
index 00000000..b256f12b
Binary files /dev/null and b/lam/docs/manual-sources/images/jobs_shadow3.png differ
diff --git a/lam/lib/modules/shadowAccount.inc b/lam/lib/modules/shadowAccount.inc
index 939012a7..39aec47b 100644
--- a/lam/lib/modules/shadowAccount.inc
+++ b/lam/lib/modules/shadowAccount.inc
@@ -3,7 +3,7 @@
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
Copyright (C) 2003 - 2006 Tilo Lutz
- Copyright (C) 2007 - 2018 Roland Gruber
+ Copyright (C) 2007 - 2019 Roland Gruber
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
@@ -762,7 +762,8 @@ class shadowAccount extends baseModule implements passwordService {
public function getSupportedJobs(&$config) {
return array(
new ShadowAccountPasswordNotifyJob(),
- new ShadowAccountExpirationCleanupJob()
+ new ShadowAccountExpirationCleanupJob(),
+ new ShadowAccountExpirationNotifyJob()
);
}
@@ -914,6 +915,100 @@ if (interface_exists('\LAM\JOB\Job', false)) {
}
+ /**
+ * Job to notify users about account expiration.
+ *
+ * @package jobs
+ */
+ class ShadowAccountExpirationNotifyJob extends \LAM\JOB\PasswordExpirationJob {
+
+ /**
+ * Returns the alias name of the job.
+ *
+ * @return String name
+ */
+ public function getAlias() {
+ return _('Shadow') . ': ' . _('Notify users about acoount expiration');
+ }
+
+ /**
+ * {@inheritDoc}
+ * @see \LAM\JOB\PasswordExpirationJob::getDescription()
+ */
+ public function getDescription() {
+ return _('This job sends out emails to inform your users that their account will expire soon.');
+ }
+
+ /**
+ * Searches for users in LDAP.
+ *
+ * @param String $jobID unique job identifier
+ * @param array $options config options (name => value)
+ * @return array list of user attributes
+ */
+ protected function findUsers($jobID, $options) {
+ // read users
+ $sysattrs = array('mail', 'shadowExpire');
+ $attrs = $this->getAttrWildcards($jobID, $options);
+ $attrs = array_values(array_unique(array_merge($attrs, $sysattrs)));
+ return searchLDAPByFilter('(&(shadowExpire=*)(mail=*))', $attrs, array('user'));
+ }
+
+ /**
+ * Checks if a user needs to change his password.
+ *
+ * @param integer $jobID job ID
+ * @param array $options job settings
+ * @param PDO $pdo PDO
+ * @param DateTime $now current time
+ * @param array $policyOptions list of max age values (policy DN => maxAge)
+ * @param array $user user attributes
+ * @param boolean $isDryRun just do a dry run, nothing is modified
+ */
+ protected function checkSingleUser($jobID, $options, &$pdo, $now, $policyOptions, $user, $isDryRun) {
+ $dn = $user['dn'];
+ $expireTimeUnix = $user['shadowexpire'][0] * 3600 * 24;
+ $expireTime = new DateTime('@' . $expireTimeUnix, new DateTimeZone('UTC'));
+ $this->jobResultLog->logDebug("Expiration on " . $expireTime->format('Y-m-d'));
+ if ($expireTime <= $now) {
+ $this->jobResultLog->logDebug($dn . ' already expired');
+ return;
+ }
+ $numDaysToWarn = 0;
+ if (!empty($options[$this->getConfigPrefix() . '_mailNotificationPeriod' . $jobID][0])) {
+ $numDaysToWarn = $options[$this->getConfigPrefix() . '_mailNotificationPeriod' . $jobID][0];
+ }
+ $actionTime = clone $expireTime;
+ if ($numDaysToWarn != 0) {
+ $actionTime->sub(new DateInterval('P' . $numDaysToWarn . 'D'));
+ }
+ $actionTime->setTimeZone(getTimeZone());
+ $this->jobResultLog->logDebug("Action time on " . $actionTime->format('Y-m-d'));
+ if ($actionTime > $now) {
+ $this->jobResultLog->logDebug($dn . ' does not need notification yet.');
+ return;
+ }
+ $dbLastChange = $this->getDBLastPwdChangeTime($jobID, $pdo, $user['dn']);
+ // skip entries where mail was already sent
+ if ($dbLastChange == $user['shadowexpire'][0]) {
+ $this->jobResultLog->logDebug($dn . ' was already notified.');
+ return;
+ }
+ if ($isDryRun) {
+ // no action for dry run
+ $this->jobResultLog->logInfo('Not sending email to ' . $dn . ' because of dry run.');
+ return;
+ }
+ // send email
+ $success = $this->sendMail($options, $jobID, $user, $expireTime);
+ // update DB if mail was sent successfully
+ if ($success) {
+ $this->setDBLastPwdChangeTime($jobID, $pdo, $dn, $user['shadowexpire'][0]);
+ }
+ }
+
+ }
+
/**
* Job to delete or move users on account expiration.
*