XmlUserManager implements UserManager { @Override public User getUser(final String username, final String password) throws UserManagerException { if (username == null || username.trim().isEmpty()) { throw new UserManagerException("Username is empty."); } else if (password == null || password.trim().isEmpty()) { throw new UserManagerException("Password is empty."); } String foundPassword = null; User user = null; synchronized (this) { foundPassword = this.userPassword.get(username); if (foundPassword != null) { user = this.users.get(username); } } if (foundPassword == null || !foundPassword.equals(password)) { throw new UserManagerException("Username/Password not found."); } if (user == null) { throw new UserManagerException("Internal error: User not found."); } resolveGroupRoles(user); user.setPermissions(new UserPermissions() { @Override public boolean hasPermission(final String permission) { return true; } @Override public void addPermission(final String permission) { } }); return user; } XmlUserManager(final Props props);   XmlUserManager(final Props props, final FileWatcherFactory fileWatcherFactory); @Override User getUser(final String username, final String password); @Override boolean validateUser(final String username); @Override Role getRole(final String roleName); @Override boolean validateGroup(final String group); @Override boolean validateProxyUser(final String proxyUser, final User realUser); static final String XML_FILE_PARAM; static final String AZKABAN_USERS_TAG; static final String USER_TAG; static final String ROLE_TAG; static final String GROUP_TAG; static final String ROLENAME_ATTR; static final String ROLEPERMISSIONS_ATTR; static final String USERNAME_ATTR; static final String PASSWORD_ATTR; static final String EMAIL_ATTR; static final String ROLES_ATTR; static final String PROXY_ATTR; static final String GROUPS_ATTR; static final String GROUPNAME_ATTR; }
@Test public void testAutoReload() throws Exception { final Props props = new Props(this.baseProps); final Path filePath = getFilePath("testAutoReload"); props.put(XmlUserManager.XML_FILE_PARAM, filePath.toString()); final CountDownLatch managerLoaded = setupMocks(filePath); final UserManager manager = new XmlUserManager(props, () -> this.fileWatcher); User user8 = manager.getUser("user8", "password8"); final List<String> lines = new ArrayList<>(); for (final String line : Files.readAllLines(filePath)) { if (line.contains("password8")) { lines.add(line.replace("password8", "passwordModified")); } else { lines.add(line); } } Files.write(filePath, lines); managerLoaded.countDown(); Awaitility.await().atMost(10L, TimeUnit.SECONDS). pollInterval(10L, TimeUnit.MILLISECONDS).until( () -> { User user; try { user = manager.getUser("user8", "password8"); } catch (final UserManagerException e) { user = null; } return user == null; }); user8 = manager.getUser("user8", "passwordModified"); assertEquals("user8", user8.getUserId()); Mockito.verify(this.fileWatcher, Mockito.timeout(10_000L).atLeast(3)).take(); }
@Test public void testAutoReloadFail() throws Exception { final Props props = new Props(this.baseProps); final Path filePath = getFilePath("testAutoReloadFail"); props.put(XmlUserManager.XML_FILE_PARAM, filePath.toString()); final CountDownLatch managerLoaded = setupMocks(filePath); final UserManager manager; try { manager = new XmlUserManager(props, () -> this.fileWatcher); } catch (final RuntimeException e) { fail("Should have found the xml file"); return; } final User user8 = manager.getUser("user8", "password8"); assertEquals("user8", user8.getUserId()); Files.write(filePath, new byte[0], StandardOpenOption.TRUNCATE_EXISTING); managerLoaded.countDown(); managerLoaded.await(10L, TimeUnit.SECONDS); assertEquals(0, managerLoaded.getCount()); Mockito.verify(this.fileWatcher, Mockito.timeout(10_000L).atLeast(3)).take(); final User user = manager.getUser("user8", "password8"); assertEquals("user8", user.getUserId()); }
@Ignore @Test public void testBasicLoad() throws Exception { final Props props = new Props(this.baseProps); props.put(XmlUserManager.XML_FILE_PARAM, "unit/test-conf/azkaban-users-test1.xml"); UserManager manager = null; try { manager = new XmlUserManager(props, () -> this.fileWatcher); } catch (final RuntimeException e) { e.printStackTrace(); fail("XmlUserManager should've found file azkaban-users.xml"); } try { manager.getUser("user0", null); } catch (final UserManagerException e) { System.out.println("Exception handled correctly: " + e.getMessage()); } try { manager.getUser(null, "etw"); } catch (final UserManagerException e) { System.out.println("Exception handled correctly: " + e.getMessage()); } try { manager.getUser("user0", "user0"); } catch (final UserManagerException e) { System.out.println("Exception handled correctly: " + e.getMessage()); } try { manager.getUser("user0", "password0"); } catch (final UserManagerException e) { e.printStackTrace(); fail("XmlUserManager should've returned a user."); } final User user0 = manager.getUser("user0", "password0"); checkUser(user0, "role0", "group0"); final User user1 = manager.getUser("user1", "password1"); checkUser(user1, "role0,role1", "group1,group2"); final User user2 = manager.getUser("user2", "password2"); checkUser(user2, "role0,role1,role2", "group1,group2,group3"); final User user3 = manager.getUser("user3", "password3"); checkUser(user3, "role1,role2", "group1,group2"); final User user4 = manager.getUser("user4", "password4"); checkUser(user4, "role1,role2", "group1,group2"); final User user5 = manager.getUser("user5", "password5"); checkUser(user5, "role1,role2", "group1,group2"); final User user6 = manager.getUser("user6", "password6"); checkUser(user6, "role3,role2", "group1,group2"); final User user7 = manager.getUser("user7", "password7"); checkUser(user7, "", "group1"); final User user8 = manager.getUser("user8", "password8"); checkUser(user8, "role3", ""); final User user9 = manager.getUser("user9", "password9"); checkUser(user9, "", ""); }