[Major] Rewrote privilege XML to use SAX for writing and parsing
This commit is contained in:
parent
96b24ca03d
commit
bcba0264e4
|
@ -104,7 +104,7 @@ public abstract class BaseLdapPrivilegeHandler extends DefaultPrivilegeHandler {
|
|||
this.persistenceHandler.replaceUser(user);
|
||||
|
||||
if (this.autoPersistOnUserChangesData)
|
||||
this.persistenceHandler.persist();
|
||||
persistModelAsync();
|
||||
|
||||
return user;
|
||||
|
||||
|
|
|
@ -19,9 +19,9 @@ import li.strolch.privilege.base.*;
|
|||
import li.strolch.privilege.model.*;
|
||||
import li.strolch.privilege.model.internal.*;
|
||||
import li.strolch.privilege.policy.PrivilegePolicy;
|
||||
import li.strolch.privilege.xml.CertificateStubsDomWriter;
|
||||
import li.strolch.privilege.xml.CertificateStubsSaxReader;
|
||||
import li.strolch.privilege.xml.CertificateStubsSaxReader.CertificateStub;
|
||||
import li.strolch.privilege.xml.CertificateStubsSaxWriter;
|
||||
import li.strolch.utils.collections.Tuple;
|
||||
import li.strolch.utils.concurrent.ElementLockingHandler;
|
||||
import li.strolch.utils.dbc.DBC;
|
||||
|
@ -31,7 +31,9 @@ import org.slf4j.LoggerFactory;
|
|||
import org.xml.sax.SAXParseException;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.Files;
|
||||
|
@ -46,6 +48,7 @@ import java.util.stream.Collectors;
|
|||
import java.util.stream.Stream;
|
||||
|
||||
import static java.text.MessageFormat.format;
|
||||
import static java.util.Comparator.comparing;
|
||||
import static li.strolch.utils.helper.ExceptionHelper.getRootCause;
|
||||
import static li.strolch.utils.helper.StringHelper.*;
|
||||
|
||||
|
@ -336,6 +339,7 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
result.add(user.asUserRep());
|
||||
}
|
||||
|
||||
result.sort(comparing(UserRep::getUsername));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1571,7 +1575,7 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
user.getLocale(), userRoles, new HashMap<>(user.getProperties()));
|
||||
}
|
||||
|
||||
private synchronized void persistModelAsync() {
|
||||
protected synchronized void persistModelAsync() {
|
||||
if (!this.autoPersistOnUserChangesData)
|
||||
return;
|
||||
|
||||
|
@ -1605,7 +1609,7 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
try (OutputStream out = Files.newOutputStream(this.persistSessionsPath.toPath());
|
||||
OutputStream outputStream = AesCryptoHelper.wrapEncrypt(this.secretKey, out)) {
|
||||
|
||||
CertificateStubsDomWriter writer = new CertificateStubsDomWriter(sessions, outputStream);
|
||||
CertificateStubsSaxWriter writer = new CertificateStubsSaxWriter(sessions, outputStream);
|
||||
writer.write();
|
||||
outputStream.flush();
|
||||
|
||||
|
@ -1986,7 +1990,11 @@ public class DefaultPrivilegeHandler implements PrivilegeHandler {
|
|||
prvCtx.validateAction(new SimpleRestrictable(PRIVILEGE_ACTION, PRIVILEGE_ACTION_PERSIST));
|
||||
|
||||
// persist non async
|
||||
return this.persistenceHandler.persist();
|
||||
try {
|
||||
return this.persistenceHandler.persist();
|
||||
} catch (XMLStreamException | IOException e) {
|
||||
throw new IllegalStateException("Failed to persist model", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
package li.strolch.privilege.handler;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -24,6 +25,8 @@ import li.strolch.privilege.model.internal.Role;
|
|||
import li.strolch.privilege.model.internal.User;
|
||||
import li.strolch.privilege.policy.PrivilegePolicy;
|
||||
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* The {@link PersistenceHandler} takes care of retrieving and persisting model objects to the underlying database. This
|
||||
|
@ -131,7 +134,7 @@ public interface PersistenceHandler {
|
|||
*
|
||||
* @return true if changes were persisted successfully, false if nothing needed to be persisted
|
||||
*/
|
||||
boolean persist();
|
||||
boolean persist() throws XMLStreamException, IOException;
|
||||
|
||||
/**
|
||||
* Informs this {@link PersistenceHandler} to reload the data from the backend
|
||||
|
|
|
@ -19,15 +19,17 @@ import li.strolch.privilege.base.PrivilegeException;
|
|||
import li.strolch.privilege.helper.XmlConstants;
|
||||
import li.strolch.privilege.model.internal.Role;
|
||||
import li.strolch.privilege.model.internal.User;
|
||||
import li.strolch.privilege.xml.PrivilegeRolesDomWriter;
|
||||
import li.strolch.privilege.xml.PrivilegeRolesSaxReader;
|
||||
import li.strolch.privilege.xml.PrivilegeUsersDomWriter;
|
||||
import li.strolch.privilege.xml.PrivilegeRolesSaxWriter;
|
||||
import li.strolch.privilege.xml.PrivilegeUsersSaxReader;
|
||||
import li.strolch.privilege.xml.PrivilegeUsersSaxWriter;
|
||||
import li.strolch.utils.helper.XmlHelper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -259,14 +261,14 @@ public class XmlPersistenceHandler implements PersistenceHandler {
|
|||
* Writes the model to the XML files. Where the files are written to was defined in the {@link #initialize(Map)}
|
||||
*/
|
||||
@Override
|
||||
public boolean persist() {
|
||||
public boolean persist() throws XMLStreamException, IOException {
|
||||
long start = System.nanoTime();
|
||||
boolean saved = false;
|
||||
|
||||
// write users file
|
||||
if (this.userMapDirty) {
|
||||
// delegate writing
|
||||
PrivilegeUsersDomWriter modelWriter = new PrivilegeUsersDomWriter(getAllUsers(), this.usersPath);
|
||||
PrivilegeUsersSaxWriter modelWriter = new PrivilegeUsersSaxWriter(getAllUsers(), this.usersPath);
|
||||
modelWriter.write();
|
||||
|
||||
this.userMapDirty = false;
|
||||
|
@ -276,7 +278,7 @@ public class XmlPersistenceHandler implements PersistenceHandler {
|
|||
// write roles file
|
||||
if (this.roleMapDirty) {
|
||||
// delegate writing
|
||||
PrivilegeRolesDomWriter modelWriter = new PrivilegeRolesDomWriter(getAllRoles(), this.rolesPath);
|
||||
PrivilegeRolesSaxWriter modelWriter = new PrivilegeRolesSaxWriter(getAllRoles(), this.rolesPath);
|
||||
modelWriter.write();
|
||||
|
||||
this.roleMapDirty = false;
|
||||
|
|
|
@ -1,18 +1,20 @@
|
|||
package li.strolch.privilege.helper;
|
||||
|
||||
import li.strolch.privilege.model.internal.Role;
|
||||
import li.strolch.privilege.xml.PrivilegeRolesSaxReader;
|
||||
import li.strolch.privilege.xml.PrivilegeRolesSaxWriter;
|
||||
import li.strolch.utils.helper.XmlHelper;
|
||||
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import li.strolch.privilege.model.internal.Role;
|
||||
import li.strolch.privilege.xml.PrivilegeRolesDomWriter;
|
||||
import li.strolch.privilege.xml.PrivilegeRolesSaxReader;
|
||||
import li.strolch.utils.helper.XmlHelper;
|
||||
|
||||
public class WriteRolesFileHelper {
|
||||
|
||||
public static void main(String[] args) {
|
||||
public static void main(String[] args) throws XMLStreamException, IOException {
|
||||
|
||||
if (args.length != 2)
|
||||
throw new IllegalStateException("Usage: <src> <dst>");
|
||||
|
@ -31,7 +33,7 @@ public class WriteRolesFileHelper {
|
|||
Map<String, Role> rolesMap = xmlHandler.getRoles();
|
||||
List<Role> roles = new ArrayList<>(rolesMap.values());
|
||||
|
||||
PrivilegeRolesDomWriter configSaxWriter = new PrivilegeRolesDomWriter(roles, dst);
|
||||
PrivilegeRolesSaxWriter configSaxWriter = new PrivilegeRolesSaxWriter(roles, dst);
|
||||
configSaxWriter.write();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
package li.strolch.privilege.helper;
|
||||
|
||||
import javanet.staxutils.IndentingXMLStreamWriter;
|
||||
|
||||
import javax.xml.stream.XMLOutputFactory;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import javax.xml.stream.XMLStreamWriter;
|
||||
import java.io.Writer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static li.strolch.privilege.helper.XmlConstants.*;
|
||||
|
||||
public class XmlHelper {
|
||||
|
||||
public static void writeStringMapElement(XMLStreamWriter xmlWriter, Map<String, String> parameterMap,
|
||||
String elementName, String valueElementName) throws XMLStreamException {
|
||||
writeStringMapElement(xmlWriter, parameterMap, elementName, valueElementName, XML_ATTR_VALUE);
|
||||
}
|
||||
|
||||
public static void writeStringMapElement(XMLStreamWriter xmlWriter, Map<String, String> parameterMap,
|
||||
String elementName, String valueElementName, String valueAttrName) throws XMLStreamException {
|
||||
if (parameterMap == null || parameterMap.isEmpty())
|
||||
return;
|
||||
|
||||
xmlWriter.writeStartElement(elementName);
|
||||
|
||||
List<String> propertyKeys = new ArrayList<>(parameterMap.keySet());
|
||||
propertyKeys.sort(null);
|
||||
for (String propertyKey : propertyKeys) {
|
||||
xmlWriter.writeEmptyElement(valueElementName);
|
||||
xmlWriter.writeAttribute(XML_ATTR_NAME, propertyKey);
|
||||
xmlWriter.writeAttribute(valueAttrName, parameterMap.get(propertyKey));
|
||||
}
|
||||
|
||||
xmlWriter.writeEndElement();
|
||||
}
|
||||
|
||||
public static void writeStringList(IndentingXMLStreamWriter xmlWriter, String elementName, Set<String> values)
|
||||
throws XMLStreamException {
|
||||
List<String> denyList = new ArrayList<>(values);
|
||||
denyList.sort(null);
|
||||
for (String value : denyList) {
|
||||
writeStringElement(xmlWriter, elementName, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeStringElement(IndentingXMLStreamWriter xmlWriter, String elementName, String value)
|
||||
throws XMLStreamException {
|
||||
xmlWriter.writeStartElement(elementName);
|
||||
xmlWriter.writeCharacters(value);
|
||||
xmlWriter.writeEndElement();
|
||||
}
|
||||
|
||||
public static IndentingXMLStreamWriter openXmlStreamWriterDocument(Writer ioWriter) throws XMLStreamException {
|
||||
XMLOutputFactory factory = XMLOutputFactory.newInstance();
|
||||
IndentingXMLStreamWriter xmlWriter = new IndentingXMLStreamWriter(factory.createXMLStreamWriter(ioWriter));
|
||||
xmlWriter.setIndent(" ");
|
||||
|
||||
// create document root
|
||||
xmlWriter.writeStartDocument(StandardCharsets.UTF_8.name(), "1.0");
|
||||
return xmlWriter;
|
||||
}
|
||||
}
|
|
@ -1,87 +0,0 @@
|
|||
/*
|
||||
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package li.strolch.privilege.xml;
|
||||
|
||||
import static java.util.Comparator.comparing;
|
||||
import static li.strolch.privilege.helper.XmlConstants.*;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
|
||||
import li.strolch.privilege.model.Certificate;
|
||||
import li.strolch.utils.helper.XmlHelper;
|
||||
import li.strolch.utils.iso8601.ISO8601;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||
*/
|
||||
public class CertificateStubsDomWriter {
|
||||
|
||||
private final List<Certificate> certificates;
|
||||
private final OutputStream outputStream;
|
||||
|
||||
public CertificateStubsDomWriter(List<Certificate> certificates, OutputStream outputStream) {
|
||||
this.certificates = certificates;
|
||||
this.outputStream = outputStream;
|
||||
}
|
||||
|
||||
public void write() {
|
||||
|
||||
// create document root
|
||||
Document doc = XmlHelper.createDocument();
|
||||
Element rootElement = doc.createElement(XML_ROOT_CERTIFICATES);
|
||||
doc.appendChild(rootElement);
|
||||
|
||||
this.certificates.stream().sorted(comparing(Certificate::getSessionId)).forEach(cert -> {
|
||||
|
||||
// create the certificate element
|
||||
Element certElement = doc.createElement(XML_CERTIFICATE);
|
||||
rootElement.appendChild(certElement);
|
||||
|
||||
// sessionId;
|
||||
certElement.setAttribute(XML_ATTR_SESSION_ID, cert.getSessionId());
|
||||
|
||||
// usage;
|
||||
certElement.setAttribute(XML_ATTR_USAGE, cert.getUsage().name());
|
||||
|
||||
// username;
|
||||
certElement.setAttribute(XML_ATTR_USERNAME, cert.getUsername());
|
||||
|
||||
// authToken;
|
||||
certElement.setAttribute(XML_ATTR_AUTH_TOKEN, cert.getAuthToken());
|
||||
|
||||
// source;
|
||||
certElement.setAttribute(XML_ATTR_SOURCE, cert.getSource());
|
||||
|
||||
// locale;
|
||||
certElement.setAttribute(XML_ATTR_LOCALE, cert.getLocale().toLanguageTag());
|
||||
|
||||
// loginTime;
|
||||
certElement.setAttribute(XML_ATTR_LOGIN_TIME, ISO8601.toString(cert.getLoginTime()));
|
||||
|
||||
// lastAccess;
|
||||
certElement.setAttribute(XML_ATTR_LAST_ACCESS, ISO8601.toString(cert.getLastAccess()));
|
||||
|
||||
// keepAlive;
|
||||
certElement.setAttribute(XML_ATTR_KEEP_ALIVE, String.valueOf(cert.isKeepAlive()));
|
||||
});
|
||||
|
||||
// write the container file to disk
|
||||
XmlHelper.writeDocument(doc, this.outputStream);
|
||||
}
|
||||
}
|
|
@ -15,16 +15,6 @@
|
|||
*/
|
||||
package li.strolch.privilege.xml;
|
||||
|
||||
import static li.strolch.privilege.handler.DefaultPrivilegeHandler.SOURCE_UNKNOWN;
|
||||
import static li.strolch.privilege.helper.XmlConstants.*;
|
||||
import static li.strolch.utils.helper.StringHelper.isEmpty;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import li.strolch.privilege.base.PrivilegeException;
|
||||
import li.strolch.privilege.model.Usage;
|
||||
import li.strolch.utils.dbc.DBC;
|
||||
|
@ -33,6 +23,16 @@ import li.strolch.utils.iso8601.ISO8601;
|
|||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.helpers.DefaultHandler;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import static li.strolch.privilege.handler.DefaultPrivilegeHandler.SOURCE_UNKNOWN;
|
||||
import static li.strolch.privilege.helper.XmlConstants.*;
|
||||
import static li.strolch.utils.helper.StringHelper.isEmpty;
|
||||
|
||||
/**
|
||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||
*/
|
||||
|
@ -55,33 +55,27 @@ public class CertificateStubsSaxReader extends DefaultHandler {
|
|||
public void startElement(String uri, String localName, String qName, Attributes attributes) {
|
||||
|
||||
switch (qName) {
|
||||
case XML_ROOT_CERTIFICATES:
|
||||
break;
|
||||
case XML_CERTIFICATE:
|
||||
|
||||
CertificateStub stub = new CertificateStub();
|
||||
stub.usage = Usage.valueOf(attributes.getValue(XML_ATTR_USAGE).trim());
|
||||
stub.sessionId = attributes.getValue(XML_ATTR_SESSION_ID).trim();
|
||||
stub.username = attributes.getValue(XML_ATTR_USERNAME).trim();
|
||||
stub.authToken = attributes.getValue(XML_ATTR_AUTH_TOKEN).trim();
|
||||
stub.source = attributes.getValue(XML_ATTR_SOURCE).trim();
|
||||
stub.locale = Locale.forLanguageTag(attributes.getValue(XML_ATTR_LOCALE).trim());
|
||||
stub.loginTime = ISO8601.parseToZdt(attributes.getValue(XML_ATTR_LOGIN_TIME).trim());
|
||||
stub.lastAccess = ISO8601.parseToZdt(attributes.getValue(XML_ATTR_LAST_ACCESS).trim());
|
||||
stub.keepAlive = Boolean.parseBoolean(attributes.getValue(XML_ATTR_KEEP_ALIVE).trim());
|
||||
|
||||
DBC.INTERIM.assertNotEmpty("sessionId missing on sessions data!", stub.sessionId);
|
||||
DBC.INTERIM.assertNotEmpty("username missing on sessions data!", stub.username);
|
||||
DBC.INTERIM.assertNotEmpty("authToken missing on sessions data!", stub.authToken);
|
||||
|
||||
if (isEmpty(stub.source))
|
||||
stub.source = SOURCE_UNKNOWN;
|
||||
|
||||
this.stubs.add(stub);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new PrivilegeException("Unhandled tag " + qName);
|
||||
case XML_ROOT_CERTIFICATES -> {
|
||||
}
|
||||
case XML_CERTIFICATE -> {
|
||||
CertificateStub stub = new CertificateStub();
|
||||
stub.usage = Usage.valueOf(attributes.getValue(XML_ATTR_USAGE).trim());
|
||||
stub.sessionId = attributes.getValue(XML_ATTR_SESSION_ID).trim();
|
||||
stub.username = attributes.getValue(XML_ATTR_USERNAME).trim();
|
||||
stub.authToken = attributes.getValue(XML_ATTR_AUTH_TOKEN).trim();
|
||||
stub.source = attributes.getValue(XML_ATTR_SOURCE).trim();
|
||||
stub.locale = Locale.forLanguageTag(attributes.getValue(XML_ATTR_LOCALE).trim());
|
||||
stub.loginTime = ISO8601.parseToZdt(attributes.getValue(XML_ATTR_LOGIN_TIME).trim());
|
||||
stub.lastAccess = ISO8601.parseToZdt(attributes.getValue(XML_ATTR_LAST_ACCESS).trim());
|
||||
stub.keepAlive = Boolean.parseBoolean(attributes.getValue(XML_ATTR_KEEP_ALIVE).trim());
|
||||
DBC.INTERIM.assertNotEmpty("sessionId missing on sessions data!", stub.sessionId);
|
||||
DBC.INTERIM.assertNotEmpty("username missing on sessions data!", stub.username);
|
||||
DBC.INTERIM.assertNotEmpty("authToken missing on sessions data!", stub.authToken);
|
||||
if (isEmpty(stub.source))
|
||||
stub.source = SOURCE_UNKNOWN;
|
||||
this.stubs.add(stub);
|
||||
}
|
||||
default -> throw new PrivilegeException("Unhandled tag " + qName);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package li.strolch.privilege.xml;
|
||||
|
||||
import javanet.staxutils.IndentingXMLStreamWriter;
|
||||
import li.strolch.privilege.model.Certificate;
|
||||
import li.strolch.utils.iso8601.ISO8601;
|
||||
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Writer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static java.util.Comparator.comparing;
|
||||
import static li.strolch.privilege.helper.XmlConstants.*;
|
||||
import static li.strolch.privilege.helper.XmlHelper.openXmlStreamWriterDocument;
|
||||
|
||||
/**
|
||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||
*/
|
||||
public class CertificateStubsSaxWriter {
|
||||
|
||||
private final List<Certificate> certificates;
|
||||
private final OutputStream outputStream;
|
||||
|
||||
public CertificateStubsSaxWriter(List<Certificate> certificates, OutputStream outputStream) {
|
||||
this.certificates = certificates;
|
||||
this.outputStream = outputStream;
|
||||
}
|
||||
|
||||
public void write() throws IOException, XMLStreamException {
|
||||
|
||||
Writer ioWriter = new OutputStreamWriter(this.outputStream, StandardCharsets.UTF_8);
|
||||
|
||||
IndentingXMLStreamWriter xmlWriter = openXmlStreamWriterDocument(ioWriter);
|
||||
xmlWriter.writeStartElement(XML_ROOT_CERTIFICATES);
|
||||
|
||||
List<Certificate> certificates = new ArrayList<>(this.certificates);
|
||||
certificates.sort(comparing(Certificate::getSessionId));
|
||||
for (Certificate cert : certificates) {
|
||||
|
||||
// create the certificate element
|
||||
xmlWriter.writeStartElement(XML_CERTIFICATE);
|
||||
|
||||
// sessionId;
|
||||
xmlWriter.writeAttribute(XML_ATTR_SESSION_ID, cert.getSessionId());
|
||||
|
||||
// usage;
|
||||
xmlWriter.writeAttribute(XML_ATTR_USAGE, cert.getUsage().name());
|
||||
|
||||
// username;
|
||||
xmlWriter.writeAttribute(XML_ATTR_USERNAME, cert.getUsername());
|
||||
|
||||
// authToken;
|
||||
xmlWriter.writeAttribute(XML_ATTR_AUTH_TOKEN, cert.getAuthToken());
|
||||
|
||||
// source;
|
||||
xmlWriter.writeAttribute(XML_ATTR_SOURCE, cert.getSource());
|
||||
|
||||
// locale;
|
||||
xmlWriter.writeAttribute(XML_ATTR_LOCALE, cert.getLocale().toLanguageTag());
|
||||
|
||||
// loginTime;
|
||||
xmlWriter.writeAttribute(XML_ATTR_LOGIN_TIME, ISO8601.toString(cert.getLoginTime()));
|
||||
|
||||
// lastAccess;
|
||||
xmlWriter.writeAttribute(XML_ATTR_LAST_ACCESS, ISO8601.toString(cert.getLastAccess()));
|
||||
|
||||
// keepAlive;
|
||||
xmlWriter.writeAttribute(XML_ATTR_KEEP_ALIVE, String.valueOf(cert.isKeepAlive()));
|
||||
}
|
||||
|
||||
// and now end
|
||||
xmlWriter.writeEndDocument();
|
||||
xmlWriter.flush();
|
||||
}
|
||||
}
|
|
@ -17,7 +17,6 @@ package li.strolch.privilege.xml;
|
|||
|
||||
import org.xml.sax.Attributes;
|
||||
|
||||
// TODO write JavaDoc...
|
||||
public interface ElementParser {
|
||||
|
||||
void startElement(String uri, String localName, String qName, Attributes attributes);
|
||||
|
|
|
@ -1,129 +0,0 @@
|
|||
/*
|
||||
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package li.strolch.privilege.xml;
|
||||
|
||||
import static li.strolch.privilege.helper.XmlConstants.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import li.strolch.privilege.model.internal.PrivilegeContainerModel;
|
||||
import li.strolch.utils.helper.XmlHelper;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||
*/
|
||||
public class PrivilegeConfigDomWriter {
|
||||
|
||||
private final PrivilegeContainerModel containerModel;
|
||||
private final File configFile;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public PrivilegeConfigDomWriter(PrivilegeContainerModel containerModel, File configFile) {
|
||||
this.containerModel = containerModel;
|
||||
this.configFile = configFile;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public void write() {
|
||||
|
||||
// create document root
|
||||
Document doc = XmlHelper.createDocument();
|
||||
Element rootElement = doc.createElement(XML_ROOT_PRIVILEGE);
|
||||
doc.appendChild(rootElement);
|
||||
|
||||
Element containerElement = doc.createElement(XML_CONTAINER);
|
||||
rootElement.appendChild(containerElement);
|
||||
|
||||
// create EncryptionHandler
|
||||
Element encryptionHandlerElem = doc.createElement(XML_HANDLER_ENCRYPTION);
|
||||
containerElement.appendChild(encryptionHandlerElem);
|
||||
encryptionHandlerElem.setAttribute(XML_ATTR_CLASS, this.containerModel.getEncryptionHandlerClassName());
|
||||
// Parameters
|
||||
fillParameterMap(doc, encryptionHandlerElem, this.containerModel.getEncryptionHandlerParameterMap());
|
||||
|
||||
// create PersistenceHandler
|
||||
Element persistenceHandlerElem = doc.createElement(XML_HANDLER_PERSISTENCE);
|
||||
containerElement.appendChild(persistenceHandlerElem);
|
||||
persistenceHandlerElem.setAttribute(XML_ATTR_CLASS, this.containerModel.getPersistenceHandlerClassName());
|
||||
// Parameters
|
||||
fillParameterMap(doc, persistenceHandlerElem, this.containerModel.getPersistenceHandlerParameterMap());
|
||||
|
||||
// Parameters
|
||||
fillParameterMap(doc, containerElement, this.containerModel.getParameterMap());
|
||||
|
||||
// create UserChallengeHandler
|
||||
Element userChallengeHandlerElem = doc.createElement(XML_HANDLER_USER_CHALLENGE);
|
||||
containerElement.appendChild(userChallengeHandlerElem);
|
||||
userChallengeHandlerElem.setAttribute(XML_ATTR_CLASS, this.containerModel.getUserChallengeHandlerClassName());
|
||||
// Parameters
|
||||
fillParameterMap(doc, userChallengeHandlerElem, this.containerModel.getUserChallengeHandlerParameterMap());
|
||||
|
||||
// create SingleSignOnHandler
|
||||
if (this.containerModel.getSsoHandlerClassName() != null) {
|
||||
Element ssoHandlerElem = doc.createElement(XML_HANDLER_SSO);
|
||||
containerElement.appendChild(ssoHandlerElem);
|
||||
ssoHandlerElem.setAttribute(XML_ATTR_CLASS, this.containerModel.getSsoHandlerClassName());
|
||||
// Parameters
|
||||
fillParameterMap(doc, ssoHandlerElem, this.containerModel.getSsoHandlerParameterMap());
|
||||
}
|
||||
|
||||
// create PrivilegeHandler
|
||||
if (this.containerModel.getSsoHandlerClassName() != null) {
|
||||
Element privilegeHandlerElem = doc.createElement(XML_HANDLER_PRIVILEGE);
|
||||
containerElement.appendChild(privilegeHandlerElem);
|
||||
privilegeHandlerElem.setAttribute(XML_ATTR_CLASS, this.containerModel.getPrivilegeHandlerClassName());
|
||||
// Parameters
|
||||
fillParameterMap(doc, privilegeHandlerElem, this.containerModel.getPrivilegeHandlerParameterMap());
|
||||
}
|
||||
|
||||
// Policies
|
||||
Element policiesElem = doc.createElement(XML_POLICIES);
|
||||
rootElement.appendChild(policiesElem);
|
||||
this.containerModel.getPolicies().entrySet().stream().sorted(Entry.comparingByKey())
|
||||
.forEach(entry -> {
|
||||
Element policyElem = doc.createElement(XML_POLICY);
|
||||
policyElem.setAttribute(XML_ATTR_NAME, entry.getKey());
|
||||
policyElem.setAttribute(XML_ATTR_CLASS, entry.getValue().getName());
|
||||
policiesElem.appendChild(policyElem);
|
||||
});
|
||||
|
||||
// write the container file to disk
|
||||
XmlHelper.writeDocument(doc, this.configFile);
|
||||
}
|
||||
|
||||
private void fillParameterMap(Document doc, Element parent, Map<String, String> parameterMap) {
|
||||
|
||||
if (parameterMap != null && !parameterMap.isEmpty()) {
|
||||
Element parametersElement = doc.createElement(XML_PARAMETERS);
|
||||
for (Entry<String, String> entry : parameterMap.entrySet()) {
|
||||
Element parameterElement = doc.createElement(XML_PARAMETER);
|
||||
parameterElement.setAttribute(XML_ATTR_NAME, entry.getKey());
|
||||
parameterElement.setAttribute(XML_ATTR_VALUE, entry.getValue());
|
||||
parametersElement.appendChild(parameterElement);
|
||||
}
|
||||
|
||||
parent.appendChild(parametersElement);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,18 +15,17 @@
|
|||
*/
|
||||
package li.strolch.privilege.xml;
|
||||
|
||||
import static li.strolch.privilege.helper.XmlConstants.*;
|
||||
import li.strolch.privilege.model.internal.PrivilegeContainerModel;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.helpers.DefaultHandler;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import li.strolch.privilege.helper.XmlConstants;
|
||||
import li.strolch.privilege.model.internal.PrivilegeContainerModel;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.helpers.DefaultHandler;
|
||||
import static li.strolch.privilege.helper.XmlConstants.*;
|
||||
|
||||
/**
|
||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||
|
@ -48,12 +47,12 @@ public class PrivilegeConfigSaxReader extends DefaultHandler {
|
|||
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
|
||||
|
||||
switch (qName) {
|
||||
case XML_CONTAINER -> this.buildersStack.push(new ContainerParser());
|
||||
case XML_PARAMETERS -> this.buildersStack.push(new ParametersParser());
|
||||
case XML_POLICIES -> this.buildersStack.push(new PoliciesParser());
|
||||
default -> {
|
||||
// nothing to do, probably handle on stack
|
||||
}
|
||||
case XML_CONTAINER -> this.buildersStack.push(new ContainerParser());
|
||||
case XML_PARAMETERS -> this.buildersStack.push(new ParametersParser());
|
||||
case XML_POLICIES -> this.buildersStack.push(new PoliciesParser());
|
||||
default -> {
|
||||
// nothing to do, probably handle on stack
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.buildersStack.isEmpty())
|
||||
|
@ -89,38 +88,38 @@ public class PrivilegeConfigSaxReader extends DefaultHandler {
|
|||
public void startElement(String uri, String localName, String qName, Attributes attributes) {
|
||||
|
||||
switch (qName) {
|
||||
case XML_CONTAINER -> this.currentElement = qName;
|
||||
case XML_HANDLER_ENCRYPTION -> {
|
||||
this.currentElement = qName;
|
||||
String className = attributes.getValue(XML_ATTR_CLASS).trim();
|
||||
getContainerModel().setEncryptionHandlerClassName(className);
|
||||
}
|
||||
case XML_HANDLER_PASSWORD_STRENGTH -> {
|
||||
this.currentElement = qName;
|
||||
String className = attributes.getValue(XML_ATTR_CLASS).trim();
|
||||
getContainerModel().setPasswordStrengthHandlerClassName(className);
|
||||
}
|
||||
case XML_HANDLER_PERSISTENCE -> {
|
||||
this.currentElement = qName;
|
||||
String className = attributes.getValue(XML_ATTR_CLASS).trim();
|
||||
getContainerModel().setPersistenceHandlerClassName(className);
|
||||
}
|
||||
case XML_HANDLER_USER_CHALLENGE -> {
|
||||
this.currentElement = qName;
|
||||
String className = attributes.getValue(XML_ATTR_CLASS).trim();
|
||||
getContainerModel().setUserChallengeHandlerClassName(className);
|
||||
}
|
||||
case XML_HANDLER_SSO -> {
|
||||
this.currentElement = qName;
|
||||
String className = attributes.getValue(XML_ATTR_CLASS).trim();
|
||||
getContainerModel().setSsoHandlerClassName(className);
|
||||
}
|
||||
case XML_HANDLER_PRIVILEGE -> {
|
||||
this.currentElement = qName;
|
||||
String className = attributes.getValue(XML_ATTR_CLASS).trim();
|
||||
getContainerModel().setPrivilegeHandlerClassName(className);
|
||||
}
|
||||
default -> throw new IllegalStateException("Unexpected value: " + qName);
|
||||
case XML_CONTAINER -> this.currentElement = qName;
|
||||
case XML_HANDLER_PRIVILEGE -> {
|
||||
this.currentElement = qName;
|
||||
String className = attributes.getValue(XML_ATTR_CLASS).trim();
|
||||
getContainerModel().setPrivilegeHandlerClassName(className);
|
||||
}
|
||||
case XML_HANDLER_ENCRYPTION -> {
|
||||
this.currentElement = qName;
|
||||
String className = attributes.getValue(XML_ATTR_CLASS).trim();
|
||||
getContainerModel().setEncryptionHandlerClassName(className);
|
||||
}
|
||||
case XML_HANDLER_PASSWORD_STRENGTH -> {
|
||||
this.currentElement = qName;
|
||||
String className = attributes.getValue(XML_ATTR_CLASS).trim();
|
||||
getContainerModel().setPasswordStrengthHandlerClassName(className);
|
||||
}
|
||||
case XML_HANDLER_PERSISTENCE -> {
|
||||
this.currentElement = qName;
|
||||
String className = attributes.getValue(XML_ATTR_CLASS).trim();
|
||||
getContainerModel().setPersistenceHandlerClassName(className);
|
||||
}
|
||||
case XML_HANDLER_USER_CHALLENGE -> {
|
||||
this.currentElement = qName;
|
||||
String className = attributes.getValue(XML_ATTR_CLASS).trim();
|
||||
getContainerModel().setUserChallengeHandlerClassName(className);
|
||||
}
|
||||
case XML_HANDLER_SSO -> {
|
||||
this.currentElement = qName;
|
||||
String className = attributes.getValue(XML_ATTR_CLASS).trim();
|
||||
getContainerModel().setSsoHandlerClassName(className);
|
||||
}
|
||||
default -> throw new IllegalStateException("Unexpected value: " + qName);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -129,20 +128,17 @@ public class PrivilegeConfigSaxReader extends DefaultHandler {
|
|||
if (!(child instanceof ParametersParser parametersChild))
|
||||
return;
|
||||
|
||||
final Map<String, String> params = parametersChild.getParameterMap();
|
||||
switch (this.currentElement) {
|
||||
case XML_CONTAINER -> getContainerModel().setParameterMap(parametersChild.getParameterMap());
|
||||
case XML_HANDLER_ENCRYPTION ->
|
||||
getContainerModel().setEncryptionHandlerParameterMap(parametersChild.getParameterMap());
|
||||
case XML_HANDLER_PASSWORD_STRENGTH ->
|
||||
getContainerModel().setPasswordStrengthHandlerParameterMap(parametersChild.getParameterMap());
|
||||
case XML_HANDLER_PERSISTENCE ->
|
||||
getContainerModel().setPersistenceHandlerParameterMap(parametersChild.getParameterMap());
|
||||
case XML_HANDLER_USER_CHALLENGE ->
|
||||
getContainerModel().setUserChallengeHandlerParameterMap(parametersChild.getParameterMap());
|
||||
case XML_HANDLER_SSO -> getContainerModel().setSsoHandlerParameterMap(parametersChild.getParameterMap());
|
||||
case XML_HANDLER_PRIVILEGE ->
|
||||
getContainerModel().setPrivilegeHandlerParameterMap(parametersChild.getParameterMap());
|
||||
default -> throw new IllegalStateException("Unexpected value: " + this.currentElement);
|
||||
case XML_CONTAINER -> getContainerModel().setParameterMap(params);
|
||||
case XML_HANDLER_PRIVILEGE -> getContainerModel().setPrivilegeHandlerParameterMap(params);
|
||||
case XML_HANDLER_ENCRYPTION -> getContainerModel().setEncryptionHandlerParameterMap(params);
|
||||
case XML_HANDLER_PASSWORD_STRENGTH ->
|
||||
getContainerModel().setPasswordStrengthHandlerParameterMap(params);
|
||||
case XML_HANDLER_PERSISTENCE -> getContainerModel().setPersistenceHandlerParameterMap(params);
|
||||
case XML_HANDLER_USER_CHALLENGE -> getContainerModel().setUserChallengeHandlerParameterMap(params);
|
||||
case XML_HANDLER_SSO -> getContainerModel().setSsoHandlerParameterMap(params);
|
||||
default -> throw new IllegalStateException("Unexpected value: " + this.currentElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package li.strolch.privilege.xml;
|
||||
|
||||
import javanet.staxutils.IndentingXMLStreamWriter;
|
||||
import li.strolch.privilege.model.internal.PrivilegeContainerModel;
|
||||
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static li.strolch.privilege.helper.XmlConstants.*;
|
||||
import static li.strolch.privilege.helper.XmlHelper.openXmlStreamWriterDocument;
|
||||
import static li.strolch.privilege.helper.XmlHelper.writeStringMapElement;
|
||||
|
||||
/**
|
||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||
*/
|
||||
public class PrivilegeConfigSaxWriter {
|
||||
|
||||
private final PrivilegeContainerModel containerModel;
|
||||
private final File configFile;
|
||||
|
||||
public PrivilegeConfigSaxWriter(PrivilegeContainerModel containerModel, File configFile) {
|
||||
this.containerModel = containerModel;
|
||||
this.configFile = configFile;
|
||||
}
|
||||
|
||||
public void write() throws IOException, XMLStreamException {
|
||||
|
||||
try (Writer ioWriter = new OutputStreamWriter(new FileOutputStream(this.configFile), StandardCharsets.UTF_8)) {
|
||||
|
||||
IndentingXMLStreamWriter xmlWriter = openXmlStreamWriterDocument(ioWriter);
|
||||
xmlWriter.writeStartElement(XML_ROOT_PRIVILEGE);
|
||||
|
||||
// write container element
|
||||
xmlWriter.writeStartElement(XML_CONTAINER);
|
||||
writeStringMapElement(xmlWriter, this.containerModel.getParameterMap(), XML_PARAMETERS, XML_PARAMETER);
|
||||
|
||||
{
|
||||
// write PrivilegeHandler
|
||||
if (this.containerModel.getPrivilegeHandlerClassName() != null)
|
||||
writeHandler(xmlWriter, XML_HANDLER_PRIVILEGE, this.containerModel.getPrivilegeHandlerClassName(),
|
||||
this.containerModel.getPrivilegeHandlerParameterMap());
|
||||
|
||||
// write EncryptionHandler
|
||||
writeHandler(xmlWriter, XML_HANDLER_ENCRYPTION, this.containerModel.getEncryptionHandlerClassName(),
|
||||
this.containerModel.getEncryptionHandlerParameterMap());
|
||||
|
||||
// write PersistenceHandler
|
||||
writeHandler(xmlWriter, XML_HANDLER_PERSISTENCE, this.containerModel.getPersistenceHandlerClassName(),
|
||||
this.containerModel.getPersistenceHandlerParameterMap());
|
||||
|
||||
// write PasswordStrengthHandler
|
||||
if (this.containerModel.getPasswordStrengthHandlerClassName() != null)
|
||||
writeHandler(xmlWriter, XML_HANDLER_PASSWORD_STRENGTH,
|
||||
this.containerModel.getPasswordStrengthHandlerClassName(),
|
||||
this.containerModel.getPasswordStrengthHandlerParameterMap());
|
||||
|
||||
// write UserChallengeHandler
|
||||
if (this.containerModel.getUserChallengeHandlerClassName() != null)
|
||||
writeHandler(xmlWriter, XML_HANDLER_USER_CHALLENGE,
|
||||
this.containerModel.getUserChallengeHandlerClassName(),
|
||||
this.containerModel.getUserChallengeHandlerParameterMap());
|
||||
|
||||
// write SingleSignOnHandler
|
||||
if (this.containerModel.getSsoHandlerClassName() != null)
|
||||
writeHandler(xmlWriter, XML_HANDLER_SSO, this.containerModel.getSsoHandlerClassName(),
|
||||
this.containerModel.getSsoHandlerParameterMap());
|
||||
}
|
||||
|
||||
xmlWriter.writeEndElement();
|
||||
|
||||
// Policies
|
||||
Map<String, String> policies = new HashMap<>();
|
||||
this.containerModel.getPolicies().forEach((key, value) -> policies.put(key, value.getName()));
|
||||
writeStringMapElement(xmlWriter, policies, XML_POLICIES, XML_POLICY, XML_ATTR_CLASS);
|
||||
|
||||
// and now end
|
||||
xmlWriter.writeEndDocument();
|
||||
xmlWriter.flush();
|
||||
}
|
||||
}
|
||||
|
||||
private void writeHandler(IndentingXMLStreamWriter xmlWriter, String handleName, String className,
|
||||
Map<String, String> parameters) throws XMLStreamException {
|
||||
if (parameters.isEmpty())
|
||||
xmlWriter.writeEmptyElement(handleName);
|
||||
else
|
||||
xmlWriter.writeStartElement(handleName);
|
||||
xmlWriter.writeAttribute(XML_ATTR_CLASS, className);
|
||||
|
||||
writeStringMapElement(xmlWriter, parameters, XML_PARAMETERS, XML_PARAMETER);
|
||||
|
||||
if (!parameters.isEmpty())
|
||||
xmlWriter.writeEndElement();
|
||||
}
|
||||
}
|
|
@ -1,87 +0,0 @@
|
|||
/*
|
||||
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package li.strolch.privilege.xml;
|
||||
|
||||
import static java.util.Comparator.comparing;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import li.strolch.privilege.helper.XmlConstants;
|
||||
import li.strolch.privilege.model.internal.Role;
|
||||
import li.strolch.utils.helper.XmlHelper;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||
*/
|
||||
public class PrivilegeRolesDomWriter {
|
||||
|
||||
private final List<Role> roles;
|
||||
private final File modelFile;
|
||||
|
||||
public PrivilegeRolesDomWriter(List<Role> roles, File modelFile) {
|
||||
this.roles = roles;
|
||||
this.modelFile = modelFile;
|
||||
}
|
||||
|
||||
public void write() {
|
||||
|
||||
// create document root
|
||||
Document doc = XmlHelper.createDocument();
|
||||
Element rootElement = doc.createElement(XmlConstants.XML_ROLES);
|
||||
doc.appendChild(rootElement);
|
||||
|
||||
this.roles.stream().sorted(comparing(role1 -> role1.getName().toLowerCase(Locale.ROOT))).forEach(role -> {
|
||||
|
||||
// create the role element
|
||||
Element roleElement = doc.createElement(XmlConstants.XML_ROLE);
|
||||
rootElement.appendChild(roleElement);
|
||||
|
||||
roleElement.setAttribute(XmlConstants.XML_ATTR_NAME, role.getName());
|
||||
|
||||
role.getPrivilegeNames().stream().sorted().map(role::getPrivilege).forEach(privilege -> {
|
||||
Element privilegeElement = doc.createElement(XmlConstants.XML_PRIVILEGE);
|
||||
roleElement.appendChild(privilegeElement);
|
||||
privilegeElement.setAttribute(XmlConstants.XML_ATTR_NAME, privilege.getName());
|
||||
privilegeElement.setAttribute(XmlConstants.XML_ATTR_POLICY, privilege.getPolicy());
|
||||
|
||||
if (privilege.isAllAllowed()) {
|
||||
Element allAllowedElement = doc.createElement(XmlConstants.XML_ALL_ALLOWED);
|
||||
allAllowedElement.setTextContent(Boolean.toString(privilege.isAllAllowed()));
|
||||
privilegeElement.appendChild(allAllowedElement);
|
||||
}
|
||||
|
||||
privilege.getDenyList().stream().sorted().forEach(denyValue -> {
|
||||
Element denyValueElement = doc.createElement(XmlConstants.XML_DENY);
|
||||
denyValueElement.setTextContent(denyValue);
|
||||
privilegeElement.appendChild(denyValueElement);
|
||||
});
|
||||
|
||||
privilege.getAllowList().stream().sorted().forEach(allowValue -> {
|
||||
Element allowValueElement = doc.createElement(XmlConstants.XML_ALLOW);
|
||||
allowValueElement.setTextContent(allowValue);
|
||||
privilegeElement.appendChild(allowValueElement);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// write the container file to disk
|
||||
XmlHelper.writeDocument(doc, this.modelFile);
|
||||
}
|
||||
}
|
|
@ -15,10 +15,6 @@
|
|||
*/
|
||||
package li.strolch.privilege.xml;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.*;
|
||||
|
||||
import li.strolch.privilege.helper.XmlConstants;
|
||||
import li.strolch.privilege.model.IPrivilege;
|
||||
import li.strolch.privilege.model.internal.PrivilegeImpl;
|
||||
import li.strolch.privilege.model.internal.Role;
|
||||
|
@ -29,6 +25,11 @@ import org.xml.sax.Attributes;
|
|||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.helpers.DefaultHandler;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.*;
|
||||
|
||||
import static li.strolch.privilege.helper.XmlConstants.*;
|
||||
|
||||
/**
|
||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||
*/
|
||||
|
@ -51,9 +52,13 @@ public class PrivilegeRolesSaxReader extends DefaultHandler {
|
|||
@Override
|
||||
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
|
||||
|
||||
if (qName.equals(XmlConstants.XML_ROLE)) {
|
||||
if (qName.equals(XML_ROLE)) {
|
||||
if (this.buildersStack.stream().anyMatch(e -> e.getClass().equals(RoleParser.class)))
|
||||
throw new IllegalArgumentException("Previous Role not closed!");
|
||||
this.buildersStack.push(new RoleParser());
|
||||
} else if (qName.equals(XmlConstants.XML_PROPERTIES)) {
|
||||
} else if (qName.equals(XML_PROPERTIES)) {
|
||||
if (this.buildersStack.stream().anyMatch(e -> e.getClass().equals(PropertyParser.class)))
|
||||
throw new IllegalArgumentException("Previous Properties not closed!");
|
||||
this.buildersStack.push(new PropertyParser());
|
||||
}
|
||||
|
||||
|
@ -74,9 +79,9 @@ public class PrivilegeRolesSaxReader extends DefaultHandler {
|
|||
this.buildersStack.peek().endElement(uri, localName, qName);
|
||||
|
||||
ElementParser elementParser = null;
|
||||
if (qName.equals(XmlConstants.XML_ROLE)) {
|
||||
if (qName.equals(XML_ROLE)) {
|
||||
elementParser = this.buildersStack.pop();
|
||||
} else if (qName.equals(XmlConstants.XML_PROPERTIES)) {
|
||||
} else if (qName.equals(XML_PROPERTIES)) {
|
||||
elementParser = this.buildersStack.pop();
|
||||
}
|
||||
|
||||
|
@ -134,20 +139,15 @@ public class PrivilegeRolesSaxReader extends DefaultHandler {
|
|||
this.text = new StringBuilder();
|
||||
|
||||
switch (qName) {
|
||||
case XmlConstants.XML_ROLE:
|
||||
this.roleName = attributes.getValue(XmlConstants.XML_ATTR_NAME).trim();
|
||||
break;
|
||||
case XmlConstants.XML_PRIVILEGE:
|
||||
this.privilegeName = attributes.getValue(XmlConstants.XML_ATTR_NAME).trim();
|
||||
this.privilegePolicy = attributes.getValue(XmlConstants.XML_ATTR_POLICY).trim();
|
||||
break;
|
||||
case XmlConstants.XML_ALLOW:
|
||||
case XmlConstants.XML_DENY:
|
||||
case XmlConstants.XML_ALL_ALLOWED:
|
||||
case XML_ROLE -> this.roleName = attributes.getValue(XML_ATTR_NAME).trim();
|
||||
case XML_PRIVILEGE -> {
|
||||
this.privilegeName = attributes.getValue(XML_ATTR_NAME).trim();
|
||||
this.privilegePolicy = attributes.getValue(XML_ATTR_POLICY).trim();
|
||||
}
|
||||
case XML_ALLOW, XML_DENY, XML_ALL_ALLOWED -> {
|
||||
}
|
||||
// no-op
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Unhandled tag " + qName);
|
||||
default -> throw new IllegalArgumentException("Unhandled tag " + qName);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -159,31 +159,33 @@ public class PrivilegeRolesSaxReader extends DefaultHandler {
|
|||
|
||||
@Override
|
||||
public void endElement(String uri, String localName, String qName) {
|
||||
|
||||
switch (qName) {
|
||||
case XmlConstants.XML_ALL_ALLOWED ->
|
||||
this.allAllowed = StringHelper.parseBoolean(this.text.toString().trim());
|
||||
case XmlConstants.XML_ALLOW -> this.allowList.add(this.text.toString().trim());
|
||||
case XmlConstants.XML_DENY -> this.denyList.add(this.text.toString().trim());
|
||||
case XmlConstants.XML_PRIVILEGE -> {
|
||||
IPrivilege privilege = new PrivilegeImpl(this.privilegeName, this.privilegePolicy, this.allAllowed,
|
||||
this.denyList, this.allowList);
|
||||
this.privileges.put(this.privilegeName, privilege);
|
||||
this.privilegeName = null;
|
||||
this.privilegePolicy = null;
|
||||
this.allAllowed = false;
|
||||
this.denyList = new HashSet<>();
|
||||
this.allowList = new HashSet<>();
|
||||
}
|
||||
case XmlConstants.XML_ROLE -> {
|
||||
Role role = new Role(this.roleName, this.privileges);
|
||||
roles.put(role.getName(), role);
|
||||
logger.info(MessageFormat.format("New Role: {0}", role));
|
||||
init();
|
||||
}
|
||||
default -> throw new IllegalStateException("Unexpected value: " + qName);
|
||||
case XML_ALL_ALLOWED -> this.allAllowed = StringHelper.parseBoolean(getText());
|
||||
case XML_ALLOW -> this.allowList.add(getText());
|
||||
case XML_DENY -> this.denyList.add(getText());
|
||||
case XML_PRIVILEGE -> {
|
||||
IPrivilege privilege = new PrivilegeImpl(this.privilegeName, this.privilegePolicy, this.allAllowed,
|
||||
this.denyList, this.allowList);
|
||||
this.privileges.put(this.privilegeName, privilege);
|
||||
this.privilegeName = null;
|
||||
this.privilegePolicy = null;
|
||||
this.allAllowed = false;
|
||||
this.denyList = new HashSet<>();
|
||||
this.allowList = new HashSet<>();
|
||||
}
|
||||
case XML_ROLE -> {
|
||||
Role role = new Role(this.roleName, this.privileges);
|
||||
roles.put(role.getName(), role);
|
||||
logger.info(MessageFormat.format("New Role: {0}", role));
|
||||
init();
|
||||
}
|
||||
default -> throw new IllegalStateException("Unexpected value: " + qName);
|
||||
}
|
||||
}
|
||||
|
||||
private String getText() {
|
||||
return this.text.toString().trim();
|
||||
}
|
||||
}
|
||||
|
||||
static class PropertyParser extends ElementParserAdapter {
|
||||
|
@ -194,11 +196,11 @@ public class PrivilegeRolesSaxReader extends DefaultHandler {
|
|||
|
||||
@Override
|
||||
public void startElement(String uri, String localName, String qName, Attributes attributes) {
|
||||
if (qName.equals(XmlConstants.XML_PROPERTY)) {
|
||||
String key = attributes.getValue(XmlConstants.XML_ATTR_NAME).trim();
|
||||
String value = attributes.getValue(XmlConstants.XML_ATTR_VALUE).trim();
|
||||
if (qName.equals(XML_PROPERTY)) {
|
||||
String key = attributes.getValue(XML_ATTR_NAME).trim();
|
||||
String value = attributes.getValue(XML_ATTR_VALUE).trim();
|
||||
this.parameterMap.put(key, value);
|
||||
} else if (!qName.equals(XmlConstants.XML_PROPERTIES)) {
|
||||
} else if (!qName.equals(XML_PROPERTIES)) {
|
||||
throw new IllegalArgumentException("Unhandled tag " + qName);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package li.strolch.privilege.xml;
|
||||
|
||||
import javanet.staxutils.IndentingXMLStreamWriter;
|
||||
import li.strolch.privilege.model.IPrivilege;
|
||||
import li.strolch.privilege.model.internal.Role;
|
||||
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import static java.util.Comparator.comparing;
|
||||
import static li.strolch.privilege.helper.XmlConstants.*;
|
||||
import static li.strolch.privilege.helper.XmlHelper.*;
|
||||
|
||||
/**
|
||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||
*/
|
||||
public class PrivilegeRolesSaxWriter {
|
||||
|
||||
private final List<Role> roles;
|
||||
private final File modelFile;
|
||||
|
||||
public PrivilegeRolesSaxWriter(List<Role> roles, File modelFile) {
|
||||
this.roles = roles;
|
||||
this.modelFile = modelFile;
|
||||
}
|
||||
|
||||
public void write() throws IOException, XMLStreamException {
|
||||
|
||||
try (Writer ioWriter = new OutputStreamWriter(new FileOutputStream(this.modelFile), StandardCharsets.UTF_8)) {
|
||||
|
||||
IndentingXMLStreamWriter xmlWriter = openXmlStreamWriterDocument(ioWriter);
|
||||
xmlWriter.writeStartElement(XML_ROLES);
|
||||
|
||||
List<Role> roles = new ArrayList<>(this.roles);
|
||||
roles.sort(comparing(role1 -> role1.getName().toLowerCase(Locale.ROOT)));
|
||||
for (Role role : roles) {
|
||||
|
||||
// start the role element
|
||||
xmlWriter.writeStartElement(XML_ROLE);
|
||||
xmlWriter.writeAttribute(XML_ATTR_NAME, role.getName());
|
||||
|
||||
List<String> privilegeNames = new ArrayList<>(role.getPrivilegeNames());
|
||||
privilegeNames.sort(null);
|
||||
for (String privilegeName : privilegeNames) {
|
||||
IPrivilege privilege = role.getPrivilege(privilegeName);
|
||||
|
||||
xmlWriter.writeStartElement(XML_PRIVILEGE);
|
||||
xmlWriter.writeAttribute(XML_ATTR_NAME, privilege.getName());
|
||||
xmlWriter.writeAttribute(XML_ATTR_POLICY, privilege.getPolicy());
|
||||
|
||||
if (privilege.isAllAllowed())
|
||||
writeStringElement(xmlWriter, XML_ALL_ALLOWED, "true");
|
||||
writeStringList(xmlWriter, XML_DENY, privilege.getDenyList());
|
||||
writeStringList(xmlWriter, XML_ALLOW, privilege.getAllowList());
|
||||
|
||||
xmlWriter.writeEndElement();
|
||||
}
|
||||
|
||||
xmlWriter.writeEndElement();
|
||||
}
|
||||
|
||||
// and now end
|
||||
xmlWriter.writeEndDocument();
|
||||
xmlWriter.flush();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,165 +0,0 @@
|
|||
/*
|
||||
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package li.strolch.privilege.xml;
|
||||
|
||||
import li.strolch.privilege.helper.XmlConstants;
|
||||
import li.strolch.privilege.model.internal.PasswordCrypt;
|
||||
import li.strolch.privilege.model.internal.User;
|
||||
import li.strolch.privilege.model.internal.UserHistory;
|
||||
import li.strolch.utils.helper.StringHelper;
|
||||
import li.strolch.utils.helper.XmlHelper;
|
||||
import li.strolch.utils.iso8601.ISO8601;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static java.util.Comparator.comparing;
|
||||
import static li.strolch.privilege.helper.XmlConstants.*;
|
||||
import static li.strolch.privilege.model.internal.PasswordCrypt.buildPasswordString;
|
||||
import static li.strolch.utils.helper.StringHelper.*;
|
||||
|
||||
/**
|
||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||
*/
|
||||
public class PrivilegeUsersDomWriter {
|
||||
|
||||
private final List<User> users;
|
||||
private final File modelFile;
|
||||
|
||||
public PrivilegeUsersDomWriter(List<User> users, File modelFile) {
|
||||
this.users = users;
|
||||
this.modelFile = modelFile;
|
||||
|
||||
this.users.sort(comparing(User::getUsername));
|
||||
}
|
||||
|
||||
public void write() {
|
||||
|
||||
// create document root
|
||||
Document doc = XmlHelper.createDocument();
|
||||
Element rootElement = doc.createElement(XML_USERS);
|
||||
doc.appendChild(rootElement);
|
||||
|
||||
this.users.forEach(user -> {
|
||||
|
||||
// create the user element
|
||||
Element userElement = doc.createElement(XML_USER);
|
||||
rootElement.appendChild(userElement);
|
||||
|
||||
userElement.setAttribute(XML_ATTR_USER_ID, user.getUserId());
|
||||
userElement.setAttribute(XML_ATTR_USERNAME, user.getUsername());
|
||||
writePassword(user, userElement);
|
||||
|
||||
// add first name element
|
||||
if (isNotEmpty(user.getFirstname())) {
|
||||
Element firstnameElement = doc.createElement(XML_FIRSTNAME);
|
||||
firstnameElement.setTextContent(user.getFirstname());
|
||||
userElement.appendChild(firstnameElement);
|
||||
}
|
||||
|
||||
// add last name element
|
||||
if (isNotEmpty(user.getLastname())) {
|
||||
Element lastnameElement = doc.createElement(XML_LASTNAME);
|
||||
lastnameElement.setTextContent(user.getLastname());
|
||||
userElement.appendChild(lastnameElement);
|
||||
}
|
||||
|
||||
// add state element
|
||||
Element stateElement = doc.createElement(XML_STATE);
|
||||
stateElement.setTextContent(user.getUserState().toString());
|
||||
userElement.appendChild(stateElement);
|
||||
|
||||
// add locale element
|
||||
Element localeElement = doc.createElement(XML_LOCALE);
|
||||
localeElement.setTextContent(user.getLocale().toLanguageTag());
|
||||
userElement.appendChild(localeElement);
|
||||
|
||||
// add password change requested element
|
||||
if (user.isPasswordChangeRequested()) {
|
||||
Element passwordChangeRequestedElement = doc.createElement(XML_PASSWORD_CHANGE_REQUESTED);
|
||||
passwordChangeRequestedElement.setTextContent(Boolean.toString(true));
|
||||
userElement.appendChild(passwordChangeRequestedElement);
|
||||
}
|
||||
|
||||
// add all the role elements
|
||||
Element rolesElement = doc.createElement(XML_ROLES);
|
||||
userElement.appendChild(rolesElement);
|
||||
user.getRoles().stream().sorted().forEach(roleName -> {
|
||||
Element roleElement = doc.createElement(XML_ROLE);
|
||||
roleElement.setTextContent(roleName);
|
||||
rolesElement.appendChild(roleElement);
|
||||
});
|
||||
|
||||
// add the parameters
|
||||
if (!user.getProperties().isEmpty()) {
|
||||
Element parametersElement = doc.createElement(XML_PROPERTIES);
|
||||
userElement.appendChild(parametersElement);
|
||||
user.getProperties().entrySet().stream().sorted(Map.Entry.comparingByKey()).forEach(entry -> {
|
||||
Element paramElement = doc.createElement(XML_PROPERTY);
|
||||
paramElement.setAttribute(XML_ATTR_NAME, entry.getKey());
|
||||
paramElement.setAttribute(XML_ATTR_VALUE, entry.getValue());
|
||||
parametersElement.appendChild(paramElement);
|
||||
});
|
||||
}
|
||||
|
||||
if (!user.isHistoryEmpty()) {
|
||||
UserHistory history = user.getHistory();
|
||||
Element historyElement = doc.createElement(XML_HISTORY);
|
||||
userElement.appendChild(historyElement);
|
||||
|
||||
if (!history.isFirstLoginEmpty()) {
|
||||
Element element = doc.createElement(XML_FIRST_LOGIN);
|
||||
element.setTextContent(ISO8601.toString(history.getFirstLogin()));
|
||||
historyElement.appendChild(element);
|
||||
}
|
||||
|
||||
if (!history.isLastLoginEmpty()) {
|
||||
Element element = doc.createElement(XML_LAST_LOGIN);
|
||||
element.setTextContent(ISO8601.toString(history.getLastLogin()));
|
||||
historyElement.appendChild(element);
|
||||
}
|
||||
|
||||
if (!history.isLastPasswordChangeEmpty()) {
|
||||
Element element = doc.createElement(XML_LAST_PASSWORD_CHANGE);
|
||||
element.setTextContent(ISO8601.toString(history.getLastPasswordChange()));
|
||||
historyElement.appendChild(element);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// write the container file to disk
|
||||
XmlHelper.writeDocument(doc, this.modelFile);
|
||||
}
|
||||
|
||||
private void writePassword(User user, Element userElement) {
|
||||
PasswordCrypt passwordCrypt = user.getPasswordCrypt();
|
||||
if (passwordCrypt == null)
|
||||
return;
|
||||
|
||||
String passwordString = passwordCrypt.buildPasswordString();
|
||||
if (passwordString != null) {
|
||||
userElement.setAttribute(XML_ATTR_PASSWORD, passwordString);
|
||||
} else {
|
||||
if (passwordCrypt.getPassword() != null)
|
||||
userElement.setAttribute(XML_ATTR_PASSWORD, toHexString(passwordCrypt.getPassword()));
|
||||
if (passwordCrypt.getSalt() != null)
|
||||
userElement.setAttribute(XML_ATTR_SALT, toHexString(passwordCrypt.getSalt()));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,16 +15,10 @@
|
|||
*/
|
||||
package li.strolch.privilege.xml;
|
||||
|
||||
import static li.strolch.privilege.helper.XmlConstants.*;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.*;
|
||||
|
||||
import li.strolch.privilege.model.UserState;
|
||||
import li.strolch.privilege.model.internal.PasswordCrypt;
|
||||
import li.strolch.privilege.model.internal.User;
|
||||
import li.strolch.privilege.model.internal.UserHistory;
|
||||
import li.strolch.utils.helper.StringHelper;
|
||||
import li.strolch.utils.iso8601.ISO8601;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -32,6 +26,11 @@ import org.xml.sax.Attributes;
|
|||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.helpers.DefaultHandler;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.*;
|
||||
|
||||
import static li.strolch.privilege.helper.XmlConstants.*;
|
||||
|
||||
/**
|
||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||
*/
|
||||
|
@ -59,8 +58,12 @@ public class PrivilegeUsersSaxReader extends DefaultHandler {
|
|||
@Override
|
||||
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
|
||||
if (qName.equals(XML_USER)) {
|
||||
if (this.buildersStack.stream().anyMatch(e -> e.getClass().equals(UserParser.class)))
|
||||
throw new IllegalArgumentException("Previous User not closed!");
|
||||
this.buildersStack.push(new UserParser());
|
||||
} else if (qName.equals(XML_PROPERTIES)) {
|
||||
if (this.buildersStack.stream().anyMatch(e -> e.getClass().equals(PropertyParser.class)))
|
||||
throw new IllegalArgumentException("Previous Properties not closed!");
|
||||
this.buildersStack.push(new PropertyParser());
|
||||
}
|
||||
|
||||
|
@ -157,17 +160,15 @@ public class PrivilegeUsersSaxReader extends DefaultHandler {
|
|||
public void endElement(String uri, String localName, String qName) {
|
||||
|
||||
switch (qName) {
|
||||
case XML_FIRSTNAME -> this.firstName = this.text.toString().trim();
|
||||
case XML_LASTNAME -> this.lastname = this.text.toString().trim();
|
||||
case XML_STATE -> this.userState = UserState.valueOf(this.text.toString().trim());
|
||||
case XML_LOCALE -> this.locale = Locale.forLanguageTag(this.text.toString().trim());
|
||||
case XML_PASSWORD_CHANGE_REQUESTED ->
|
||||
this.passwordChangeRequested = Boolean.parseBoolean(this.text.toString().trim());
|
||||
case XML_FIRST_LOGIN -> this.history.setFirstLogin(ISO8601.parseToZdt(this.text.toString().trim()));
|
||||
case XML_LAST_LOGIN -> this.history.setLastLogin(ISO8601.parseToZdt(this.text.toString().trim()));
|
||||
case XML_LAST_PASSWORD_CHANGE ->
|
||||
this.history.setLastPasswordChange(ISO8601.parseToZdt(this.text.toString().trim()));
|
||||
case XML_ROLE -> this.userRoles.add(this.text.toString().trim());
|
||||
case XML_FIRSTNAME -> this.firstName = getText();
|
||||
case XML_LASTNAME -> this.lastname = getText();
|
||||
case XML_STATE -> this.userState = UserState.valueOf(getText());
|
||||
case XML_LOCALE -> this.locale = Locale.forLanguageTag(getText());
|
||||
case XML_PASSWORD_CHANGE_REQUESTED -> this.passwordChangeRequested = Boolean.parseBoolean(getText());
|
||||
case XML_FIRST_LOGIN -> this.history.setFirstLogin(ISO8601.parseToZdt(getText()));
|
||||
case XML_LAST_LOGIN -> this.history.setLastLogin(ISO8601.parseToZdt(getText()));
|
||||
case XML_LAST_PASSWORD_CHANGE -> this.history.setLastPasswordChange(ISO8601.parseToZdt(getText()));
|
||||
case XML_ROLE -> this.userRoles.add(getText());
|
||||
case XML_USER -> {
|
||||
if (this.history == null)
|
||||
this.history = new UserHistory();
|
||||
|
@ -191,6 +192,10 @@ public class PrivilegeUsersSaxReader extends DefaultHandler {
|
|||
}
|
||||
}
|
||||
|
||||
private String getText() {
|
||||
return this.text.toString().trim();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyChild(ElementParser child) {
|
||||
if (child instanceof PropertyParser) {
|
||||
|
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package li.strolch.privilege.xml;
|
||||
|
||||
import javanet.staxutils.IndentingXMLStreamWriter;
|
||||
import li.strolch.privilege.model.internal.PasswordCrypt;
|
||||
import li.strolch.privilege.model.internal.User;
|
||||
import li.strolch.privilege.model.internal.UserHistory;
|
||||
import li.strolch.utils.iso8601.ISO8601;
|
||||
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import javax.xml.stream.XMLStreamWriter;
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import static java.util.Comparator.comparing;
|
||||
import static li.strolch.privilege.helper.XmlConstants.*;
|
||||
import static li.strolch.privilege.helper.XmlHelper.*;
|
||||
import static li.strolch.utils.helper.StringHelper.isNotEmpty;
|
||||
import static li.strolch.utils.helper.StringHelper.toHexString;
|
||||
|
||||
/**
|
||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||
*/
|
||||
public class PrivilegeUsersSaxWriter {
|
||||
|
||||
private final List<User> users;
|
||||
private final File modelFile;
|
||||
|
||||
public PrivilegeUsersSaxWriter(List<User> users, File modelFile) {
|
||||
this.users = users;
|
||||
this.modelFile = modelFile;
|
||||
|
||||
this.users.sort(comparing(User::getUsername));
|
||||
}
|
||||
|
||||
public void write() throws IOException, XMLStreamException {
|
||||
|
||||
try (Writer ioWriter = new OutputStreamWriter(new FileOutputStream(this.modelFile), StandardCharsets.UTF_8)) {
|
||||
|
||||
IndentingXMLStreamWriter xmlWriter = openXmlStreamWriterDocument(ioWriter);
|
||||
xmlWriter.writeStartElement(XML_USERS);
|
||||
|
||||
List<User> users = new ArrayList<>(this.users);
|
||||
users.sort(comparing(u -> u.getUsername().toLowerCase(Locale.ROOT)));
|
||||
for (User user : this.users) {
|
||||
|
||||
// start the user element
|
||||
xmlWriter.writeStartElement(XML_USER);
|
||||
|
||||
xmlWriter.writeAttribute(XML_ATTR_USER_ID, user.getUserId());
|
||||
xmlWriter.writeAttribute(XML_ATTR_USERNAME, user.getUsername());
|
||||
writePassword(user, xmlWriter);
|
||||
|
||||
// add first name element
|
||||
if (isNotEmpty(user.getFirstname()))
|
||||
writeStringElement(xmlWriter, XML_FIRSTNAME, user.getFirstname());
|
||||
|
||||
// add last name element
|
||||
if (isNotEmpty(user.getLastname()))
|
||||
writeStringElement(xmlWriter, XML_LASTNAME, user.getLastname());
|
||||
|
||||
// add state element
|
||||
writeStringElement(xmlWriter, XML_STATE, user.getUserState().toString());
|
||||
|
||||
// add locale element
|
||||
writeStringElement(xmlWriter, XML_LOCALE, user.getLocale().toLanguageTag());
|
||||
|
||||
// add password change requested element
|
||||
if (user.isPasswordChangeRequested())
|
||||
writeStringElement(xmlWriter, XML_PASSWORD_CHANGE_REQUESTED, "true");
|
||||
|
||||
// add all the role elements
|
||||
if (!user.getRoles().isEmpty()) {
|
||||
xmlWriter.writeStartElement(XML_ROLES);
|
||||
writeStringList(xmlWriter, XML_ROLE, user.getRoles());
|
||||
xmlWriter.writeEndElement();
|
||||
}
|
||||
|
||||
// add the parameters
|
||||
Map<String, String> properties = user.getProperties();
|
||||
if (!properties.isEmpty()) {
|
||||
writeStringMapElement(xmlWriter, properties, XML_PROPERTIES, XML_PROPERTY);
|
||||
}
|
||||
|
||||
if (!user.isHistoryEmpty()) {
|
||||
UserHistory history = user.getHistory();
|
||||
xmlWriter.writeStartElement(XML_HISTORY);
|
||||
|
||||
if (!history.isFirstLoginEmpty())
|
||||
writeStringElement(xmlWriter, XML_FIRST_LOGIN, ISO8601.toString(history.getFirstLogin()));
|
||||
|
||||
if (!history.isLastLoginEmpty())
|
||||
writeStringElement(xmlWriter, XML_LAST_LOGIN, ISO8601.toString(history.getLastLogin()));
|
||||
|
||||
if (!history.isLastPasswordChangeEmpty())
|
||||
writeStringElement(xmlWriter, XML_LAST_PASSWORD_CHANGE,
|
||||
ISO8601.toString(history.getLastPasswordChange()));
|
||||
|
||||
xmlWriter.writeEndElement();
|
||||
}
|
||||
|
||||
xmlWriter.writeEndElement();
|
||||
}
|
||||
|
||||
// and now end
|
||||
xmlWriter.writeEndDocument();
|
||||
xmlWriter.flush();
|
||||
}
|
||||
}
|
||||
|
||||
private void writePassword(User user, XMLStreamWriter xmlStreamWriter) throws XMLStreamException {
|
||||
PasswordCrypt passwordCrypt = user.getPasswordCrypt();
|
||||
if (passwordCrypt == null)
|
||||
return;
|
||||
|
||||
String passwordString = passwordCrypt.buildPasswordString();
|
||||
if (passwordString != null) {
|
||||
xmlStreamWriter.writeAttribute(XML_ATTR_PASSWORD, passwordString);
|
||||
} else {
|
||||
if (passwordCrypt.getPassword() != null)
|
||||
xmlStreamWriter.writeAttribute(XML_ATTR_PASSWORD, toHexString(passwordCrypt.getPassword()));
|
||||
if (passwordCrypt.getSalt() != null)
|
||||
xmlStreamWriter.writeAttribute(XML_ATTR_SALT, toHexString(passwordCrypt.getSalt()));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,14 +4,17 @@ import static li.strolch.privilege.test.XmlTest.SRC_TEST;
|
|||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import li.strolch.privilege.helper.WriteRolesFileHelper;
|
||||
import org.junit.Test;
|
||||
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
|
||||
public class WriteRolesFileHelperTest {
|
||||
|
||||
@Test
|
||||
public void shouldReadAndWriteRolesFile() {
|
||||
public void shouldReadAndWriteRolesFile() throws XMLStreamException, IOException {
|
||||
|
||||
String src = SRC_TEST + "PrivilegeRoles.xml";
|
||||
String dst = "target/WriteRolesFileHelperTest_roles.xml";
|
||||
|
@ -19,7 +22,7 @@ public class WriteRolesFileHelperTest {
|
|||
if (new File(dst).exists() && !new File(dst).delete())
|
||||
throw new IllegalStateException("Could not delete file " + dst);
|
||||
|
||||
WriteRolesFileHelper.main(new String[] { src, dst });
|
||||
WriteRolesFileHelper.main(new String[]{src, dst});
|
||||
|
||||
assertTrue(new File(dst).exists());
|
||||
}
|
||||
|
|
|
@ -15,10 +15,7 @@
|
|||
*/
|
||||
package li.strolch.privilege.test;
|
||||
|
||||
import li.strolch.privilege.handler.DefaultEncryptionHandler;
|
||||
import li.strolch.privilege.handler.MailUserChallengeHandler;
|
||||
import li.strolch.privilege.handler.PrivilegeHandler;
|
||||
import li.strolch.privilege.handler.XmlPersistenceHandler;
|
||||
import li.strolch.privilege.handler.*;
|
||||
import li.strolch.privilege.model.IPrivilege;
|
||||
import li.strolch.privilege.model.UserState;
|
||||
import li.strolch.privilege.model.internal.*;
|
||||
|
@ -33,7 +30,10 @@ import org.junit.Test;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
|
@ -115,7 +115,7 @@ public class XmlTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void canWriteConfig() {
|
||||
public void canWriteConfig() throws XMLStreamException, IOException {
|
||||
|
||||
Map<String, String> parameterMap = new HashMap<>();
|
||||
Map<String, String> encryptionHandlerParameterMap = new HashMap<>();
|
||||
|
@ -128,6 +128,7 @@ public class XmlTest {
|
|||
|
||||
PrivilegeContainerModel containerModel = new PrivilegeContainerModel();
|
||||
containerModel.setParameterMap(parameterMap);
|
||||
containerModel.setPrivilegeHandlerClassName(DefaultPrivilegeHandler.class.getName());
|
||||
containerModel.setEncryptionHandlerClassName(DefaultEncryptionHandler.class.getName());
|
||||
containerModel.setEncryptionHandlerParameterMap(encryptionHandlerParameterMap);
|
||||
containerModel.setPersistenceHandlerClassName(XmlPersistenceHandler.class.getName());
|
||||
|
@ -138,11 +139,38 @@ public class XmlTest {
|
|||
containerModel.addPolicy("DefaultPrivilege", "li.strolch.privilege.policy.DefaultPrivilege");
|
||||
|
||||
File configFile = new File(TARGET_TEST + "PrivilegeTest.xml");
|
||||
PrivilegeConfigDomWriter configSaxWriter = new PrivilegeConfigDomWriter(containerModel, configFile);
|
||||
PrivilegeConfigSaxWriter configSaxWriter = new PrivilegeConfigSaxWriter(containerModel, configFile);
|
||||
configSaxWriter.write();
|
||||
|
||||
String fileHash = StringHelper.toHexString(FileHelper.hashFileSha256(configFile));
|
||||
assertEquals("dcb6b3ed7198e0a7c88bf5c61c0bd6f0d684415f2a2f29429879edc6bc795f06", fileHash);
|
||||
String expected = """
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Privilege>
|
||||
<Container>
|
||||
<Parameters>
|
||||
<Parameter name="autoPersistOnPasswordChange" value="true"/>
|
||||
</Parameters>
|
||||
<PrivilegeHandler class="li.strolch.privilege.handler.DefaultPrivilegeHandler"/>
|
||||
<EncryptionHandler class="li.strolch.privilege.handler.DefaultEncryptionHandler">
|
||||
<Parameters>
|
||||
<Parameter name="hashAlgorithm" value="SHA-256"/>
|
||||
</Parameters>
|
||||
</EncryptionHandler>
|
||||
<PersistenceHandler class="li.strolch.privilege.handler.XmlPersistenceHandler">
|
||||
<Parameters>
|
||||
<Parameter name="basePath" value="target/test/"/>
|
||||
<Parameter name="modelXmlFile" value="PrivilegeModel.xml"/>
|
||||
</Parameters>
|
||||
</PersistenceHandler>
|
||||
<UserChallengeHandler class="li.strolch.privilege.handler.MailUserChallengeHandler"/>
|
||||
<SsoHandler class="li.strolch.privilege.test.model.DummySsoHandler"/>
|
||||
</Container>
|
||||
<Policies>
|
||||
<Policy name="DefaultPrivilege" class="li.strolch.privilege.policy.DefaultPrivilege"/>
|
||||
</Policies>
|
||||
</Privilege>
|
||||
""";
|
||||
|
||||
assertEquals(expected, Files.readString(configFile.toPath()));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -295,7 +323,7 @@ public class XmlTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void canWriteUsers() {
|
||||
public void canWriteUsers() throws XMLStreamException, IOException {
|
||||
|
||||
Map<String, String> propertyMap;
|
||||
Set<String> userRoles;
|
||||
|
@ -324,7 +352,7 @@ public class XmlTest {
|
|||
users.add(user2);
|
||||
|
||||
File modelFile = new File(TARGET_TEST + "PrivilegeUsersTest.xml");
|
||||
PrivilegeUsersDomWriter configSaxWriter = new PrivilegeUsersDomWriter(users, modelFile);
|
||||
PrivilegeUsersSaxWriter configSaxWriter = new PrivilegeUsersSaxWriter(users, modelFile);
|
||||
configSaxWriter.write();
|
||||
|
||||
PrivilegeUsersSaxReader xmlHandler = new PrivilegeUsersSaxReader(true);
|
||||
|
@ -361,7 +389,7 @@ public class XmlTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void canWriteRoles() {
|
||||
public void canWriteRoles() throws XMLStreamException, IOException {
|
||||
|
||||
Map<String, IPrivilege> privilegeMap;
|
||||
List<Role> roles = new ArrayList<>();
|
||||
|
@ -381,8 +409,8 @@ public class XmlTest {
|
|||
roles.add(role2);
|
||||
|
||||
File modelFile = new File(TARGET_TEST + "PrivilegeRolesTest.xml");
|
||||
PrivilegeRolesDomWriter configSaxWriter = new PrivilegeRolesDomWriter(roles, modelFile);
|
||||
configSaxWriter.write();
|
||||
PrivilegeRolesSaxWriter writer = new PrivilegeRolesSaxWriter(roles, modelFile);
|
||||
writer.write();
|
||||
|
||||
PrivilegeRolesSaxReader xmlHandler = new PrivilegeRolesSaxReader();
|
||||
XmlHelper.parseDocument(modelFile, xmlHandler);
|
||||
|
|
Loading…
Reference in New Issue