PageRenderTime 123ms CodeModel.GetById 34ms app.highlight 81ms RepoModel.GetById 2ms app.codeStats 0ms

/org.amdatu.security.account/test/org/amdatu/security/account/admin/AccountAdminImplTest.java

https://bitbucket.org/amdatu/amdatu-security
Java | 680 lines | 478 code | 182 blank | 20 comment | 5 complexity | 5aaf144975d7df84adf4826657f9a3f3 MD5 | raw file
  1/*
  2 * Licensed under the Apache License, Version 2.0 (the "License");
  3 * you may not use this file except in compliance with the License.
  4 * You may obtain a copy of the License at
  5 *
  6 *      http://www.apache.org/licenses/LICENSE-2.0
  7 *
  8 * Unless required by applicable law or agreed to in writing, software
  9 * distributed under the License is distributed on an "AS IS" BASIS,
 10 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 11 * See the License for the specific language governing permissions and
 12 * limitations under the License.
 13 */
 14package org.amdatu.security.account.admin;
 15
 16import static org.amdatu.security.account.admin.AccountAdminConfig.KEY_ACCOUNT_REMOVAL_ALLOWED;
 17import static org.amdatu.security.account.admin.AccountAdminConfig.KEY_ACCOUNT_VERIFICATION_NEEDED;
 18import static org.junit.Assert.assertEquals;
 19import static org.junit.Assert.assertFalse;
 20import static org.junit.Assert.assertNotNull;
 21import static org.junit.Assert.assertNull;
 22import static org.junit.Assert.assertTrue;
 23import static org.mockito.ArgumentMatchers.any;
 24import static org.mockito.ArgumentMatchers.anyMap;
 25import static org.mockito.ArgumentMatchers.anyString;
 26import static org.mockito.Mockito.atLeast;
 27import static org.mockito.Mockito.doThrow;
 28import static org.mockito.Mockito.reset;
 29import static org.mockito.Mockito.verify;
 30import static org.mockito.Mockito.when;
 31
 32import java.util.Dictionary;
 33import java.util.HashMap;
 34import java.util.Hashtable;
 35import java.util.Map;
 36import java.util.Optional;
 37
 38import org.amdatu.security.account.Account;
 39import org.amdatu.security.account.Account.State;
 40import org.amdatu.security.account.AccountAdminBackend;
 41import org.amdatu.security.account.AccountCredentialResetException;
 42import org.amdatu.security.account.AccountException;
 43import org.amdatu.security.account.AccountLockedException;
 44import org.amdatu.security.account.AccountValidationException;
 45import org.amdatu.security.account.AccountValidator;
 46import org.amdatu.security.account.NoSuchAccountException;
 47import org.amdatu.security.account.TestPasswordHasher;
 48import org.amdatu.security.account.UnverifiedAccountException;
 49import org.amdatu.security.password.hash.PasswordHasher;
 50import org.amdatu.security.tokenprovider.InvalidTokenException;
 51import org.amdatu.security.tokenprovider.InvalidTokenException.Reason;
 52import org.amdatu.security.tokenprovider.TokenProvider;
 53import org.junit.Before;
 54import org.junit.Rule;
 55import org.junit.Test;
 56import org.junit.rules.ExpectedException;
 57import org.junit.runner.RunWith;
 58import org.mockito.InjectMocks;
 59import org.mockito.Mock;
 60import org.mockito.Spy;
 61import org.mockito.junit.MockitoJUnitRunner;
 62import org.osgi.service.event.EventAdmin;
 63import org.osgi.service.log.LogService;
 64
 65/**
 66 * Test cases for {@link AccountAdminImpl}.
 67 */
 68@RunWith(MockitoJUnitRunner.class)
 69public class AccountAdminImplTest {
 70    private static final String SECRET_PLAIN = "secret";
 71    private static final String SECRET_SHA256 = "$5$K7gNU3sdo+OL0wNhqoVWhr3g6s1xYv72ol/pe/Unols=";
 72
 73    private static final String PASSWORD_PLAIN = "password";
 74    private static final String PASSWORD_SHA256 = "$5$XohImNooBHFR0OVvjcYpJ3NgPQ1qq73WKhHvch0VQtg=";
 75
 76    private static final String EXISTING_ACCOUNT_ID = "existing_user@amdatu.org";
 77    private static final String NEW_ACCOUNT_ID = "new_user@amdatu.org";
 78    private static final String LOCKED_ACCOUNT_ID = "bad_user@amdatu.org";
 79    private static final String NON_EXISTING_ACCOUNT_ID = "does_not_exist@amdatu.org";
 80
 81    private PasswordHasher m_pwdHasher = new TestPasswordHasher();
 82    @Spy
 83    private AccountAdminBackend m_backend = new MockAccountAdminBackend();
 84    @Mock
 85    private AccountValidator m_accountValidator;
 86    @Mock
 87    private EventAdmin m_eventAdmin;
 88    @Mock
 89    private LogService m_logService;
 90    @Mock
 91    private TokenProvider m_tokenProvider;
 92    @InjectMocks
 93    private AccountAdminImpl m_accountAdmin = new AccountAdminImpl(m_backend, m_pwdHasher);
 94
 95    @Rule
 96    public final ExpectedException m_rule = ExpectedException.none();
 97
 98    private static Dictionary<String, Object> asDictionary(String... entries) {
 99        Dictionary<String, Object> result = new Hashtable<>();
100        for (int i = 0; i < entries.length; i += 2) {
101            result.put(entries[i], entries[i + 1]);
102        }
103        return result;
104    }
105
106    private static Map<String, String> asMap(String... entries) {
107        Map<String, String> result = new HashMap<>();
108        for (int i = 0; i < entries.length; i += 2) {
109            result.put(entries[i], entries[i + 1]);
110        }
111        return result;
112    }
113
114    private static Map<String, String> createCredentials(String email, String password) {
115        return asMap("email", email, "password", password);
116    }
117
118    @Before
119    @SuppressWarnings("unchecked")
120    public void setUp() throws Exception {
121        when(m_tokenProvider.generateToken(anyMap())).thenAnswer(mock -> {
122            String sub = ((Map<String, String>) mock.getArguments()[0]).get("sub");
123            return sub;
124        });
125        when(m_tokenProvider.verifyToken(anyString())).thenAnswer(mock -> {
126            String token = mock.getArguments()[0].toString();
127            if (EXISTING_ACCOUNT_ID.equals(token) || NEW_ACCOUNT_ID.equals(token) || LOCKED_ACCOUNT_ID.equals(token)) {
128                return asMap("sub", token);
129            }
130            throw new InvalidTokenException(Reason.UNKNOWN, "invalid token!", null);
131        });
132
133        // Inject a couple of accounts with specific properties...
134        Map<String, String> creds = createCredentials(EXISTING_ACCOUNT_ID, m_pwdHasher.hash(SECRET_PLAIN));
135        m_backend.update(new Account(EXISTING_ACCOUNT_ID, creds, State.NORMAL, null, false /* locked */));
136
137        creds = createCredentials(LOCKED_ACCOUNT_ID, m_pwdHasher.hash("bad"));
138        m_backend.update(new Account(LOCKED_ACCOUNT_ID, creds, State.NORMAL, null, true /* locked */));
139
140        when(m_backend.accountExists(EXISTING_ACCOUNT_ID)).thenReturn(Boolean.TRUE);
141
142        m_accountAdmin.updated(null); // ensure we've got a default configuration...
143
144        reset(m_backend); // make sure we've got a clear state...
145    }
146
147    @Test
148    public void testAccountExists() throws Exception {
149        assertTrue(m_accountAdmin.accountExists(EXISTING_ACCOUNT_ID));
150        assertFalse(m_accountAdmin.accountExists(NON_EXISTING_ACCOUNT_ID));
151        assertFalse(m_accountAdmin.accountExists(null));
152    }
153
154    @Test
155    public void testCreateAccount() throws Exception {
156        Account account = m_accountAdmin.createAccount(createCredentials(NEW_ACCOUNT_ID, SECRET_PLAIN));
157        assertNotNull(account);
158
159        assertEquals(NEW_ACCOUNT_ID, account.getId());
160        assertEquals(NEW_ACCOUNT_ID, account.getCredentials().get("email"));
161        assertEquals(SECRET_SHA256, account.getCredentials().get("password"));
162        assertEquals(State.ACCOUNT_VERIFICATION_NEEDED, account.getState());
163        assertEquals(Optional.of(NEW_ACCOUNT_ID), account.getAccessToken());
164    }
165
166    @Test
167    public void testCreateAccount_AccountExists() throws Exception {
168        m_rule.expect(AccountException.class);
169
170        assertNull(m_accountAdmin.createAccount(createCredentials(EXISTING_ACCOUNT_ID, SECRET_PLAIN)));
171    }
172
173    @Test
174    public void testCreateAccount_AccountValidationFails() throws Exception {
175        doThrow(new AccountValidationException()).when(m_accountValidator).validate(any());
176
177        m_rule.expect(AccountValidationException.class);
178
179        assertNull(m_accountAdmin.createAccount(createCredentials(NEW_ACCOUNT_ID, PASSWORD_PLAIN)));
180    }
181
182    @Test
183    public void testCreateAccount_EmptyCredentials() throws Exception {
184        m_rule.expect(AccountException.class);
185
186        assertNull(m_accountAdmin.createAccount(asMap()));
187    }
188
189    @Test
190    public void testCreateAccount_MissingAccountId() throws Exception {
191        m_rule.expect(AccountException.class);
192
193        assertNull(m_accountAdmin.createAccount(asMap("password", "secret")));
194    }
195
196    @Test
197    public void testCreateAccount_MissingPassword() throws Exception {
198        m_rule.expect(AccountException.class);
199
200        assertNull(m_accountAdmin.createAccount(asMap("email", EXISTING_ACCOUNT_ID)));
201    }
202
203    @Test
204    public void testCreateAccount_NoVerificationNeeded() throws Exception {
205        m_accountAdmin.updated(asDictionary(KEY_ACCOUNT_VERIFICATION_NEEDED, "false"));
206
207        Account account = m_accountAdmin.createAccount(createCredentials(NEW_ACCOUNT_ID, PASSWORD_PLAIN));
208        assertNotNull(account);
209
210        assertEquals(NEW_ACCOUNT_ID, account.getId());
211        assertEquals(NEW_ACCOUNT_ID, account.getCredentials().get("email"));
212        assertEquals(PASSWORD_SHA256, account.getCredentials().get("password"));
213        assertEquals(State.NORMAL, account.getState());
214        assertEquals(Optional.of(NEW_ACCOUNT_ID), account.getAccessToken());
215    }
216
217    @Test
218    public void testGetAccount() throws Exception {
219        Optional<Account> account = m_accountAdmin.getAccount(createCredentials(EXISTING_ACCOUNT_ID, SECRET_PLAIN));
220        assertNotNull(account);
221
222        assertTrue(account.isPresent());
223    }
224
225    @Test
226    public void testGetAccount_ForcedCredentialsReset() throws Exception {
227        m_accountAdmin.resetCredentials(EXISTING_ACCOUNT_ID, true /* force */);
228
229        m_rule.expect(AccountCredentialResetException.class);
230
231        assertNull(m_accountAdmin.getAccount(createCredentials(EXISTING_ACCOUNT_ID, SECRET_PLAIN)));
232    }
233
234    @Test
235    public void testGetAccount_IncorrectCredentials() throws Exception {
236        Optional<Account> account;
237
238        // Wrong password...
239        account = m_accountAdmin.getAccount(createCredentials(EXISTING_ACCOUNT_ID, "incorrect"));
240        assertNotNull(account);
241
242        assertFalse(account.isPresent());
243
244        // Wrong email address...
245        account = m_accountAdmin.getAccount(createCredentials(NON_EXISTING_ACCOUNT_ID, SECRET_PLAIN));
246        assertNotNull(account);
247
248        assertFalse(account.isPresent());
249    }
250
251    @Test
252    public void testGetAccount_LockedAccount() throws Exception {
253        m_rule.expect(AccountLockedException.class);
254
255        assertNull(m_accountAdmin.getAccount(createCredentials(LOCKED_ACCOUNT_ID, "bad")));
256    }
257
258    @Test
259    public void testGetAccount_NonExistingAccount() throws Exception {
260        Optional<Account> account = m_accountAdmin.getAccount(createCredentials(NON_EXISTING_ACCOUNT_ID, SECRET_PLAIN));
261        assertNotNull(account);
262
263        assertFalse(account.isPresent());
264    }
265
266    @Test
267    public void testGetAccount_UnverifiedAccount() throws Exception {
268        m_accountAdmin.createAccount(createCredentials(NEW_ACCOUNT_ID, SECRET_PLAIN));
269
270        m_rule.expect(UnverifiedAccountException.class);
271
272        assertNull(m_accountAdmin.getAccount(createCredentials(NEW_ACCOUNT_ID, SECRET_PLAIN)));
273    }
274
275    @Test
276    public void testGetAccount_WithAccessToken() throws Exception {
277        Account account = m_accountAdmin.createAccount(createCredentials(NEW_ACCOUNT_ID, PASSWORD_PLAIN));
278        assertNotNull(account);
279
280        String token = account.getAccessToken().get(); // cannot fail!
281
282        account = m_accountAdmin.getAccountByAccessToken(token);
283
284        assertNotNull(account);
285    }
286
287    @Test
288    public void testGetAccount_WithAccessTokenForAccountWithoutToken() throws Exception {
289        m_rule.expect(NoSuchAccountException.class);
290
291        assertNull(m_accountAdmin.getAccountByAccessToken(EXISTING_ACCOUNT_ID));
292    }
293
294    @Test
295    public void testGetAccount_WithAccessTokenForLockedAccount() throws Exception {
296        m_rule.expect(AccountLockedException.class);
297
298        assertNull(m_accountAdmin.getAccountByAccessToken(LOCKED_ACCOUNT_ID));
299    }
300
301    @Test
302    public void testGetAccount_WithInvalidAccessToken() throws Exception {
303        m_rule.expect(NoSuchAccountException.class);
304
305        assertNull(m_accountAdmin.getAccountByAccessToken("someToken"));
306    }
307
308    @Test
309    public void testGetAccount_WithPartialMissingCredentials() throws Exception {
310        Map<String, String> creds;
311
312        creds = asMap("email", EXISTING_ACCOUNT_ID, "foo", "bar");
313
314        assertFalse(m_accountAdmin.getAccount(creds).isPresent());
315
316        creds = asMap("password", "bar", "foo", "bar");
317
318        assertFalse(m_accountAdmin.getAccount(creds).isPresent());
319
320        creds = asMap("foo", "bar");
321
322        assertFalse(m_accountAdmin.getAccount(creds).isPresent());
323
324        creds = asMap();
325
326        assertFalse(m_accountAdmin.getAccount(creds).isPresent());
327    }
328
329    @Test
330    public void testGetAccount_WithSuperfluousCredentials() throws Exception {
331        Map<String, String> creds = createCredentials(EXISTING_ACCOUNT_ID, SECRET_PLAIN);
332        // Add some additional credentials that aren't present in the stored account...
333        creds.put("type", "local");
334        creds.put("other", "token");
335
336        Optional<Account> account = m_accountAdmin.getAccount(creds);
337        assertNotNull(account);
338
339        assertTrue(account.isPresent());
340    }
341
342    @Test
343    public void testRemoveAccount() throws Exception {
344        m_accountAdmin.updated(asDictionary(KEY_ACCOUNT_REMOVAL_ALLOWED, "true"));
345
346        Account account = m_accountAdmin.removeAccount(EXISTING_ACCOUNT_ID);
347        assertNotNull(account);
348
349        assertEquals(EXISTING_ACCOUNT_ID, account.getId());
350        assertEquals(EXISTING_ACCOUNT_ID, account.getCredentials().get("email"));
351    }
352
353    @Test
354    public void testRemoveAccount_NonExistingAccount() throws Exception {
355        m_accountAdmin.updated(asDictionary(KEY_ACCOUNT_REMOVAL_ALLOWED, "true"));
356
357        m_rule.expect(NoSuchAccountException.class);
358
359        assertNull(m_accountAdmin.removeAccount(NON_EXISTING_ACCOUNT_ID));
360    }
361
362    @Test
363    public void testRemoveAccount_NotAllowed() throws Exception {
364        m_accountAdmin.updated(asDictionary(KEY_ACCOUNT_REMOVAL_ALLOWED, "false"));
365
366        m_rule.expect(AccountException.class);
367
368        assertNull(m_accountAdmin.removeAccount(EXISTING_ACCOUNT_ID));
369    }
370
371    @Test
372    public void testRemoveAccount_NotAllowedByBackend() throws Exception {
373        m_accountAdmin.updated(asDictionary(KEY_ACCOUNT_REMOVAL_ALLOWED, "true"));
374        ((MockAccountAdminBackend) m_backend).setRemovalSupported(false);
375
376        m_rule.expect(AccountException.class);
377
378        assertNull(m_accountAdmin.removeAccount(EXISTING_ACCOUNT_ID));
379    }
380
381    @Test
382    public void testResetCredentials_Forced() throws Exception {
383        Account account = m_accountAdmin.getAccount(createCredentials(EXISTING_ACCOUNT_ID, SECRET_PLAIN)).get();
384
385        account = m_accountAdmin.resetCredentials(EXISTING_ACCOUNT_ID, true /* forced */);
386
387        assertEquals(EXISTING_ACCOUNT_ID, account.getAccessToken().get());
388
389        assertEquals(State.FORCED_CREDENTIALS_RESET, account.getState());
390
391        verify(m_backend).update(account);
392    }
393
394    @Test
395    public void testResetCredentials_ForcedFlagNotCleared() throws Exception {
396        Account account = m_accountAdmin.getAccount(createCredentials(EXISTING_ACCOUNT_ID, SECRET_PLAIN)).get();
397
398        account = m_accountAdmin.resetCredentials(EXISTING_ACCOUNT_ID, true /* forced */);
399
400        assertEquals(EXISTING_ACCOUNT_ID, account.getAccessToken().get());
401
402        assertEquals(State.FORCED_CREDENTIALS_RESET, account.getState());
403
404        m_rule.expect(AccountCredentialResetException.class);
405
406        assertNull(m_accountAdmin.getAccount(createCredentials(EXISTING_ACCOUNT_ID, SECRET_PLAIN)));
407    }
408
409    @Test
410    public void testResetCredentials_ForcedTwice() throws Exception {
411        Account account = m_accountAdmin.getAccount(createCredentials(EXISTING_ACCOUNT_ID, SECRET_PLAIN)).get();
412
413        account = m_accountAdmin.resetCredentials(EXISTING_ACCOUNT_ID, true /* forced */);
414
415        assertTrue(account.getAccessToken().isPresent());
416
417        account = m_accountAdmin.resetCredentials(EXISTING_ACCOUNT_ID, true /* forced */);
418
419        assertEquals(State.FORCED_CREDENTIALS_RESET, account.getState());
420
421        verify(m_backend, atLeast(2)).update(account);
422    }
423
424    @Test
425    public void testResetCredentials_LockedAccount() throws Exception {
426        m_rule.expect(AccountLockedException.class);
427
428        assertNull(m_accountAdmin.resetCredentials(LOCKED_ACCOUNT_ID, false /* forced */));
429    }
430
431    @Test
432    public void testResetCredentials_NonExistingAccount() throws Exception {
433        m_rule.expect(NoSuchAccountException.class);
434
435        assertNull(m_accountAdmin.resetCredentials(NON_EXISTING_ACCOUNT_ID, false /* forced */));
436    }
437
438    @Test
439    public void testResetCredentials_RequestForcedResetAfterVoluntaryReset() throws Exception {
440        Account account = m_accountAdmin.getAccount(createCredentials(EXISTING_ACCOUNT_ID, SECRET_PLAIN)).get();
441
442        account = m_accountAdmin.resetCredentials(EXISTING_ACCOUNT_ID, false /* forced */);
443
444        assertTrue(account.getAccessToken().isPresent());
445        assertEquals(State.VOLUNTARY_CREDENTIALS_RESET, account.getState());
446
447        account = m_accountAdmin.resetCredentials(EXISTING_ACCOUNT_ID, true /* forced */);
448
449        assertEquals(State.FORCED_CREDENTIALS_RESET, account.getState());
450
451        verify(m_backend, atLeast(2)).update(account);
452    }
453
454    @Test
455    public void testResetCredentials_RequestVoluntaryResetAfterForcedReset() throws Exception {
456        Account account = m_accountAdmin.getAccount(createCredentials(EXISTING_ACCOUNT_ID, SECRET_PLAIN)).get();
457
458        account = m_accountAdmin.resetCredentials(EXISTING_ACCOUNT_ID, true /* forced */);
459
460        assertTrue(account.getAccessToken().isPresent());
461        assertEquals(State.FORCED_CREDENTIALS_RESET, account.getState());
462
463        account = m_accountAdmin.resetCredentials(EXISTING_ACCOUNT_ID, false /* forced */);
464
465        assertEquals(State.FORCED_CREDENTIALS_RESET, account.getState());
466
467        verify(m_backend, atLeast(2)).update(account);
468    }
469
470    @Test
471    public void testResetCredentials_Twice() throws Exception {
472        Account account = m_accountAdmin.getAccount(createCredentials(EXISTING_ACCOUNT_ID, SECRET_PLAIN)).get();
473
474        account = m_accountAdmin.resetCredentials(EXISTING_ACCOUNT_ID, false /* forced */);
475
476        assertTrue(account.getAccessToken().isPresent());
477        assertEquals(State.VOLUNTARY_CREDENTIALS_RESET, account.getState());
478
479        account = m_accountAdmin.resetCredentials(EXISTING_ACCOUNT_ID, false /* forced */);
480
481        assertEquals(State.VOLUNTARY_CREDENTIALS_RESET, account.getState());
482
483        verify(m_backend, atLeast(2)).update(account);
484    }
485
486    @Test
487    public void testResetCredentials_UnverifiedAccount() throws Exception {
488        Account account = m_accountAdmin.createAccount(createCredentials(NEW_ACCOUNT_ID, SECRET_PLAIN));
489        assertNotNull(account);
490
491        m_rule.expect(AccountCredentialResetException.class);
492
493        assertNull(m_accountAdmin.resetCredentials(NEW_ACCOUNT_ID, true /* forced */));
494    }
495
496    @Test
497    public void testResetCredentials_Voluntary() throws Exception {
498        Account account = m_accountAdmin.getAccount(createCredentials(EXISTING_ACCOUNT_ID, SECRET_PLAIN)).get();
499
500        assertFalse(account.getAccessToken().isPresent());
501
502        account = m_accountAdmin.resetCredentials(EXISTING_ACCOUNT_ID, false /* forced */);
503
504        assertTrue(account.getAccessToken().isPresent());
505        assertEquals(State.VOLUNTARY_CREDENTIALS_RESET, account.getState());
506
507        verify(m_backend).update(account);
508    }
509
510    @Test
511    public void testResetCredentials_VoluntaryFlagClearedAfterSuccessfulGet() throws Exception {
512        Account account = m_accountAdmin.getAccount(createCredentials(EXISTING_ACCOUNT_ID, SECRET_PLAIN)).get();
513
514        account = m_accountAdmin.resetCredentials(EXISTING_ACCOUNT_ID, false /* forced */);
515
516        assertEquals(State.VOLUNTARY_CREDENTIALS_RESET, account.getState());
517
518        account = m_accountAdmin.getAccount(createCredentials(EXISTING_ACCOUNT_ID, SECRET_PLAIN)).get();
519
520        verify(m_backend, atLeast(2)).update(account);
521
522        assertEquals(State.NORMAL, account.getState());
523    }
524
525    @Test
526    public void testUpdateAccount_AccountValidationFails() throws Exception {
527        Map<String, String> creds = createCredentials(EXISTING_ACCOUNT_ID, "secret");
528
529        doThrow(new AccountValidationException()).when(m_accountValidator).validate(any());
530
531        m_rule.expect(AccountValidationException.class);
532
533        assertNull(m_accountAdmin.updateAccount(creds, creds));
534    }
535
536    @Test
537    public void testUpdateAccount_LockedAccount() throws Exception {
538        Map<String, String> creds = createCredentials(LOCKED_ACCOUNT_ID, "bad");
539
540        m_rule.expect(AccountLockedException.class);
541
542        assertNull(m_accountAdmin.updateAccount(creds, creds));
543    }
544
545    @Test
546    public void testUpdateAccount_NonExistingAccount() throws Exception {
547        m_rule.expect(NoSuchAccountException.class);
548
549        Map<String, String> creds = createCredentials(NON_EXISTING_ACCOUNT_ID, "bad");
550
551        assertNull(m_accountAdmin.updateAccount(creds, creds));
552    }
553
554    @Test
555    public void testUpdateAccount_NoResetTokenRequested() throws Exception {
556        m_rule.expect(NoSuchAccountException.class);
557
558        assertNull(m_accountAdmin.updateAccount(createCredentials(EXISTING_ACCOUNT_ID, "password"), EXISTING_ACCOUNT_ID));
559    }
560
561    @Test
562    public void testUpdateAccount_WithInvalidResetToken() throws Exception {
563        Account account = m_accountAdmin.resetCredentials(EXISTING_ACCOUNT_ID, false /* forced */);
564        assertTrue(account.getAccessToken().isPresent());
565
566        m_rule.expect(NoSuchAccountException.class);
567
568        assertNull(m_accountAdmin.updateAccount(createCredentials(EXISTING_ACCOUNT_ID, "password"), "invalidToken"));
569    }
570
571    @Test
572    public void testUpdateAccount_WithoutResetToken() throws Exception {
573        Map<String, String> oldCreds = createCredentials(EXISTING_ACCOUNT_ID, SECRET_PLAIN);
574        Map<String, String> newCreds = createCredentials(EXISTING_ACCOUNT_ID, PASSWORD_PLAIN);
575
576        Account account = m_accountAdmin.updateAccount(oldCreds, newCreds);
577        assertNotNull(account);
578
579        assertEquals(EXISTING_ACCOUNT_ID, account.getId());
580        assertEquals(EXISTING_ACCOUNT_ID, account.getCredentials().get("email"));
581        assertEquals(PASSWORD_SHA256, account.getCredentials().get("password"));
582        assertEquals(State.NORMAL, account.getState());
583        assertEquals(Optional.empty(), account.getAccessToken());
584    }
585
586    @Test
587    public void testUpdateAccount_WithoutResetToken_ForcedUpdate() throws Exception {
588        Account account = m_accountAdmin.resetCredentials(EXISTING_ACCOUNT_ID, true /* forced */);
589        assertTrue(account.getAccessToken().isPresent());
590
591        Map<String, String> oldCreds = createCredentials(EXISTING_ACCOUNT_ID, SECRET_PLAIN);
592        Map<String, String> newCreds = createCredentials(EXISTING_ACCOUNT_ID, "password");
593
594        m_rule.expect(AccountCredentialResetException.class);
595
596        assertNotNull(m_accountAdmin.updateAccount(oldCreds, newCreds));
597    }
598
599    @Test
600    public void testUpdateAccount_WithoutResetToken_InvalidOldCredentials() throws Exception {
601        Map<String, String> oldCreds = createCredentials(EXISTING_ACCOUNT_ID, "incorrect");
602        Map<String, String> newCreds = createCredentials(EXISTING_ACCOUNT_ID, "password");
603
604        m_rule.expect(NoSuchAccountException.class);
605
606        assertNull(m_accountAdmin.updateAccount(oldCreds, newCreds));
607    }
608
609    @Test
610    public void testUpdateAccount_WithResetToken() throws Exception {
611        Account account = m_accountAdmin.resetCredentials(EXISTING_ACCOUNT_ID, false /* forced */);
612        assertTrue(account.getAccessToken().isPresent());
613
614        account = m_accountAdmin.updateAccount(createCredentials(EXISTING_ACCOUNT_ID, PASSWORD_PLAIN), EXISTING_ACCOUNT_ID);
615
616        assertEquals(EXISTING_ACCOUNT_ID, account.getId());
617        assertEquals(EXISTING_ACCOUNT_ID, account.getCredentials().get("email"));
618        assertEquals(PASSWORD_SHA256, account.getCredentials().get("password"));
619        assertEquals(State.NORMAL, account.getState());
620        assertEquals(Optional.empty(), account.getAccessToken());
621    }
622
623    @Test
624    public void testUpdateAccount_WithResetToken_AccountValidationFails() throws Exception {
625        Account account = m_accountAdmin.resetCredentials(EXISTING_ACCOUNT_ID, false /* forced */);
626        assertTrue(account.getAccessToken().isPresent());
627
628        doThrow(new AccountValidationException()).when(m_accountValidator).validate(any());
629
630        m_rule.expect(AccountValidationException.class);
631
632        assertNull(m_accountAdmin.updateAccount(createCredentials(EXISTING_ACCOUNT_ID, "password"), EXISTING_ACCOUNT_ID));
633    }
634
635    @Test
636    public void testUpdateAccount_WithResetToken_LockedAccount() throws Exception {
637        m_rule.expect(AccountLockedException.class);
638
639        assertNull(m_accountAdmin.updateAccount(createCredentials(LOCKED_ACCOUNT_ID, "password"), LOCKED_ACCOUNT_ID));
640    }
641
642    @Test
643    public void testVerifyAccount() throws Exception {
644        Account account = m_accountAdmin.createAccount(createCredentials(NEW_ACCOUNT_ID, SECRET_PLAIN));
645        assertNotNull(account);
646
647        account = m_accountAdmin.verifyAccount(NEW_ACCOUNT_ID, NEW_ACCOUNT_ID);
648        assertNotNull(account);
649
650        assertEquals(NEW_ACCOUNT_ID, account.getId());
651        assertEquals(NEW_ACCOUNT_ID, account.getCredentials().get("email"));
652        assertEquals(SECRET_SHA256, account.getCredentials().get("password"));
653        assertEquals(State.NORMAL, account.getState());
654        assertEquals(Optional.empty(), account.getAccessToken());
655    }
656
657    @Test
658    public void testVerifyAccount_WithInvalidVerificationToken() throws Exception {
659        Account account = m_accountAdmin.createAccount(createCredentials(NEW_ACCOUNT_ID, SECRET_PLAIN));
660        assertNotNull(account);
661
662        m_rule.expect(AccountException.class);
663
664        assertNull(m_accountAdmin.verifyAccount(NEW_ACCOUNT_ID, "invalidToken"));
665    }
666
667    @Test
668    public void testVerifyAccount_WithInvalidVerificationToken2() throws Exception {
669        m_rule.expect(AccountException.class);
670
671        assertNull(m_accountAdmin.verifyAccount(EXISTING_ACCOUNT_ID, EXISTING_ACCOUNT_ID));
672    }
673
674    @Test
675    public void testVerifyAccount_WithResetToken_LockedAccount() throws Exception {
676        m_rule.expect(AccountLockedException.class);
677
678        assertNull(m_accountAdmin.verifyAccount(LOCKED_ACCOUNT_ID, LOCKED_ACCOUNT_ID));
679    }
680}