Commit 0bd1bf07 authored by Guus der Kinderen's avatar Guus der Kinderen Committed by daryl herzmann

OF-1457: Add auto-expiry option to registration plugin. (#985)

An option has been added to the registration plugin that allows an administrator to configure
that all newly created user accounts will be locked out automatically after a certain amount
of time has passed.

Shoutout to @jadestorm for having the foresight in 2008, making this possible. :)
parent 1de1685c
...@@ -44,6 +44,11 @@ ...@@ -44,6 +44,11 @@
Registration Plugin Changelog Registration Plugin Changelog
</h1> </h1>
<p><b>1.7.2</b> -- December 19, 2017</p>
<ul>
<li>[<a href='https://issues.igniterealtime.org/browse/OF-1457'>OF-1457</a>] - Add optional automatic account expiry.</li>
</ul>
<p><b>1.7.1</b> -- July 11, 2017</p> <p><b>1.7.1</b> -- July 11, 2017</p>
<ul> <ul>
<li>[<a href='https://issues.igniterealtime.org/browse/OF-1364'>OF-1364</a>] - Add default Privacy List for new users.</li> <li>[<a href='https://issues.igniterealtime.org/browse/OF-1364'>OF-1364</a>] - Add default Privacy List for new users.</li>
......
...@@ -5,8 +5,8 @@ ...@@ -5,8 +5,8 @@
<name>Registration</name> <name>Registration</name>
<description>Performs various actions whenever a new user account is created.</description> <description>Performs various actions whenever a new user account is created.</description>
<author>Ryan Graham</author> <author>Ryan Graham</author>
<version>1.7.1</version> <version>1.7.2</version>
<date>07/11/2017</date> <date>12/19/2017</date>
<minServerVersion>4.0.0</minServerVersion> <minServerVersion>4.0.0</minServerVersion>
<adminconsole> <adminconsole>
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
<groupId>org.igniterealtime.openfire.plugins</groupId> <groupId>org.igniterealtime.openfire.plugins</groupId>
<artifactId>registration</artifactId> <artifactId>registration</artifactId>
<name>Registration Plugin</name> <name>Registration Plugin</name>
<version>1.7.1</version> <version>1.7.2</version>
<build> <build>
<sourceDirectory>src/java</sourceDirectory> <sourceDirectory>src/java</sourceDirectory>
......
...@@ -61,8 +61,9 @@ The registration plugin is configured via the "Registration Properties" sidebar ...@@ -61,8 +61,9 @@ The registration plugin is configured via the "Registration Properties" sidebar
"Users" sidebar item under the "Users/Groups" tab in the Openfire Admin Console. By default, "Users" sidebar item under the "Users/Groups" tab in the Openfire Admin Console. By default,
after the registration plugin has been deployed all of its features are disabled. To enable a feature after the registration plugin has been deployed all of its features are disabled. To enable a feature
of the plugin select the checkbox next to the feature and then click on the "Save Settings" button. of the plugin select the checkbox next to the feature and then click on the "Save Settings" button.
The registration plugin has three items that can be configured: The registration plugin has various items that can be configured:
</p> </p>
<li>Account expiry - Disables new accounts after a certain amount of time has passed.</li>
<li>Registration Notification - Contacts can be configured to receive an instant message and/or email to <li>Registration Notification - Contacts can be configured to receive an instant message and/or email to
notify them whenever a new user registers.</li> notify them whenever a new user registers.</li>
<li>Welcome Message - A message that will be sent to a user when they first register.</li> <li>Welcome Message - A message that will be sent to a user when they first register.</li>
......
...@@ -6,6 +6,7 @@ registration.props.form.registration_settings=Registration Settings ...@@ -6,6 +6,7 @@ registration.props.form.registration_settings=Registration Settings
registration.props.form.enable_features=Enable registration features using the checkboxes below. registration.props.form.enable_features=Enable registration features using the checkboxes below.
registration.props.form.save_success=Settings saved successfully. registration.props.form.save_success=Settings saved successfully.
registration.props.form.invalid_group=Please enter and save a valid group name in the Default Group section at the bottom of this page before enabling automatic group adding. registration.props.form.invalid_group=Please enter and save a valid group name in the Default Group section at the bottom of this page before enabling automatic group adding.
registration.props.form.invalid_autoexpirycustom=Please enter a valid numeric value as the amount of minutes after which automatic account lockout should occur.
registration.props.form.enable_im_notification=Enable instant message registration notification. registration.props.form.enable_im_notification=Enable instant message registration notification.
registration.props.form.enable_email_notification=Enable email registration notification. registration.props.form.enable_email_notification=Enable email registration notification.
registration.props.form.enable_welcome_msg=Enable welcome message. registration.props.form.enable_welcome_msg=Enable welcome message.
...@@ -16,6 +17,14 @@ registration.props.form.enable_recaptcha=Enable reCAPTCHA human check for web pa ...@@ -16,6 +17,14 @@ registration.props.form.enable_recaptcha=Enable reCAPTCHA human check for web pa
registration.props.form.recaptcha_noscript=Enable reCAPTCHA NoScript section for a better compatibility. registration.props.form.recaptcha_noscript=Enable reCAPTCHA NoScript section for a better compatibility.
registration.props.form.recaptcha_public_key=Public key for reCAPTCHA: registration.props.form.recaptcha_public_key=Public key for reCAPTCHA:
registration.props.form.recaptcha_private_key=Private key for reCAPTCHA: registration.props.form.recaptcha_private_key=Private key for reCAPTCHA:
registration.props.form.auto_expiry_caption=Automatically lock out new accounts:
registration.props.form.auto_expiry_disabled=never.
registration.props.form.auto_expiry_1minute=after one minute.
registration.props.form.auto_expiry_1hour=after one hour.
registration.props.form.auto_expiry_1day=after one day.
registration.props.form.auto_expiry_1week=after one week.
registration.props.form.auto_expiry_custom=after
registration.props.form.auto_expiry_minutes=minutes.
registration.props.form.save_settings=Save Settings registration.props.form.save_settings=Save Settings
registration.props.form.registration_contacts=Registration Notification Contacts registration.props.form.registration_contacts=Registration Notification Contacts
registration.props.form.registration_contacts_details=Add or remove contacts to be alerted when a new user registers. registration.props.form.registration_contacts_details=Add or remove contacts to be alerted when a new user registers.
......
...@@ -17,13 +17,7 @@ ...@@ -17,13 +17,7 @@
package org.jivesoftware.openfire.plugin; package org.jivesoftware.openfire.plugin;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.*;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.dom4j.Document; import org.dom4j.Document;
import org.dom4j.DocumentHelper; import org.dom4j.DocumentHelper;
...@@ -39,6 +33,7 @@ import org.jivesoftware.openfire.event.UserEventListener; ...@@ -39,6 +33,7 @@ import org.jivesoftware.openfire.event.UserEventListener;
import org.jivesoftware.openfire.group.Group; import org.jivesoftware.openfire.group.Group;
import org.jivesoftware.openfire.group.GroupManager; import org.jivesoftware.openfire.group.GroupManager;
import org.jivesoftware.openfire.group.GroupNotFoundException; import org.jivesoftware.openfire.group.GroupNotFoundException;
import org.jivesoftware.openfire.lockout.LockOutManager;
import org.jivesoftware.openfire.user.User; import org.jivesoftware.openfire.user.User;
import org.jivesoftware.openfire.privacy.PrivacyList; import org.jivesoftware.openfire.privacy.PrivacyList;
import org.jivesoftware.openfire.privacy.PrivacyListManager; import org.jivesoftware.openfire.privacy.PrivacyListManager;
...@@ -152,7 +147,14 @@ public class RegistrationPlugin implements Plugin { ...@@ -152,7 +147,14 @@ public class RegistrationPlugin implements Plugin {
* privacy list, if the property #PRIVACYLIST_ENABLED is set to true. * privacy list, if the property #PRIVACYLIST_ENABLED is set to true.
*/ */
private static final String REGISTRAION_PRIVACYLIST_NAME = "registration.privacylist.name"; private static final String REGISTRAION_PRIVACYLIST_NAME = "registration.privacylist.name";
/**
* The expected value is a numeric (long) value that defines the number of seconds after which
* a newly created User will be automatically locked out. A non-positive value (zero or less) will
* disable this feature (it is disabled by default).
*/
private static final String REGISTRATION_AUTO_LOCKOUT = "registration.automatic.lockout.seconds";
/** /**
* The expected value is a String that contains the text that will be displayed in the header * The expected value is a String that contains the text that will be displayed in the header
* of the sign-up.jsp, if the property #WEB_ENABLED is set to true. * of the sign-up.jsp, if the property #WEB_ENABLED is set to true.
...@@ -364,7 +366,21 @@ public class RegistrationPlugin implements Plugin { ...@@ -364,7 +366,21 @@ public class RegistrationPlugin implements Plugin {
public String getPrivacyListName() { public String getPrivacyListName() {
return JiveGlobals.getProperty(REGISTRAION_PRIVACYLIST_NAME); return JiveGlobals.getProperty(REGISTRAION_PRIVACYLIST_NAME);
} }
public boolean isAutomaticAccountLockoutEnabled()
{
return getAutomaticAccountLockoutAfter() > 0;
}
public void setAutomaticAccountLockoutAfter( long seconds )
{
JiveGlobals.setProperty( REGISTRATION_AUTO_LOCKOUT, Long.toString( seconds ) );
}
public long getAutomaticAccountLockoutAfter()
{
return JiveGlobals.getLongProperty( REGISTRATION_AUTO_LOCKOUT, -1 );
}
public void setHeader(String message) { public void setHeader(String message) {
JiveGlobals.setProperty(HEADER, message); JiveGlobals.setProperty(HEADER, message);
} }
...@@ -399,6 +415,11 @@ public class RegistrationPlugin implements Plugin { ...@@ -399,6 +415,11 @@ public class RegistrationPlugin implements Plugin {
if (privacyListEnabled()) { if (privacyListEnabled()) {
addDefaultPrivacyList(user); addDefaultPrivacyList(user);
} }
if (isAutomaticAccountLockoutEnabled())
{
addAutomaticAccountLockout(user);
}
} }
public void userDeleting(User user, Map<String, Object> params) { public void userDeleting(User user, Map<String, Object> params) {
...@@ -486,6 +507,12 @@ public class RegistrationPlugin implements Plugin { ...@@ -486,6 +507,12 @@ public class RegistrationPlugin implements Plugin {
privacyListManager.changeDefaultList(user.getUsername(), newPrivacyList, null); privacyListManager.changeDefaultList(user.getUsername(), newPrivacyList, null);
} }
} }
private void addAutomaticAccountLockout(User user)
{
final long start = System.currentTimeMillis() + ( getAutomaticAccountLockoutAfter() * 1000 );
LockOutManager.getInstance().disableAccount( user.getUsername(), new Date( start ), null );
}
} }
private String propPrep(Collection<String> props) { private String propPrep(Collection<String> props) {
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
<%@ page <%@ page
import="java.util.*, import="java.util.*,
org.jivesoftware.admin.*,
org.jivesoftware.openfire.XMPPServer, org.jivesoftware.openfire.XMPPServer,
org.jivesoftware.openfire.user.*, org.jivesoftware.openfire.user.*,
org.jivesoftware.openfire.plugin.RegistrationPlugin, org.jivesoftware.openfire.plugin.RegistrationPlugin,
...@@ -24,6 +23,7 @@ ...@@ -24,6 +23,7 @@
org.jivesoftware.util.*" org.jivesoftware.util.*"
errorPage="error.jsp"%> errorPage="error.jsp"%>
<%@ page import="org.xmpp.packet.JID" %> <%@ page import="org.xmpp.packet.JID" %>
<%@ page import="org.jivesoftware.openfire.lockout.LockOutManager" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
...@@ -46,6 +46,9 @@ ...@@ -46,6 +46,9 @@
String reCaptchaPublicKey = ParamUtils.getParameter(request, "recaptchapublickey"); String reCaptchaPublicKey = ParamUtils.getParameter(request, "recaptchapublickey");
String reCaptchaPrivateKey = ParamUtils.getParameter(request, "recaptchaprivatekey"); String reCaptchaPrivateKey = ParamUtils.getParameter(request, "recaptchaprivatekey");
long autoExpiry = ParamUtils.getLongParameter( request, "autoexpiry", -1 );
String autoExpiryCustom = ParamUtils.getParameter( request, "autoexpiry_custom" );
String contactIM = ParamUtils.getParameter(request, "contactIM"); String contactIM = ParamUtils.getParameter(request, "contactIM");
boolean addIM = ParamUtils.getBooleanParameter(request, "addIM"); boolean addIM = ParamUtils.getBooleanParameter(request, "addIM");
boolean deleteIM = ParamUtils.getBooleanParameter(request, "deleteIM"); boolean deleteIM = ParamUtils.getBooleanParameter(request, "deleteIM");
...@@ -131,6 +134,19 @@ ...@@ -131,6 +134,19 @@
plugin.setReCaptchaPublicKey(reCaptchaPublicKey); plugin.setReCaptchaPublicKey(reCaptchaPublicKey);
plugin.setReCaptchaPrivateKey(reCaptchaPrivateKey); plugin.setReCaptchaPrivateKey(reCaptchaPrivateKey);
plugin.setPrivacyListEnabled(privacyListEnabled); plugin.setPrivacyListEnabled(privacyListEnabled);
if (autoExpiry == -2 )
{
try
{
autoExpiry = Long.parseLong( autoExpiryCustom ) * 60;
}
catch ( NumberFormatException e )
{
errors.put("autoexpirycustom", "autoexpirycustom");
}
}
plugin.setAutomaticAccountLockoutAfter( autoExpiry );
if (groupEnabled) { if (groupEnabled) {
group = plugin.getGroup(); group = plugin.getGroup();
...@@ -227,6 +243,7 @@ ...@@ -227,6 +243,7 @@
reCaptchaNoScript = plugin.reCaptchaNoScript(); reCaptchaNoScript = plugin.reCaptchaNoScript();
reCaptchaPublicKey = plugin.getReCaptchaPublicKey(); reCaptchaPublicKey = plugin.getReCaptchaPublicKey();
reCaptchaPrivateKey = plugin.getReCaptchaPrivateKey(); reCaptchaPrivateKey = plugin.getReCaptchaPrivateKey();
autoExpiry = plugin.getAutomaticAccountLockoutAfter();
%> %>
<html> <html>
...@@ -287,7 +304,22 @@ function addEmailContact() { ...@@ -287,7 +304,22 @@ function addEmailContact() {
</div> </div>
<% } %> <% } %>
<% if (errors.containsKey("autoexpirycustom")) { %>
<div class="jive-error">
<table cellpadding="0" cellspacing="0" border="0">
<tbody>
<tr>
<td class="jive-icon"><img src="images/error-16x16.gif" width="16" height="16" border="0"></td>
<td class="jive-icon-label"><fmt:message key="registration.props.form.invalid_autoexpirycustom" /></td>
</tr>
</tbody>
</table>
</div>
<% } %>
<table cellpadding="3" cellspacing="0" border="0" width="100%"> <table cellpadding="3" cellspacing="0" border="0" width="100%">
<tbody> <tbody>
<tr> <tr>
...@@ -332,6 +364,40 @@ function addEmailContact() { ...@@ -332,6 +364,40 @@ function addEmailContact() {
<td width="24%" align="left"><fmt:message key="registration.props.form.recaptcha_private_key" /></td> <td width="24%" align="left"><fmt:message key="registration.props.form.recaptcha_private_key" /></td>
<td width="75%" align="left"><input type="text" name="recaptchaprivatekey" size="40" maxlength="100" value="<%= (reCaptchaPrivateKey != null ? reCaptchaPrivateKey : "") %>"/></td> <td width="75%" align="left"><input type="text" name="recaptchaprivatekey" size="40" maxlength="100" value="<%= (reCaptchaPrivateKey != null ? reCaptchaPrivateKey : "") %>"/></td>
</tr> </tr>
<% if ( LockOutManager.getLockOutProvider().isDelayedStartSupported()) { %>
<tr>
<td width="100%" colspan="3">&nbsp;</td>
</tr>
<tr>
<td width="100%" align="left" colspan="3"><fmt:message key="registration.props.form.auto_expiry_caption" /></td>
</tr>
<tr>
<td width="1%" align="center" nowrap><input type="radio" name="autoexpiry" id="autoexpirydisabled" value="-1" <%= autoExpiry == -1 ? "checked" : "" %>/></td>
<td width="99%" align="left" colspan="2"><label for="autoexpirydisabled"><fmt:message key="registration.props.form.auto_expiry_disabled" /></label></td>
</tr>
<tr>
<td width="1%" align="center" nowrap><input type="radio" name="autoexpiry" id="autoexpiry1minute" value="60" <%= autoExpiry == 60 ? "checked" : "" %>/></td>
<td width="99%" align="left" colspan="2"><label for="autoexpiry1minute"><fmt:message key="registration.props.form.auto_expiry_1minute" /></label></td>
</tr>
<tr>
<td width="1%" align="center" nowrap><input type="radio" name="autoexpiry" id="autoexpiry1hour" value="3600" <%= autoExpiry == 3600 ? "checked" : "" %>/></td>
<td width="99%" align="left" colspan="2"><label for="autoexpiry1hour"><fmt:message key="registration.props.form.auto_expiry_1hour" /></label></td>
</tr>
<tr>
<td width="1%" align="center" nowrap><input type="radio" name="autoexpiry" id="autoexpiry1day" value="86400" <%= autoExpiry == 86400 ? "checked" : "" %>/></td>
<td width="99%" align="left" colspan="2"><label for="autoexpiry1day"><fmt:message key="registration.props.form.auto_expiry_1day" /></label></td>
</tr>
<tr>
<td width="1%" align="center" nowrap><input type="radio" name="autoexpiry" id="autoexpiry1week" value="604800" <%= autoExpiry == 604800 ? "checked" : "" %>/></td>
<td width="99%" align="left" colspan="2"><label for="autoexpiry1week"><fmt:message key="registration.props.form.auto_expiry_1week" /></label></td>
</tr>
<tr>
<td width="1%" align="center" nowrap><input type="radio" name="autoexpiry" id="autoexpiry_custom" value="-2" <%= autoExpiry != -1 && autoExpiry != 60 && autoExpiry != 3600 && autoExpiry != 86400 && autoExpiry != 604800? "checked" : "" %>/></td>
<td width="99%" align="left" colspan="2"><label for="autoexpiry_custom"><fmt:message key="registration.props.form.auto_expiry_custom" /> </label><input type="text" size="5" maxlength="10" name="autoexpiry_custom" value="<%= autoExpiry != -1 && autoExpiry != -2 && autoExpiry != 60 && autoExpiry != 3600 && autoExpiry != 86400 && autoExpiry != 604800 ? autoExpiry / 60 : "" %>"/><label for="autoexpiry_custom"> <fmt:message key="registration.props.form.auto_expiry_minutes" /></label></td>
</tr>
<% } %>
</tbody> </tbody>
</table> </table>
<br> <br>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment