/org.amdatu.security.account/test/org/amdatu/security/account/admin/AccountAdminImplTest.java
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}