dhis2-devs team mailing list archive
-
dhis2-devs team
-
Mailing list archive
-
Message #28142
[Branch ~dhis2-devs-core/dhis2/trunk] Rev 14031: Support account invite with predefined username
------------------------------------------------------------
revno: 14031
committer: Jim Grace <jimgrace@xxxxxxxxx>
branch nick: dhis2
timestamp: Fri 2014-02-14 09:09:37 -0500
message:
Support account invite with predefined username
added:
dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/RestoreOptions.java
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/RestoreType.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/api/controller/AccountController.java
dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/validationRules.js
dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/useraccount/account.vm
dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/useraccount/action/IsInviteTokenValidAction.java
dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-user/src/main/java/org/hisp/dhis/user/action/AddUserAction.java
dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-user/src/main/webapp/dhis-web-maintenance-user/addUserForm.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 2014-02-04 11:02:32 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/DefaultSecurityService.java 2014-02-14 14:09:37 +0000
@@ -114,24 +114,31 @@
return false;
}
- String username = "invitedUser_" + CodeGenerator.generateCode( INVITED_USERNAME_UNIQUE_LENGTH );
+ if ( credentials.getUsername().isEmpty() )
+ {
+ String username = "user_invitation_" + CodeGenerator.generateCode( INVITED_USERNAME_UNIQUE_LENGTH );
+
+ credentials.setUsername( username );
+ }
+
String rawPassword = CodeGenerator.generateCode( INVITED_USER_PASSWORD_LENGTH );
credentials.getUser().setSurname( "(TBD)" );
credentials.getUser().setFirstName( "(TBD)" );
- credentials.setUsername( username );
- credentials.setPassword( passwordManager.encodePassword( username, rawPassword ) );
+ credentials.setPassword( passwordManager.encodePassword( credentials.getUsername(), rawPassword ) );
return true;
}
- public boolean sendRestoreMessage( UserCredentials credentials, String rootPath, RestoreType restoreType )
+ public boolean sendRestoreMessage( UserCredentials credentials, String rootPath, RestoreOptions restoreOptions )
{
if ( credentials == null || rootPath == null )
{
return false;
}
+ RestoreType restoreType = restoreOptions.getRestoreType();
+
if ( credentials.getUser() == null || credentials.getUser().getEmail() == null )
{
log.info( "Could not send " + restoreType.name() + " message as user does not exist or has no email: " + credentials );
@@ -156,7 +163,7 @@
return false;
}
- String[] result = initRestore( credentials, restoreType );
+ String[] result = initRestore( credentials, restoreOptions );
Set<User> users = new HashSet<User>();
users.add( credentials.getUser() );
@@ -177,14 +184,16 @@
return true;
}
- public String[] initRestore( UserCredentials credentials, RestoreType restoreType )
+ public String[] initRestore( UserCredentials credentials, RestoreOptions restoreOptions )
{
- String token = restoreType.getTokenPrefix() + CodeGenerator.generateCode( RESTORE_TOKEN_LENGTH );
+ String token = restoreOptions.getTokenPrefix() + CodeGenerator.generateCode( RESTORE_TOKEN_LENGTH );
String code = CodeGenerator.generateCode( RESTORE_CODE_LENGTH );
String hashedToken = passwordManager.encodePassword( credentials.getUsername(), token );
String hashedCode = passwordManager.encodePassword( credentials.getUsername(), code );
+ RestoreType restoreType = restoreOptions.getRestoreType();
+
Date expiry = new Cal().now().add( restoreType.getExpiryIntervalType(), restoreType.getExpiryIntervalCount() ).time();
credentials.setRestoreToken( hashedToken );
@@ -197,6 +206,11 @@
return result;
}
+ public RestoreOptions getRestoreOptions( String token )
+ {
+ return RestoreOptions.getRestoreOptions( token );
+ }
+
public boolean restore( UserCredentials credentials, String token, String code, String newPassword, RestoreType restoreType )
{
if ( credentials == null || token == null || code == null || newPassword == null
@@ -239,20 +253,28 @@
public boolean verifyToken( UserCredentials credentials, String token, RestoreType restoreType )
{
- if ( credentials == null || token == null )
- {
- return false;
- }
-
- if ( !token.startsWith( restoreType.getTokenPrefix() ) )
- {
- log.info( "Wrong prefix for restore type " + restoreType.name() + " on token: " + token );
+ if ( credentials == null || token == null || restoreType == null )
+ {
+ return false;
+ }
+
+ RestoreOptions restoreOptions = RestoreOptions.getRestoreOptions( token );
+
+ if ( restoreOptions == null )
+ {
+ log.info( "Can't parse restore options for " + restoreType.name() + " from token " + token + " for user " + credentials );
+ return false;
+ }
+
+ if ( restoreType != restoreOptions.getRestoreType() )
+ {
+ log.info( "Wrong prefix for restore type " + restoreType.name() + " on token " + token + " for user " + credentials );
return false;
}
if ( credentials.getRestoreToken() == null )
{
- log.info( "Could not verify token as user has no token: " + credentials );
+ log.info( "Could not verify token for " + restoreType.name() + " as user has no token: " + credentials );
return false;
}
=== added file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/RestoreOptions.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/RestoreOptions.java 1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/RestoreOptions.java 2014-02-14 14:09:37 +0000
@@ -0,0 +1,108 @@
+package org.hisp.dhis.security;
+/*
+ * Copyright (c) 2004-2013, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * Neither the name of the HISP project nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * Options for user account restore operation. These options are represented
+ * in the user account restore email as a prefix to the restore token.
+ * This token is hashed, and the hash is stored in the database. This means
+ * that the options cannot be hacked to change them, because then the token
+ * would no longer match the saved hash in the database.
+ *
+ * @author Jim Grace
+ */
+
+public enum RestoreOptions
+{
+ RECOVER_PASSWORD_OPTION ( "R", RestoreType.RECOVER_PASSWORD, false ),
+ INVITE_WITH_USERNAME_CHOICE ( "IC", RestoreType.INVITE, true ),
+ INVITE_WITH_DEFINED_USERNAME ( "ID", RestoreType.INVITE, false );
+
+ /**
+ * Prefix to be used on restore token, to represent this set of options.
+ */
+ private final String tokenPrefix;
+
+ /**
+ * The type of restore operation to perform (i.e. password recovery
+ * or invite to create account.)
+ */
+ private final RestoreType restoreType;
+
+ /**
+ * Defines whether the user can choose a username at the time of restore.
+ */
+ private final boolean usernameChoice;
+
+ // -------------------------------------------------------------------------
+ // Constructor
+ // -------------------------------------------------------------------------
+
+ RestoreOptions( String tokenPrefix, RestoreType restoreType, boolean usernameChoice )
+ {
+ this.tokenPrefix = tokenPrefix;
+ this.restoreType = restoreType;
+ this.usernameChoice = usernameChoice;
+ }
+
+ // -------------------------------------------------------------------------
+ // Get Restore Options from a token string
+ // -------------------------------------------------------------------------
+
+ static public RestoreOptions getRestoreOptions( String token )
+ {
+ for (RestoreOptions ro : RestoreOptions.values())
+ {
+ if ( token.startsWith( ro.getTokenPrefix() ) )
+ {
+ return ro;
+ }
+ }
+
+ return null;
+ }
+
+ // -------------------------------------------------------------------------
+ // Getters
+ // -------------------------------------------------------------------------
+
+ public String getTokenPrefix()
+ {
+ return tokenPrefix;
+ }
+
+ public RestoreType getRestoreType()
+ {
+ return restoreType;
+ }
+
+ public boolean isUsernameChoice()
+ {
+ return usernameChoice;
+ }
+}
=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/RestoreType.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/RestoreType.java 2014-01-17 03:48:57 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/RestoreType.java 2014-02-14 14:09:37 +0000
@@ -37,14 +37,8 @@
public enum RestoreType
{
- RECOVER_PASSWORD ("R", Calendar.HOUR_OF_DAY, 1, "restore_message", "User account restore confirmation", "restore.action" ),
- INVITE ("I", Calendar.MONTH, 3, "invite_message", "Create DHIS 2 user account invitation", "invite.action" );
-
- /**
- * Prefix to be used on restore token. This prevents one type of restore
- * URL from being hacked and used for a different type of restore.
- */
- private final String tokenPrefix;
+ RECOVER_PASSWORD( Calendar.HOUR_OF_DAY, 1, "restore_message", "User account restore confirmation", "restore.action" ),
+ INVITE( Calendar.MONTH, 3, "invite_message", "Create DHIS 2 user account invitation", "invite.action" );
/**
* Type of Calendar interval before the restore expires.
@@ -75,10 +69,9 @@
// Constructor
// -------------------------------------------------------------------------
- RestoreType( String tokenPrefix, int expiryIntervalType, int expiryIntervalCount,
+ RestoreType( int expiryIntervalType, int expiryIntervalCount,
String emailTemplate, String emailSubject, String action )
{
- this.tokenPrefix = tokenPrefix;
this.expiryIntervalType = expiryIntervalType;
this.expiryIntervalCount = expiryIntervalCount;
this.emailTemplate = emailTemplate;
@@ -90,11 +83,6 @@
// Getters
// -------------------------------------------------------------------------
- public String getTokenPrefix()
- {
- return tokenPrefix;
- }
-
public int getExpiryIntervalType()
{
return expiryIntervalType;
=== 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 2014-01-25 18:46:36 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/security/SecurityService.java 2014-02-14 14:09:37 +0000
@@ -55,11 +55,11 @@
*
* @param credentials the credentials for the user to send restore message.
* @param rootPath the root path of the request.
- * @param restoreType type of restore operation (e.g. pw recovery, invite).
+ * @param restoreOptions restore options, including type of restore.
* @return false if any of the arguments are null or if the user credentials
* identified by the user name does not exist, true otherwise.
*/
- boolean sendRestoreMessage( UserCredentials credentials, String rootPath, RestoreType restoreType );
+ boolean sendRestoreMessage( UserCredentials credentials, String rootPath, RestoreOptions restoreOptions );
/**
* Populates the restoreToken and restoreCode property of the given
@@ -68,11 +68,19 @@
* on the restore type. Changes are persisted.
*
* @param credentials the user credentials.
- * @param restoreType type of restore operation (e.g. pw recovery, invite).
+ * @param restoreOptions restore options, including type of restore.
* @return an array where index 0 is the clear-text token and index 1 the
* clear-text code.
*/
- String[] initRestore( UserCredentials credentials, RestoreType restoreType );
+ String[] initRestore( UserCredentials credentials, RestoreOptions restoreOptions );
+
+ /**
+ * Gets the restore options by parsing them from a restore token string.
+ *
+ * @param token the restore token.
+ * @return the restore options.
+ */
+ RestoreOptions getRestoreOptions( String token );
/**
* Tests whether the given token and code are valid for the given user name.
=== 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 2014-01-25 18:46:36 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/test/java/org/hisp/dhis/security/SecurityServiceTest.java 2014-02-14 14:09:37 +0000
@@ -83,8 +83,10 @@
@Test
public void testRestoreRecoverPassword()
{
- String[] result = securityService.initRestore( credentials, RestoreType.RECOVER_PASSWORD );
-
+ String[] result = securityService.initRestore( credentials, RestoreOptions.RECOVER_PASSWORD_OPTION );
+
+ assertEquals( 2, result.length );
+
String token = result[0];
String code = result[1];
@@ -94,6 +96,12 @@
assertNotNull( credentials.getRestoreCode() );
assertNotNull( credentials.getRestoreExpiry() );
+ RestoreOptions restoreOptions = securityService.getRestoreOptions( token );
+
+ assertEquals( RestoreOptions.RECOVER_PASSWORD_OPTION, restoreOptions );
+ assertEquals( RestoreType.RECOVER_PASSWORD, restoreOptions.getRestoreType() );
+ assertEquals( false, restoreOptions.isUsernameChoice() );
+
//
// verifyToken()
//
@@ -144,7 +152,10 @@
@Test
public void testRestoreInvite()
{
- String[] result = securityService.initRestore( credentials, RestoreType.INVITE );
+ String[] result = securityService.initRestore( credentials, RestoreOptions.INVITE_WITH_DEFINED_USERNAME );
+
+ assertEquals( 2, result.length );
+
String token = result[0];
String code = result[1];
@@ -154,6 +165,12 @@
assertNotNull( credentials.getRestoreCode() );
assertNotNull( credentials.getRestoreExpiry() );
+ RestoreOptions restoreOptions = securityService.getRestoreOptions( token );
+
+ assertEquals( RestoreOptions.INVITE_WITH_DEFINED_USERNAME, restoreOptions );
+ assertEquals( RestoreType.INVITE, restoreOptions.getRestoreType() );
+ assertEquals( false, restoreOptions.isUsernameChoice() );
+
//
// verifyToken()
//
@@ -200,4 +217,20 @@
assertEquals( hashedPassword, credentials.getPassword() );
}
+
+ @Test
+ public void testRestoreInviteWithUsernameChoice()
+ {
+ String[] result = securityService.initRestore( credentials, RestoreOptions.INVITE_WITH_USERNAME_CHOICE );
+
+ assertEquals( 2, result.length );
+
+ String token = result[0];
+
+ RestoreOptions restoreOptions = securityService.getRestoreOptions( token );
+
+ assertEquals( RestoreOptions.INVITE_WITH_USERNAME_CHOICE, restoreOptions );
+ assertEquals( RestoreType.INVITE, restoreOptions.getRestoreType() );
+ assertEquals( true, restoreOptions.isUsernameChoice() );
+ }
}
=== modified file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/AccountController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/AccountController.java 2014-01-27 17:20:36 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/AccountController.java 2014-02-14 14:09:37 +0000
@@ -36,6 +36,7 @@
import org.hisp.dhis.configuration.ConfigurationService;
import org.hisp.dhis.organisationunit.OrganisationUnit;
import org.hisp.dhis.security.PasswordManager;
+import org.hisp.dhis.security.RestoreOptions;
import org.hisp.dhis.security.RestoreType;
import org.hisp.dhis.security.SecurityService;
import org.hisp.dhis.setting.SystemSettingManager;
@@ -132,7 +133,7 @@
return "User does not exist: " + username;
}
- boolean recover = securityService.sendRestoreMessage( credentials, rootPath, RestoreType.RECOVER_PASSWORD );
+ boolean recover = securityService.sendRestoreMessage( credentials, rootPath, RestoreOptions.RECOVER_PASSWORD_OPTION );
if ( !recover )
{
@@ -204,9 +205,9 @@
@RequestParam String email,
@RequestParam String phoneNumber,
@RequestParam String employer,
- @RequestParam String inviteUsername,
- @RequestParam String inviteToken,
- @RequestParam String inviteCode,
+ @RequestParam( required = false ) String inviteUsername,
+ @RequestParam( required = false ) String inviteToken,
+ @RequestParam( required = false ) String inviteCode,
@RequestParam( value = "recaptcha_challenge_field", required = false ) String recapChallenge,
@RequestParam( value = "recaptcha_response_field", required = false ) String recapResponse,
HttpServletRequest request,
@@ -214,7 +215,11 @@
{
UserCredentials credentials = null;
- boolean invitedByEmail = !inviteUsername.isEmpty();
+ boolean invitedByEmail = ( inviteUsername != null && !inviteUsername.isEmpty() );
+
+ log.info( "AccountController: inviteUsername = " + inviteUsername );
+
+ boolean canChooseUsername = true;
if ( invitedByEmail )
{
@@ -239,6 +244,10 @@
response.setStatus( HttpServletResponse.SC_BAD_REQUEST );
return "Invitation code not valid";
}
+
+ RestoreOptions restoreOptions = securityService.getRestoreOptions( inviteToken );
+
+ canChooseUsername = restoreOptions.isUsernameChoice();
}
else
{
@@ -277,7 +286,7 @@
UserCredentials usernameAlreadyTakenCredentials = userService.getUserCredentialsByUsername( username );
- if ( usernameAlreadyTakenCredentials != null )
+ if ( canChooseUsername && usernameAlreadyTakenCredentials != null )
{
response.setStatus( HttpServletResponse.SC_BAD_REQUEST );
return "User name is already taken";
@@ -387,7 +396,15 @@
user.setPhoneNumber( phoneNumber );
user.setEmployer( employer );
- credentials.setUsername( username );
+ if ( canChooseUsername )
+ {
+ credentials.setUsername( username );
+ }
+ else
+ {
+ username = credentials.getUsername();
+ }
+
credentials.setPassword( passwordManager.encodePassword( username, password ) );
userService.updateUser( user );
=== modified file 'dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/validationRules.js'
--- dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/validationRules.js 2014-01-17 03:48:57 +0000
+++ dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/validationRules.js 2014-02-14 14:09:37 +0000
@@ -4,6 +4,9 @@
"required" : true,
"rangelength" : [ 2, 140 ]
},
+ "inviteUsername" : {
+ "rangelength" : [ 2, 140 ]
+ },
"firstName" : {
"required" : true,
"rangelength" : [ 2, 140 ]
=== modified file 'dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/useraccount/account.vm'
--- dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/useraccount/account.vm 2014-01-23 15:04:07 +0000
+++ dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/useraccount/account.vm 2014-02-14 14:09:37 +0000
@@ -28,23 +28,34 @@
<table>
- <tr #if( $accountAction != "invited" ) style="display:none" #end>
+#if( $accountAction == "invited" )
+ <tr>
<td style="width:140px"><label for="code">$i18n.getString( "code_from_email" )</label></td>
<td>
<input type="text" id="inviteCode" name="inviteCode" autocomplete="off">
- <input type="hidden" id="inviteUsername" name="inviteUsername" #if( $accountAction == "invited" ) value="$username" #end>
- <input type="hidden" id="inviteToken" name="inviteToken" #if( $accountAction == "invited" ) value="$token" #end>
+ <input type="hidden" id="inviteUsername" name="inviteUsername" value="$username">
+ <input type="hidden" id="inviteToken" name="inviteToken" value="$token">
</td>
</tr>
+#end
<tr>
<td style="width:140px"><label id="label_firstName" for="firstName">$i18n.getString( "name" )</label></td>
- <td><input type="text" id="firstName" name="firstName" autocomplete="off" style="width:11.7em; margin-right:7px;" placeholder="First">
- <input type="text" id="surname" name="surname" autocomplete="off" style="width:11.7em" placeholder="Last"></td>
+ <td>
+ <input type="text" id="firstName" name="firstName" autocomplete="off" style="width:11.7em; margin-right:7px;" placeholder="First">
+ <input type="text" id="surname" name="surname" autocomplete="off" style="width:11.7em" placeholder="Last">
+ </td>
</tr>
<tr>
<td><label id="label_username" for="username">$i18n.getString( "user_name" )</label></td>
- <td><input type="text" id="username" name="username" autocomplete="off"></td>
+ <td>
+ <input type="text" id="username" name="username" autocomplete="off" #if( $usernameChoice == "false" ) style="display:none" value="nonExistingUserName_RpuECtIlVoRKTpYmEkYrAHmPtX4m1U" #end>
+
+#if( $usernameChoice == "false" )
+ <input type="text" id="assignedUsername" name="assignedUsername" disabled="disabled" value="$username">
+#end
+
+ </td>
</tr>
<tr>
<td><label id="label_password" for="password">$i18n.getString( "password" )</label></td>
=== modified file 'dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/useraccount/action/IsInviteTokenValidAction.java'
--- dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/useraccount/action/IsInviteTokenValidAction.java 2014-01-23 15:04:07 +0000
+++ dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/useraccount/action/IsInviteTokenValidAction.java 2014-02-14 14:09:37 +0000
@@ -28,6 +28,7 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+import org.hisp.dhis.security.RestoreOptions;
import org.hisp.dhis.security.RestoreType;
import org.hisp.dhis.security.SecurityService;
import org.hisp.dhis.setting.SystemSettingManager;
@@ -98,6 +99,13 @@
return accountAction;
}
+ private String usernameChoice;
+
+ public String getUsernameChoice()
+ {
+ return usernameChoice;
+ }
+
private String email;
public String getEmail()
@@ -125,6 +133,13 @@
email = userCredentials.getUser().getEmail();
+ RestoreOptions restoreOptions = securityService.getRestoreOptions( token );
+
+ if ( restoreOptions != null )
+ {
+ usernameChoice = Boolean.toString( restoreOptions.isUsernameChoice() );
+ }
+
boolean verified = securityService.verifyToken( userCredentials, token, RestoreType.INVITE );
return verified ? SUCCESS : ERROR;
=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-user/src/main/java/org/hisp/dhis/user/action/AddUserAction.java'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-user/src/main/java/org/hisp/dhis/user/action/AddUserAction.java 2014-01-25 18:46:36 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-user/src/main/java/org/hisp/dhis/user/action/AddUserAction.java 2014-02-14 14:09:37 +0000
@@ -42,7 +42,7 @@
import org.hisp.dhis.oust.manager.SelectionTreeManager;
import org.hisp.dhis.ouwt.manager.OrganisationUnitSelectionManager;
import org.hisp.dhis.security.PasswordManager;
-import org.hisp.dhis.security.RestoreType;
+import org.hisp.dhis.security.RestoreOptions;
import org.hisp.dhis.security.SecurityService;
import org.hisp.dhis.system.util.AttributeUtils;
import org.hisp.dhis.system.util.LocaleUtils;
@@ -135,6 +135,13 @@
this.username = username;
}
+ private String inviteUsername;
+
+ public void setInviteUsername( String inviteUsername )
+ {
+ this.inviteUsername = inviteUsername;
+ }
+
private String rawPassword;
public void setRawPassword( String rawPassword )
@@ -237,6 +244,7 @@
}
username = username.trim();
+ inviteUsername = inviteUsername.trim();
inviteEmail = inviteEmail.trim();
// ---------------------------------------------------------------------
@@ -251,8 +259,11 @@
userCredentials.setUser( user );
user.setUserCredentials( userCredentials );
+ userCredentials.setUsername( username );
+
if ( ACCOUNT_ACTION_INVITE.equals( accountAction ) )
{
+ userCredentials.setUsername( inviteUsername );
user.setEmail( inviteEmail );
securityService.prepareUserForInvite ( userCredentials );
@@ -264,7 +275,6 @@
user.setEmail( email );
user.setPhoneNumber( phoneNumber );
- userCredentials.setUsername( username );
userCredentials.setPassword( passwordManager.encodePassword( username, rawPassword ) );
}
@@ -299,7 +309,9 @@
if ( ACCOUNT_ACTION_INVITE.equals( accountAction ) )
{
- securityService.sendRestoreMessage( userCredentials, getRootPath(), RestoreType.INVITE );
+ RestoreOptions restoreOptions = inviteUsername.isEmpty() ? RestoreOptions.INVITE_WITH_USERNAME_CHOICE : RestoreOptions.INVITE_WITH_DEFINED_USERNAME;
+
+ securityService.sendRestoreMessage( userCredentials, getRootPath(), restoreOptions );
}
return SUCCESS;
=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-user/src/main/webapp/dhis-web-maintenance-user/addUserForm.vm'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-user/src/main/webapp/dhis-web-maintenance-user/addUserForm.vm 2014-02-04 09:38:44 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-user/src/main/webapp/dhis-web-maintenance-user/addUserForm.vm 2014-02-14 14:09:37 +0000
@@ -63,12 +63,22 @@
<th colspan="4">$i18n.getString( "details" )</th>
</tr>
- <tr class="account">
+ <tr class="invite" style="display:none">
+ <td><label for="inviteEmail">$i18n.getString( "email" ) <em title="$i18n.getString( 'required' )" class="required">*</em></label></td>
+ <td colspan="3"><input type="text" id="inviteEmail" name="inviteEmail" value="validEmail@xxxxxxxxxx"></td>
+ </tr>
+
+ <tr class="invite" style="display:none">
+ <td><label for="inviteUsername">$i18n.getString( "username" )</label></td>
+ <td colspan="3"><input type="text" id="inviteUsername" name="inviteUsername"></td>
+ </tr>
+
+ <tr class="account">
<td><label for="username">$i18n.getString( "username" ) <em title="$i18n.getString( 'required' )" class="required">*</em></label></td>
<td colspan="3"><input type="text" id="username" name="username" autocomplete="off"></td>
</tr>
- <tr class="account">
+ <tr class="account">
<td><label for="rawPassword">$i18n.getString( "password" ) <em title="$i18n.getString( 'required' )" class="required">*</em></label></td>
<td colspan="3"><input type="password" id="rawPassword" name="rawPassword" autocomplete="off"></td>
</tr>
@@ -90,12 +100,7 @@
<tr class="account">
<td><label for="email">$i18n.getString( "email" )</label></td>
- <td colspan="3"><input type="text" id="email" name="email" ></td>
- </tr>
-
- <tr class="invite" style="display:none">
- <td><label for="inviteEmail">$i18n.getString( "email" ) <em title="$i18n.getString( 'required' )" class="required">*</em></label></td>
- <td colspan="3"><input type="text" id="inviteEmail" name="inviteEmail" value="validEmail@xxxxxxxxxx" ></td>
+ <td colspan="3"><input type="text" id="email" name="email"></td>
</tr>
<tr class="account">
=== 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 2014-02-04 09:38:44 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-user/src/main/webapp/dhis-web-maintenance-user/javascript/user.js 2014-02-14 14:09:37 +0000
@@ -85,7 +85,8 @@
{
if( $('#accountAction').val() == 'create' )
{
- $('#username').val( saved["username"] );
+ $('#username').val( $('#inviteUsername').val() );
+ $('#inviteUsername').val( 'nonExistingUserName_RpuECtIlVoRKTpYmEkYrAHmPtX4m1U' );
$('#rawPassword').val( saved["rawPassword"] );
$('#retypePassword').val( saved["retypePassword"] );
$('#surname').val( saved["surname"] );
@@ -102,13 +103,13 @@
$('.account').hide();
$('.invite').show();
- saved["username"] = $('#username').val();
saved["rawPassword"] = $('#rawPassword').val();
saved["retypePassword"] = $('#retypePassword').val();
saved["surname"] = $('#surname').val();
saved["firstName"] = $('#firstName').val();
saved["phoneNumber"] = $('#phoneNumber').val();
+ $('#inviteUsername').val( $('#username').val() );
$('#username').val( 'nonExistingUserName_RpuECtIlVoRKTpYmEkYrAHmPtX4m1U' );
$('#rawPassword').val( 'validPassword_123' );
$('#retypePassword').val( 'validPassword_123' );