Project

General

Profile

« Previous | Next » 

Revision 8cb8fc5c

Added by Andreas Kohlbecker over 2 years ago

ref #9497 user account self registration: AccountCreationRequest only with email-address

  • request tokens only with email address possible
  • refactoring request tokens class hierarchy
  • ... and token stores

View differences:

cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/security/AbstractRequestTokenStore.java
18 18
import java.util.Optional;
19 19
import java.util.stream.Collectors;
20 20

  
21
import org.apache.commons.lang3.StringUtils;
21 22
import org.apache.log4j.Logger;
22 23

  
23
import eu.etaxonomy.cdm.model.permission.User;
24

  
25 24
/**
26 25
 * @author a.kohlbecker
27 26
 * @since Nov 18, 2021
28 27
 */
29
public abstract class AbstractRequestTokenStore<T extends AbstractRequestToken>  implements IAbstractRequestTokenStore<T> {
28
public abstract class AbstractRequestTokenStore<T extends AbstractRequestToken, X extends Object>  implements IAbstractRequestTokenStore<T, X> {
30 29

  
31 30
    public static final int TOKEN_LENGTH = 50;
32 31
    protected static Logger logger = Logger.getLogger(AbstractRequestTokenStore.class);
......
35 34

  
36 35

  
37 36
    @Override
38
    public T create(User user) {
37
    public T create(String userEmailAddress, X additionalData) {
39 38
        clearExpiredTokens();
40
        assert user != null;
41
        assert !user.getEmailAddress().isEmpty();
39
        assert StringUtils.isNotBlank(userEmailAddress);
42 40
        String randomToken = generateRandomToken();
43 41
        int tokenLifetimeMinutes = getTokenLifetimeMinutes();
44
        T token = createNewToken(user, randomToken, tokenLifetimeMinutes);
42
        T token = createNewToken(userEmailAddress, additionalData, randomToken, tokenLifetimeMinutes);
45 43
        tokenList.put(token.getToken(), token);
46 44
        return token;
47 45
    }
......
56 54
    }
57 55

  
58 56
    @Override
59
    public Optional<T> findResetRequest(String token) {
57
    public Optional<T> findRequest(String token) {
60 58
        clearExpiredTokens();
61 59
        T resetRequest = tokenList.get(token);
62 60
        if(isEligibleResetRequest(resetRequest)) {
cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/security/AccountCreationRequest.java
9 9
 */
10 10
public class AccountCreationRequest extends AbstractRequestToken {
11 11

  
12
    private String userName;
13

  
14 12
    private String userEmail;
15 13

  
16
    private String encryptedPassword;
17 14

  
18
    protected AccountCreationRequest(String userName, String encryptedPassword, String userEmail, String token, int expireInMinutes) {
15
    protected AccountCreationRequest(String userEmail, String token, int expireInMinutes) {
19 16
        super();
20
        this.userName = userName;
21 17
        this.userEmail = userEmail;
22
        this.encryptedPassword = encryptedPassword;
23 18
        this.token = token;
24 19
        this.setExpiryDate(expireInMinutes);
25 20
    }
26 21

  
27
    public String getUserName() {
28
        return userName;
29
    }
30

  
31 22
    public String getUserEmail() {
32 23
        return userEmail;
33 24
    }
34 25

  
35
    public String getEncryptedPassword() {
36
        return encryptedPassword;
37
    }
38 26
}
cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/security/AccountCreationRequestTokenStore.java
12 12
import org.springframework.stereotype.Component;
13 13

  
14 14
import eu.etaxonomy.cdm.api.service.IUserService;
15
import eu.etaxonomy.cdm.model.permission.User;
16 15

  
17 16
/**
18 17
 * @author a.kohlbecker
19 18
 * @since Nov 3, 2021
20 19
 */
21 20
@Component
22
public class AccountCreationRequestTokenStore extends AbstractRequestTokenStore<AccountCreationRequest> {
21
public class AccountCreationRequestTokenStore extends AbstractRequestTokenStore<AccountCreationRequest, Object> {
23 22

  
24 23
    @Autowired
25 24
    private IUserService userService;
26 25

  
27 26
    @Override
28
    public AccountCreationRequest createNewToken(User user, String randomToken, int tokenLifetimeMinutes) {
29
        userService.encodeUserPassword(user, user.getPassword());
30
        AccountCreationRequest token = new AccountCreationRequest(user.getUsername(), user.getPassword(), user.getEmailAddress(), randomToken, tokenLifetimeMinutes);
27
    public AccountCreationRequest createNewToken(String userEmailAddress, Object unused, String randomToken, int tokenLifetimeMinutes) {
28
        AccountCreationRequest token = new AccountCreationRequest(userEmailAddress, randomToken, tokenLifetimeMinutes);
31 29
        return token;
32 30
    }
33 31

  
cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/security/IAbstractRequestTokenStore.java
10 10

  
11 11
import java.util.Optional;
12 12

  
13
import eu.etaxonomy.cdm.model.permission.User;
14

  
15 13
/**
16 14
 * @author a.kohlbecker
17 15
 * @since Nov 3, 2021
18 16
 */
19
public interface IAbstractRequestTokenStore<T extends AbstractRequestToken> {
17
public interface IAbstractRequestTokenStore<T extends AbstractRequestToken, X extends Object> {
20 18

  
21 19
    public static final int TOKEN_LIFETIME_MINUTES_DEFAULT = 60 * 6;
22 20

  
23
    public T create(User user);
21
    public T create(String userEmailAddress, X additionalData);
24 22

  
25 23
    /**
26 24
     * Removes the corresponding <code>AbstractRequestToken</code> from the
......
50 48
     * @return the valid <code>AbstractRequestToken</code> or an empty
51 49
     *         <code>Optional</code>
52 50
     */
53
    public Optional<T> findResetRequest(String token);
51
    public Optional<T> findRequest(String token);
54 52

  
55 53

  
56 54
    public void setTokenLifetimeMinutes(int tokenLifetimeMinutes);
57 55

  
58
    public T createNewToken(User user, String randomToken, int tokenLifetimeMinutes);
56
    public T createNewToken(String userEmailAddress, X additionalData, String randomToken, int tokenLifetimeMinutes);
59 57

  
60 58
}
cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/security/PasswordResetTokenStore.java
17 17
 * @since Nov 3, 2021
18 18
 */
19 19
@Component
20
public class PasswordResetTokenStore extends AbstractRequestTokenStore<PasswordResetRequest> {
20
public class PasswordResetTokenStore extends AbstractRequestTokenStore<PasswordResetRequest, User> {
21 21

  
22 22
    @Override
23
    public PasswordResetRequest createNewToken(User user, String randomToken, int tokenLifetimeMinutes) {
24
        PasswordResetRequest token = new PasswordResetRequest(user.getUsername(), user.getEmailAddress(), randomToken, tokenLifetimeMinutes);
23
    public PasswordResetRequest createNewToken(String userEmailAddress, User user, String randomToken, int tokenLifetimeMinutes) {
24
        PasswordResetRequest token = new PasswordResetRequest(user.getUsername(), userEmailAddress, randomToken, tokenLifetimeMinutes);
25 25
        return token;
26 26
    }
27 27

  
cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/security/AccountRegistrationService.java
49 49

  
50 50
    @Autowired
51 51
    @Qualifier("accountCreationRequestTokenStore")
52
    private IAbstractRequestTokenStore<AccountCreationRequest> accountRegistrationTokenStore;
52
    private IAbstractRequestTokenStore<AccountCreationRequest, Object> accountRegistrationTokenStore;
53 53

  
54 54
    @Override
55 55
    @Async
56
    public ListenableFuture<Boolean> emailAccountRegistrationRequest(String emailAddress,
57
            String userName, String password, String accountCreationRequestFormUrlTemplate) throws MailException, AddressException, AccountSelfManagementException {
56
    public ListenableFuture<Boolean> emailAccountRegistrationRequest(String emailAddress, String accountCreationRequestFormUrlTemplate) throws MailException, AddressException, AccountSelfManagementException {
58 57

  
59 58
        if(logger.isTraceEnabled()) {
60 59
            logger.trace("emailAccountRegistrationConfirmation() trying to aquire from rate limiter [rate: " + emailResetToken_rateLimiter.getRate() + ", timeout: " + getRateLimiterTimeout().toMillis() + "ms]");
......
63 62
            logger.trace("emailAccountRegistrationConfirmation() allowed by rate limiter");
64 63
            try {
65 64
                emailAddressValidAndUnused(emailAddress);
66
                if(userNameExists(userName)) {
67
                    throw new AccountSelfManagementException(USER_NAME_EXISTS_MSG);
68
                }
69
                User user = User.NewInstance(userName, password);
70
                user.setEmailAddress(emailAddress);
71
                AbstractRequestToken resetRequest = accountRegistrationTokenStore.create(user);
65
                AbstractRequestToken resetRequest = accountRegistrationTokenStore.create(emailAddress, null);
72 66
                String passwordRequestFormUrl = String.format(accountCreationRequestFormUrlTemplate, resetRequest.getToken());
73 67
                Map<String, String> additionalValues = new HashMap<>();
74 68
                additionalValues.put("linkUrl", passwordRequestFormUrl);
75
                sendEmail(user.getEmailAddress(), user.getUsername(),
69
                sendEmail(emailAddress, null,
76 70
                        UserAccountEmailTemplates.REGISTRATION_REQUEST_EMAIL_SUBJECT_TEMPLATE,
77 71
                        UserAccountEmailTemplates.REGISTRATION_REQUEST_EMAIL_BODY_TEMPLATE, additionalValues);
78
                logger.info("An account creartion request has been send to "
79
                        + user.getEmailAddress());
72
                logger.info("An account creation request has been send to " + emailAddress);
80 73
                return new AsyncResult<Boolean>(true);
81 74
            } catch (MailException e) {
82 75
                throw e;
......
90 83
    @Override
91 84
    @Async
92 85
    @Transactional(readOnly = false)
93
    public ListenableFuture<Boolean> createUserAccount(String token, String givenName, String familyName, String prefix)
86
    public ListenableFuture<Boolean> createUserAccount(String token, String userName, String password, String givenName, String familyName, String prefix)
94 87
            throws MailException, AccountSelfManagementException, AddressException {
95 88

  
96 89
        if (resetPassword_rateLimiter.tryAcquire(getRateLimiterTimeout())) {
97 90

  
98
            Optional<AccountCreationRequest> creationRequest = accountRegistrationTokenStore.findResetRequest(token);
91
            Optional<AccountCreationRequest> creationRequest = accountRegistrationTokenStore.findRequest(token);
99 92
            if (creationRequest.isPresent()) {
100 93
                try {
101 94
                    // check again if the email address is still unused
102 95
                    emailAddressValidAndUnused(creationRequest.get().getUserEmail());
103
                    if(userNameExists(creationRequest.get().getUserName())) {
96
                    if(userNameExists(userName)) {
104 97
                        throw new AccountSelfManagementException(USER_NAME_EXISTS_MSG);
105 98
                    }
106
                    User newUser = User.NewInstance(creationRequest.get().getUserName(), creationRequest.get().getEncryptedPassword());
99
                    User newUser = User.NewInstance(userName, password);
100
                    userService.encodeUserPassword(newUser, password);
107 101
                    userDao.saveOrUpdate(newUser);
108 102
                    accountRegistrationTokenStore.remove(token);
109
                    sendEmail(creationRequest.get().getUserEmail(), creationRequest.get().getUserName(),
103
                    sendEmail(creationRequest.get().getUserEmail(), userName,
110 104
                            UserAccountEmailTemplates.REGISTRATION_SUCCESS_EMAIL_SUBJECT_TEMPLATE,
111 105
                            UserAccountEmailTemplates.REGISTRATION_SUCCESS_EMAIL_BODY_TEMPLATE, null);
112 106
                    return new AsyncResult<Boolean>(true);
113 107
                } catch (DataAccessException e) {
114
                    String message = "Failed to create a new user [userName: " + creationRequest.get().getUserName() + ", email: " + creationRequest.get().getUserEmail() + "]";
108
                    String message = "Failed to create a new user [userName: " + userName + ", email: " + creationRequest.get().getUserEmail() + "]";
115 109
                    logger.error(message, e);
116 110
                    throw new AccountSelfManagementException(message);
117 111
                }
cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/security/AccountSelfManagementService.java
66 66
     * @param userEmail
67 67
     *  The TO-address
68 68
     * @param userName
69
     *  Used to set the value for <code>${userName}</code>
69
     *  Used to set the value for <code>${userName}</code>. Optional, may be null.
70 70
     * @param subjectTemplate
71 71
     *  A {@link StringSubstitutor} template for the email subject
72 72
     * @param bodyTemplate
......
85 85
        if(supportEmailAddress != null) {
86 86
            additionalValuesMap.put("supportEmailAddress", supportEmailAddress);
87 87
        }
88
        additionalValuesMap.put("userName", userName);
88
        if(userName != null) {
89
            additionalValuesMap.put("userName", userName);
90
        }
89 91
        additionalValuesMap.put("dataBase", dataSourceBeanId);
90 92
        StringSubstitutor substitutor = new StringSubstitutor(additionalValuesMap);
91 93

  
cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/security/IAccountRegistrationService.java
55 55
     * @throws AccountSelfManagementException
56 56
     *             in case the user name is already being used.
57 57
     */
58
    ListenableFuture<Boolean> emailAccountRegistrationRequest(String emailAddress, String userName, String password,
58
    ListenableFuture<Boolean> emailAccountRegistrationRequest(String emailAddress,
59 59
            String passwordRequestFormUrlTemplate)
60 60
            throws MailException, AddressException, AccountSelfManagementException;
61 61

  
......
63 63
     *
64 64
     * @param token
65 65
     *            the token string
66
     * @param userName
67
     *            The user name (login name) for the new account
68
     * @param password
69
     *            The password
66 70
     * @param givenName
67 71
     *            The new password to set - <b>required</b>
68 72
     * @param familyName
......
82 86
     *             {@link AccountCreationRequest} identified by the
83 87
     *             <code>token</code> not valid
84 88
     */
85
    ListenableFuture<Boolean> createUserAccount(String token, String givenName, String familyName, String prefix)
86
            throws MailException, AccountSelfManagementException, AddressException;
89
    ListenableFuture<Boolean> createUserAccount(String token, String userName, String password, String givenName,
90
            String familyName, String prefix) throws MailException, AccountSelfManagementException, AddressException;
87 91

  
88 92
    boolean userNameExists(String userName);
89 93

  
cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/security/PasswordResetService.java
43 43

  
44 44
    @Autowired
45 45
    @Qualifier("passwordResetTokenStore")
46
    IAbstractRequestTokenStore<PasswordResetRequest> passwordResetTokenStore;
46
    IAbstractRequestTokenStore<PasswordResetRequest, User> passwordResetTokenStore;
47 47

  
48 48
    /**
49 49
     * Create a request token and send it to the user via email.
......
86 86
            logger.trace("emailResetToken allowed by rate limiter");
87 87
            try {
88 88
                User user = findUser(userNameOrEmail);
89
                AbstractRequestToken resetRequest = passwordResetTokenStore.create(user);
89
                AbstractRequestToken resetRequest = passwordResetTokenStore.create(user.getEmailAddress(), user);
90 90
                String passwordRequestFormUrl = String.format(passwordRequestFormUrlTemplate, resetRequest.getToken());
91 91
                Map<String, String> additionalValues = new HashMap<>();
92 92
                additionalValues.put("linkUrl", passwordRequestFormUrl);
......
128 128

  
129 129
       if (resetPassword_rateLimiter.tryAcquire(getRateLimiterTimeout())) {
130 130

  
131
           Optional<PasswordResetRequest> resetRequest = passwordResetTokenStore.findResetRequest(token);
131
           Optional<PasswordResetRequest> resetRequest = passwordResetTokenStore.findRequest(token);
132 132
           if (resetRequest.isPresent()) {
133 133
               try {
134 134
                   UserDetails user = userService.loadUserByUsername(resetRequest.get().getUserName());
cdmlib-services/src/test/java/eu/etaxonomy/cdm/api/security/PasswordResetTokenStoreTest.java
36 36
    private static final String USER_NAME = "dummy";
37 37

  
38 38
    @SpringBeanByName
39
    private IAbstractRequestTokenStore<PasswordResetRequest> passwordResetTokenStore;
39
    private IAbstractRequestTokenStore<PasswordResetRequest, User> passwordResetTokenStore;
40 40

  
41 41
    private User testUser;
42 42

  
......
49 49

  
50 50
    @Test
51 51
    public void testTokenStillValid() {
52
        String token = passwordResetTokenStore.create(testUser).getToken();
52
        String token = passwordResetTokenStore.create(USER_EMAIL, testUser).getToken();
53 53
        assertTrue(passwordResetTokenStore.isEligibleToken(token));
54
        Optional<PasswordResetRequest> resetRequest = passwordResetTokenStore.findResetRequest(token);
54
        Optional<PasswordResetRequest> resetRequest = passwordResetTokenStore.findRequest(token);
55 55
        assertTrue(resetRequest.isPresent());
56 56
        assertEquals(USER_NAME, resetRequest.get().getUserName());
57 57
        assertEquals(USER_EMAIL, resetRequest.get().getUserEmail());
......
61 61
    @Test
62 62
    public void testTokenExpired() {
63 63
        passwordResetTokenStore.setTokenLifetimeMinutes(-10);
64
        String token = passwordResetTokenStore.create(testUser).getToken();
64
        String token = passwordResetTokenStore.create(USER_EMAIL, testUser).getToken();
65 65
        assertFalse(passwordResetTokenStore.isEligibleToken(token));
66
        Optional<PasswordResetRequest> resetRequest = passwordResetTokenStore.findResetRequest(token);
66
        Optional<PasswordResetRequest> resetRequest = passwordResetTokenStore.findRequest(token);
67 67
        assertTrue(!resetRequest.isPresent());
68 68
    }
69 69

  
......
71 71
    public void testTokenUnknown() {
72 72
        String unknownToken = "un-known-token";
73 73
        assertFalse(passwordResetTokenStore.isEligibleToken(unknownToken));
74
        Optional<PasswordResetRequest> resetRequest = passwordResetTokenStore.findResetRequest(unknownToken);
74
        Optional<PasswordResetRequest> resetRequest = passwordResetTokenStore.findRequest(unknownToken);
75 75
        assertTrue(!resetRequest.isPresent());
76 76
    }
77 77

  
......
79 79
    public void testTokenNull() {
80 80
        String nullToken = null;
81 81
        assertFalse(passwordResetTokenStore.isEligibleToken(nullToken));
82
        Optional<PasswordResetRequest> resetRequest = passwordResetTokenStore.findResetRequest(nullToken);
82
        Optional<PasswordResetRequest> resetRequest = passwordResetTokenStore.findRequest(nullToken);
83 83
        assertTrue(!resetRequest.isPresent());
84 84
    }
85 85

  
86 86

  
87 87
    @Test
88 88
    public void testTokenRemove() {
89
        String token = passwordResetTokenStore.create(testUser).getToken();
89
        String token = passwordResetTokenStore.create(USER_EMAIL, testUser).getToken();
90 90
        assertTrue(passwordResetTokenStore.isEligibleToken(token));
91
        Optional<PasswordResetRequest> resetRequest = passwordResetTokenStore.findResetRequest(token);
91
        Optional<PasswordResetRequest> resetRequest = passwordResetTokenStore.findRequest(token);
92 92
        assertTrue(resetRequest.isPresent());
93 93
        passwordResetTokenStore.remove(token);
94
        resetRequest = passwordResetTokenStore.findResetRequest(token);
94
        resetRequest = passwordResetTokenStore.findRequest(token);
95 95
        assertFalse("Expecing false since the token has been removed", resetRequest.isPresent());
96 96
    }
97 97

  
cdmlib-services/src/test/java/eu/etaxonomy/cdm/api/service/security/AccountRegistrationServiceTest.java
68 68
    private IAccountRegistrationService accountRegistrationService;
69 69

  
70 70
    @SpringBeanByName
71
    private IAbstractRequestTokenStore<AccountCreationRequest> accountCreationRequestTokenStore;
71
    private IAbstractRequestTokenStore<AccountCreationRequest, Object> accountCreationRequestTokenStore;
72 72

  
73 73
    @SpringBeanByType
74 74
    private JavaMailSender emailSender;
......
127 127
        createRequestTokenSendSignal = new CountDownLatch(1);
128 128
        accountCreatedSignal = new CountDownLatch(1);
129 129

  
130
        ListenableFuture<Boolean> emailResetFuture = accountRegistrationService.emailAccountRegistrationRequest(userEmail, userName, userPWD, requestFormUrlTemplate);
130
        ListenableFuture<Boolean> emailResetFuture = accountRegistrationService.emailAccountRegistrationRequest(userEmail, requestFormUrlTemplate);
131 131
        emailResetFuture.addCallback(
132 132
                requestSuccessVal -> {
133 133
                    createRequestTokenSendSignal.countDown();
......
162 162
        assertEquals(AbstractRequestTokenStore.TOKEN_LENGTH + 17, m.group(1).length());
163 163

  
164 164
        // -- change password
165
        ListenableFuture<Boolean> createAccountFuture = accountRegistrationService.createUserAccount(m.group(1), "Testor", "Nutzer", "Dr.");
165
        ListenableFuture<Boolean> createAccountFuture = accountRegistrationService.createUserAccount(m.group(1), userName, userPWD, "Testor", "Nutzer", "Dr.");
166 166
        createAccountFuture.addCallback(requestSuccessVal -> {
167 167
            accountCreatedSignal.countDown();
168 168
        }, futureException -> {
......
188 188
        createRequestTokenSendSignal = new CountDownLatch(1);
189 189

  
190 190
        accountRegistrationService.setRateLimiterTimeout(Duration.ofMillis(1)); // as should as possible to allow the fist call to be successful (with 1ns the fist call fails!)
191
        ListenableFuture<Boolean> emailResetFuture = accountRegistrationService.emailAccountRegistrationRequest("not-a-valid-email@#address#", userName, userPWD, requestFormUrlTemplate);
191
        ListenableFuture<Boolean> emailResetFuture = accountRegistrationService.emailAccountRegistrationRequest("not-a-valid-email@#address#", requestFormUrlTemplate);
192 192
        emailResetFuture.addCallback(
193 193
                requestSuccessVal -> {
194 194
                    createRequestTokenSendSignal.countDown();
......
214 214
        accountCreatedSignal = new CountDownLatch(1);
215 215

  
216 216
        // -- change password
217
        ListenableFuture<Boolean> resetPasswordFuture = accountRegistrationService.createUserAccount("IUER9843URIO--INVALID-TOKEN--UWEUR89EUWWEOIR", userName, null, null);
217
        ListenableFuture<Boolean> resetPasswordFuture = accountRegistrationService.createUserAccount("IUER9843URIO--INVALID-TOKEN--UWEUR89EUWWEOIR", userName, userPWD, null, null, null);
218 218
        resetPasswordFuture.addCallback(requestSuccessVal -> {
219 219
            accountCreatedSignal.countDown();
220 220
        }, futureException -> {
......
237 237

  
238 238
        createRequestTokenSendSignal = new CountDownLatch(1);
239 239

  
240
        ListenableFuture<Boolean> emailResetFuture = accountRegistrationService.emailAccountRegistrationRequest(userEmail, "admin", userPWD, requestFormUrlTemplate);
240
        ListenableFuture<Boolean> emailResetFuture = accountRegistrationService.emailAccountRegistrationRequest(userEmail, requestFormUrlTemplate);
241 241
        emailResetFuture.addCallback(
242 242
                requestSuccessVal -> {
243 243
                    createRequestTokenSendSignal.countDown();
......
249 249
        // -- wait for passwordResetService.emailResetToken() to complete
250 250
        createRequestTokenSendSignal.await();
251 251

  
252
        accountCreatedSignal = new CountDownLatch(1);
253

  
254
        // -- change password
255
        ListenableFuture<Boolean> resetPasswordFuture = accountRegistrationService.createUserAccount(userEmail, "admin", userPWD, null, null, null);
256
        resetPasswordFuture.addCallback(requestSuccessVal -> {
257
            accountCreatedSignal.countDown();
258
        }, futureException -> {
259
            assyncError =  futureException;
260
            accountCreatedSignal.countDown();
261
        });
262
        // -- wait for passwordResetService.resetPassword to complete
263
        accountCreatedSignal.await();
264

  
252 265
        assertNotNull(assyncError);
253 266
        assertEquals(AccountSelfManagementException.class, assyncError.getClass());
254 267
        assertEquals(AccountRegistrationService.USER_NAME_EXISTS_MSG, assyncError.getMessage());
cdmlib-services/src/test/java/eu/etaxonomy/cdm/api/service/security/PasswordResetServiceTest.java
68 68
    private IPasswordResetService passwordResetService;
69 69

  
70 70
    @SpringBeanByName
71
    private IAbstractRequestTokenStore<PasswordResetRequest> passwordResetTokenStore;
71
    private IAbstractRequestTokenStore<PasswordResetRequest, User> passwordResetTokenStore;
72 72

  
73 73
    @SpringBeanByType
74 74
    private JavaMailSender emailSender;

Also available in: Unified diff