dhis2-devs team mailing list archive
-
dhis2-devs team
-
Mailing list archive
-
Message #36381
[Branch ~dhis2-devs-core/dhis2/trunk] Rev 18621: Implemented feature for resending user account invitation emails.
------------------------------------------------------------
revno: 18621
committer: Lars Helge Overland <larshelge@xxxxxxxxx>
branch nick: dhis2
timestamp: Wed 2015-03-18 19:51:30 +0100
message:
Implemented feature for resending user account invitation emails.
modified:
dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/DefaultSecurityService.java
dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/SecurityService.java
dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/security/SecurityServiceTest.java
dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/user/UserController.java
dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-user/src/main/resources/org/hisp/dhis/user/i18n_module.properties
dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-user/src/main/webapp/dhis-web-maintenance-user/allUser.vm
dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-user/src/main/webapp/dhis-web-maintenance-user/javascript/user.js
--
lp:dhis2
https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk
Your team DHIS 2 developers is subscribed to branch lp:dhis2.
To unsubscribe from this branch go to https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk/+edit-subscription
=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/DefaultSecurityService.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/DefaultSecurityService.java 2015-02-22 20:02:00 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/DefaultSecurityService.java 2015-03-18 18:51:30 +0000
@@ -28,6 +28,15 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hisp.dhis.acl.AclService;
@@ -51,14 +60,6 @@
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
-
/**
* @author Lars Helge Overland
*/
@@ -68,6 +69,7 @@
private static final Log log = LogFactory.getLog( DefaultSecurityService.class );
private static final String RESTORE_PATH = "/dhis-web-commons/security/";
+ private static final Pattern INVITE_USERNAME_PATTERN = Pattern.compile( "^invite\\-(.+?)\\-(\\w{11})$" );
private static final String DEFAULT_APPLICATION_TITLE = "DHIS 2";
@@ -152,7 +154,7 @@
return true;
}
-
+
@Override
public String validateRestore( UserCredentials credentials )
{
@@ -462,6 +464,17 @@
}
@Override
+ public boolean isInviteUsername( String username )
+ {
+ if ( username == null || username.isEmpty() )
+ {
+ return true;
+ }
+
+ return INVITE_USERNAME_PATTERN.matcher( username ).matches();
+ }
+
+ @Override
public boolean canCreatePublic( IdentifiableObject identifiableObject )
{
return !aclService.isShareable( identifiableObject.getClass() )
=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/SecurityService.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/SecurityService.java 2015-02-13 12:51:17 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/SecurityService.java 2015-03-18 18:51:30 +0000
@@ -157,6 +157,16 @@
String verifyToken( UserCredentials credentials, String token, RestoreType restoreType );
/**
+ * Indicates whether the given username is an invite. The username is
+ * considered an invite if it is null or matches the invite username pattern
+ * of invite-<email>-<uid>.
+ *
+ * @param username the username.
+ * @return true if the username represents an account invitation.
+ */
+ boolean isInviteUsername( String username );
+
+ /**
* Checks whether current user has read access to object.
*
* @param identifiableObject Object to check for read access.
=== modified file 'dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/security/SecurityServiceTest.java'
--- dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/security/SecurityServiceTest.java 2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/security/SecurityServiceTest.java 2015-03-18 18:51:30 +0000
@@ -231,4 +231,15 @@
assertEquals( RestoreType.INVITE, restoreOptions.getRestoreType() );
assertEquals( true, restoreOptions.isUsernameChoice() );
}
+
+ @Test
+ public void testIsInviteUsername()
+ {
+ assertTrue( securityService.isInviteUsername( "invite-johndoe@xxxxxxxxx-OsTci1JyHRU" ) );
+ assertTrue( securityService.isInviteUsername( "invite-fr37@xxxxxxx-OsTci1JyHRU" ) );
+ assertTrue( securityService.isInviteUsername( null ) );
+ assertFalse( securityService.isInviteUsername( "inv1te-mark@xxxxxxxxx-OsTci1JyHRU" ) );
+ assertFalse( securityService.isInviteUsername( "invite-tomjohnson@xxxxxxxxx-OsTci1JyHRUC" ) );
+ assertFalse( securityService.isInviteUsername( "invite-johnthomson@xxxxxxxxx-OsTci1yHRU" ) );
+ }
}
=== modified file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/user/UserController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/user/UserController.java 2015-02-25 06:51:55 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/user/UserController.java 2015-03-18 18:51:30 +0000
@@ -243,6 +243,39 @@
}
}
+ @RequestMapping( value = "/{id}" + INVITE_PATH, method = RequestMethod.POST )
+ public void resendInvite( @PathVariable String id, HttpServletRequest request, HttpServletResponse response ) throws Exception
+ {
+ User user = userService.getUser( id );
+
+ if ( user == null )
+ {
+ ContextUtils.conflictResponse( response, "User not found: " + id );
+ return;
+ }
+
+ if ( user.getUserCredentials() == null || !user.getUserCredentials().isInvitation() )
+ {
+ ContextUtils.conflictResponse( response, "User account is not an invitation: " + id );
+ return;
+ }
+
+ String valid = securityService.validateRestore( user.getUserCredentials() );
+
+ if ( valid != null )
+ {
+ ContextUtils.conflictResponse( response, valid );
+ return;
+ }
+
+ boolean isInviteUsername = securityService.isInviteUsername( user.getUsername() );
+
+ RestoreOptions restoreOptions = isInviteUsername ? RestoreOptions.INVITE_WITH_USERNAME_CHOICE : RestoreOptions.INVITE_WITH_DEFINED_USERNAME;
+
+ securityService.sendRestoreMessage( user.getUserCredentials(),
+ ContextUtils.getContextPath( request ), restoreOptions );
+ }
+
@RequestMapping( value = BULK_INVITE_PATH, method = RequestMethod.POST, consumes = "application/json" )
public void postJsonInvites( HttpServletRequest request, HttpServletResponse response ) throws Exception
{
=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-user/src/main/resources/org/hisp/dhis/user/i18n_module.properties'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-user/src/main/resources/org/hisp/dhis/user/i18n_module.properties 2015-02-01 23:02:22 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-user/src/main/resources/org/hisp/dhis/user/i18n_module.properties 2015-03-18 18:51:30 +0000
@@ -376,4 +376,6 @@
expired_invitations = Expired invitations
show_self_registrations = Show self-registrations
self_registered_users = Self-registered users
-replicate=Replicate
\ No newline at end of file
+replicate=Replicate
+resend_invitation=Resend invitation
+invitation_sent=Invitation sent
\ No newline at end of file
=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-user/src/main/webapp/dhis-web-maintenance-user/allUser.vm'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-user/src/main/webapp/dhis-web-maintenance-user/allUser.vm 2015-01-12 18:53:15 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-user/src/main/webapp/dhis-web-maintenance-user/allUser.vm 2015-03-18 18:51:30 +0000
@@ -10,6 +10,7 @@
var i18n_username = '$encoder.jsEscape( $i18n.getString( "username" ) , "'")';
var i18n_name = '$encoder.jsEscape( $i18n.getString( "name" ) , "'")';
var i18n_operations = '$encoder.jsEscape( $i18n.getString( "operations" ) , "'")';
+ var i18n_invitation_sent = '$encoder.jsEscape( $i18n.getString( "invitation_sent" ) , "'")';
var currentUserName = '$currentUsername';
</script>
@@ -23,6 +24,7 @@
<li data-enabled="canUpdate"><a data-target-fn="showUpdateUserForm"><i class="fa fa-edit"></i> $i18n.getString( "edit" )</a></li>
<li data-enabled="canDelete"><a data-target-fn="removeUser"><i class="fa fa-trash-o"></i> $i18n.getString( "remove" )</a></li>
<li data-enabled="canReplicate"><a data-target-fn="showReplicateUserDialog"><i class="fa fa-copy"></i> $i18n.getString( "replicate" )</a></li>
+ <li data-enabled="canReinvite"><a data-target-fn="resendInvitation"><i class="fa fa-repeat"></i> $i18n.getString( "resend_invitation" )</a></li>
<li><a data-target-fn="showUserDetails"><i class="fa fa-info-circle"></i> $i18n.getString( "show_details" )</a></li>
<li data-enabled="userEnabled"><a data-target-fn="disableUser"><i class="fa fa-ban"></i> $i18n.getString( "disable")</a></li>
<li data-enabled="userDisabled"><a data-target-fn="enableUser"><i class="fa fa-ban"></i> $i18n.getString( "enable" )</a></li>
@@ -77,6 +79,7 @@
data-can-manage="$security.canManage( $user.userCredentials )"
data-can-update="$security.canUpdate( $user.userCredentials )"
data-can-delete="$security.canDelete( $user.userCredentials )"
+ data-can-reinvite="#if( $user.userCredentials.isInvitation() && $security.canUpdate( $user.userCredentials ) )true#{else}false#end"
data-can-replicate="$hasAllAuth"
data-user-enabled="#if( !$user.userCredentials.disabled )true#{else}false#end"
data-user-disabled="$user.userCredentials.disabled">
=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-user/src/main/webapp/dhis-web-maintenance-user/javascript/user.js'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-user/src/main/webapp/dhis-web-maintenance-user/javascript/user.js 2015-01-12 18:53:15 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-user/src/main/webapp/dhis-web-maintenance-user/javascript/user.js 2015-03-18 18:51:30 +0000
@@ -239,3 +239,18 @@
function cancelReplicateUser() {
$( "#replicateUserForm" ).dialog( "destroy" );
}
+
+function resendInvitation( context ) {
+ var userId = context.uid;
+
+ $.ajax( {
+ url: "../api/users/" + userId + "/invite",
+ type: "post",
+ success: function() {
+ setHeaderDelayMessage( i18n_invitation_sent );
+ },
+ error: function( xhr, status, error ) {
+ setHeaderDelayMessage( xhr.responseText );
+ }
+ } );
+}