package de.otto.hmac.repository; import de.otto.hmac.authentication.UserRepository; import de.otto.hmac.authorization.RoleRepository; import org.w3c.dom.Document; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import javax.xml.parsers.ParserConfigurationException; import java.io.IOException; import java.io.InputStream; import java.util.HashSet; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentSkipListSet; import static java.util.Arrays.asList; import static javax.xml.parsers.DocumentBuilderFactory.newInstance; public class FileSystemUserRepository implements UserRepository, RoleRepository { private final ConcurrentMap<String, String> userToKey = new ConcurrentHashMap<>(); private final ConcurrentMap<String, Set<String>> userToRole = new ConcurrentHashMap<>(); public FileSystemUserRepository(final String authXmlResource) { try { loadAuthXml(FileSystemUserRepository.class.getResourceAsStream(authXmlResource)); } catch (ParserConfigurationException | IOException | SAXException e) { throw new RuntimeException("failed to load auth xml", e); } } private void loadAuthXml(final InputStream authXml) throws IOException, ParserConfigurationException, SAXException { try (final InputStream inputStream = authXml) { final Document document = newInstance().newDocumentBuilder().parse(inputStream); loadAuthXml(document, userToKey, userToRole); } } @Override public String getKey(final String username) { return userToKey.get(username); } @Override public boolean hasRole(final String user, final String role) { return getRolesForUser(user).contains(role); } @Override public Set<String> getRolesForUser(final String user) { final Set<String> roles = new HashSet<>(); if (user != null) { final Set<String> userRoles = userToRole.get(user); if (userRoles != null) { roles.addAll(userRoles); } } roles.add("everybody"); return roles; } private void loadAuthXml(final Document document, final ConcurrentMap<String, String> userToKey, final ConcurrentMap<String, Set<String>> userToRole) { NodeList ndList = document.getElementsByTagName("user"); for (int i = 0; i < ndList.getLength(); i++) { Node item = ndList.item(i); NamedNodeMap attributes = item.getAttributes(); final String username = attributes.getNamedItem("name").getTextContent(); userToKey.put( username, attributes.getNamedItem("key").getTextContent() ); if (attributes.getNamedItem("roles") != null) { final String roles = attributes.getNamedItem("roles").getTextContent(); userToRole.put( username, new ConcurrentSkipListSet<>(asList(roles.split(","))) ); } } } }