getDenyList() {
+ return this.denyList;
+ }
+
+ public boolean hasAllowed() {
+ return !this.allowList.isEmpty();
+ }
+
+ public boolean isAllowed(String value) {
+ return this.allowList.contains(value);
+ }
+
+ public boolean hasDenied() {
+ return !this.allowList.isEmpty();
+ }
+
+ public boolean isDenied(String value) {
+ return this.denyList.contains(value);
+ }
+
+ @Override
+ public String toString() {
+ return "Privilege [name=" + this.name + ", policy=" + this.policy + "]";
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((this.name == null) ? 0 : this.name.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Privilege other = (Privilege) obj;
+ if (this.name == null)
+ return other.name == null;
+ return this.name.equals(other.name);
+ }
+
+ /**
+ * Constructs a {@link Privilege} from the {@link PrivilegeRep}
+ *
+ * @param privilegeRep the {@link PrivilegeRep} from which to create the {@link Privilege}
+ */
+ public static Privilege of(PrivilegeRep privilegeRep) {
+ return new Privilege(privilegeRep.getName(), privilegeRep.getPolicy(), privilegeRep.isAllAllowed(),
+ privilegeRep.getDenyList(), privilegeRep.getAllowList());
+ }
+}
\ No newline at end of file
diff --git a/privilege/src/main/java/li/strolch/privilege/model/PrivilegeContext.java b/privilege/src/main/java/li/strolch/privilege/model/PrivilegeContext.java
index b7b8999af..6ae46e6ee 100644
--- a/privilege/src/main/java/li/strolch/privilege/model/PrivilegeContext.java
+++ b/privilege/src/main/java/li/strolch/privilege/model/PrivilegeContext.java
@@ -15,14 +15,16 @@
*/
package li.strolch.privilege.model;
-import java.text.MessageFormat;
+import li.strolch.privilege.base.AccessDeniedException;
+import li.strolch.privilege.base.PrivilegeException;
+import li.strolch.privilege.policy.PrivilegePolicy;
+import li.strolch.utils.dbc.DBC;
+
import java.util.Map;
import java.util.Set;
-import li.strolch.privilege.base.AccessDeniedException;
-import li.strolch.privilege.base.PrivilegeException;
-import li.strolch.privilege.i18n.PrivilegeMessages;
-import li.strolch.privilege.policy.PrivilegePolicy;
+import static java.text.MessageFormat.format;
+import static li.strolch.privilege.i18n.PrivilegeMessages.getString;
/**
*
@@ -36,19 +38,15 @@ import li.strolch.privilege.policy.PrivilegePolicy;
*
* @author Robert von Burg
*/
-public class PrivilegeContext {
+public record PrivilegeContext(UserRep userRep, Certificate certificate, Map privileges,
+ Map policies) {
- //
- // object state
- //
-
- private final UserRep userRep;
- private final Certificate certificate;
- private final Map privileges;
- private final Map policies;
-
- public PrivilegeContext(UserRep userRep, Certificate certificate, Map privileges,
+ public PrivilegeContext(UserRep userRep, Certificate certificate, Map privileges,
Map policies) {
+ DBC.PRE.assertNotNull("userRep must not be null", userRep);
+ DBC.PRE.assertNotNull("certificate must not be null", certificate);
+ DBC.PRE.assertNotNull("privileges must not be null", privileges);
+ DBC.PRE.assertNotNull("policies must not be null", policies);
this.userRep = userRep;
this.certificate = certificate;
this.privileges = Map.copyOf(privileges);
@@ -85,35 +83,64 @@ public class PrivilegeContext {
public void assertHasPrivilege(String privilegeName) throws AccessDeniedException {
if (!this.privileges.containsKey(privilegeName)) {
- String msg = MessageFormat.format(PrivilegeMessages.getString("Privilege.noprivilege.user"),
- userRep.getUsername(), privilegeName);
+ String msg = format(getString("Privilege.noprivilege.user"), userRep.getUsername(), privilegeName);
throw new AccessDeniedException(msg);
}
}
+ public boolean hasGroup(String groupName) {
+ return this.userRep.hasGroup(groupName);
+ }
+
public boolean hasRole(String roleName) {
return this.userRep.hasRole(roleName);
}
- public void assertHasRole(String roleName) throws AccessDeniedException {
- if (!this.userRep.hasRole(roleName)) {
- String msg = MessageFormat.format(PrivilegeMessages.getString("Privilege.noprivilege.role"),
- userRep.getUsername(), roleName);
+ public void assertHasGroup(String groupName) throws AccessDeniedException {
+ if (!this.userRep.hasGroup(groupName)) {
+ String msg = format(getString("Privilege.noprivilege.group"), userRep.getUsername(), groupName);
throw new AccessDeniedException(msg);
}
}
+ public void assertHasRole(String roleName) throws AccessDeniedException {
+ if (!this.userRep.hasRole(roleName)) {
+ String msg = format(getString("Privilege.noprivilege.role"), userRep.getUsername(), roleName);
+ throw new AccessDeniedException(msg);
+ }
+ }
+
+ public void assertHasAnyGroup(String... groupNames) throws AccessDeniedException {
+ for (String groupName : groupNames) {
+ if (this.userRep.hasGroup(groupName))
+ return;
+ }
+
+ String msg = format(getString("Privilege.noprivilege.group"), userRep.getUsername(),
+ String.join(", ", groupNames));
+ throw new AccessDeniedException(msg);
+ }
+
public void assertHasAnyRole(String... roleNames) throws AccessDeniedException {
for (String roleName : roleNames) {
if (this.userRep.hasRole(roleName))
return;
}
- String msg = MessageFormat.format(PrivilegeMessages.getString("Privilege.noprivilege.role"),
- userRep.getUsername(), String.join(", ", roleNames));
+ String msg = format(getString("Privilege.noprivilege.role"), userRep.getUsername(),
+ String.join(", ", roleNames));
throw new AccessDeniedException(msg);
}
+ public boolean hasAnyGroup(String... groupNames) throws AccessDeniedException {
+ for (String groupName : groupNames) {
+ if (this.userRep.hasGroup(groupName))
+ return true;
+ }
+
+ return false;
+ }
+
public boolean hasAnyRole(String... roleNames) throws AccessDeniedException {
for (String roleName : roleNames) {
if (this.userRep.hasRole(roleName))
@@ -123,7 +150,7 @@ public class PrivilegeContext {
return false;
}
- public IPrivilege getPrivilege(String privilegeName) throws AccessDeniedException {
+ public Privilege getPrivilege(String privilegeName) throws AccessDeniedException {
assertHasPrivilege(privilegeName);
return this.privileges.get(privilegeName);
}
@@ -132,7 +159,7 @@ public class PrivilegeContext {
PrivilegePolicy policy = this.policies.get(policyName);
if (policy == null) {
String msg = "The PrivilegePolicy {0} does not exist on the PrivilegeContext!";
- throw new PrivilegeException(MessageFormat.format(msg, policyName));
+ throw new PrivilegeException(format(msg, policyName));
}
return policy;
}
@@ -148,15 +175,12 @@ public class PrivilegeContext {
*
* This method uses the {@link SimpleRestrictable} to verify access
*
- * @param privilegeName
- * the name of the privilege to verify
- * @param privilegeValue
- * the value
+ * @param privilegeName the name of the privilege to verify
+ * @param privilegeValue the value
*
- * @throws AccessDeniedException
- * if the user does not have access
- * @throws PrivilegeException
- * if there is an internal error due to wrongly configured privileges or programming errors
+ * @throws AccessDeniedException if the user does not have access
+ * @throws PrivilegeException if there is an internal error due to wrongly configured privileges or programming
+ * errors
*/
public void validateAction(String privilegeName, String privilegeValue)
throws PrivilegeException, AccessDeniedException {
@@ -168,22 +192,20 @@ public class PrivilegeContext {
* has the privilege, then this method returns with no exception and void, if the user does not have the privilege,
* then a {@link AccessDeniedException} is thrown.
*
- * @param restrictable
- * the {@link Restrictable} which the user wants to access
+ * @param restrictable the {@link Restrictable} which the user wants to access
*
- * @throws AccessDeniedException
- * if the user does not have access
- * @throws PrivilegeException
- * if there is an internal error due to wrongly configured privileges or programming errors
+ * @throws AccessDeniedException if the user does not have access
+ * @throws PrivilegeException if there is an internal error due to wrongly configured privileges or programming
+ * errors
*/
public void validateAction(Restrictable restrictable) throws PrivilegeException, AccessDeniedException {
// the privilege for the restrictable
String privilegeName = restrictable.getPrivilegeName();
- IPrivilege privilege = this.privileges.get(privilegeName);
+ Privilege privilege = this.privileges.get(privilegeName);
if (privilege == null) {
- String msg = MessageFormat.format(PrivilegeMessages.getString("Privilege.accessdenied.noprivilege"),
- getUsername(), privilegeName, restrictable.getClass().getName(), restrictable.getPrivilegeValue());
+ String msg = format(getString("Privilege.accessdenied.noprivilege"), getUsername(), privilegeName,
+ restrictable.getClass().getName(), restrictable.getPrivilegeValue());
throw new AccessDeniedException(msg);
}
@@ -199,19 +221,18 @@ public class PrivilegeContext {
* Validates if the user for this context has the privilege to access to the given {@link Restrictable}. Returning
* true if the user has the privilege, and false if not
*
- * @param restrictable
- * the {@link Restrictable} which the user wants to access
+ * @param restrictable the {@link Restrictable} which the user wants to access
*
* @return returns true if the user has the privilege, and false if not
*
- * @throws PrivilegeException
- * if there is an internal error due to wrongly configured privileges or programming errors
+ * @throws PrivilegeException if there is an internal error due to wrongly configured privileges or programming
+ * errors
*/
public boolean hasPrivilege(Restrictable restrictable) throws PrivilegeException {
// the privilege for the restrictable
String privilegeName = restrictable.getPrivilegeName();
- IPrivilege privilege = this.privileges.get(privilegeName);
+ Privilege privilege = this.privileges.get(privilegeName);
if (privilege == null)
return false;
@@ -229,15 +250,13 @@ public class PrivilegeContext {
*
* This method uses the {@link SimpleRestrictable} to verify access
*
- * @param privilegeName
- * the name of the privilege to verify
- * @param privilegeValue
- * the value
+ * @param privilegeName the name of the privilege to verify
+ * @param privilegeValue the value
*
* @return returns true if the user has the privilege, and false if not
*
- * @throws PrivilegeException
- * if there is an internal error due to wrongly configured privileges or programming errors
+ * @throws PrivilegeException if there is an internal error due to wrongly configured privileges or programming
+ * errors
*/
public boolean hasPrivilege(String privilegeName, String privilegeValue) throws PrivilegeException {
return hasPrivilege(new SimpleRestrictable(privilegeName, privilegeValue));
diff --git a/privilege/src/main/java/li/strolch/privilege/model/PrivilegeRep.java b/privilege/src/main/java/li/strolch/privilege/model/PrivilegeRep.java
index bdff20a9f..959e0d14b 100644
--- a/privilege/src/main/java/li/strolch/privilege/model/PrivilegeRep.java
+++ b/privilege/src/main/java/li/strolch/privilege/model/PrivilegeRep.java
@@ -15,27 +15,25 @@
*/
package li.strolch.privilege.model;
-import static li.strolch.utils.helper.StringHelper.trimOrEmpty;
-
-import java.io.Serializable;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.stream.Collectors;
-
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.handler.PrivilegeHandler;
import li.strolch.privilege.model.internal.Role;
import li.strolch.privilege.policy.PrivilegePolicy;
-import li.strolch.utils.helper.StringHelper;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import static li.strolch.utils.helper.StringHelper.isEmpty;
+import static li.strolch.utils.helper.StringHelper.trimOrEmpty;
/**
- * To keep certain details of the {@link IPrivilege} itself hidden from remote clients and make sure instances are only
+ * To keep certain details of the {@link Privilege} itself hidden from remote clients and make sure instances are only
* edited by users with the correct privilege, this representational version is allowed to be viewed by remote clients
- * and simply wraps all public data from the {@link IPrivilege}
+ * and simply wraps all public data from the {@link Privilege}
*
* @author Robert von Burg
*/
-public class PrivilegeRep implements Serializable {
+public class PrivilegeRep {
private String name;
private String policy;
@@ -43,48 +41,57 @@ public class PrivilegeRep implements Serializable {
private Set denyList;
private Set allowList;
+ private boolean readOnly;
+
/**
* Default constructor
*
- * @param name
- * the name of this privilege, which is unique to all privileges known in the {@link PrivilegeHandler}
- * @param policy
- * the {@link PrivilegePolicy} configured to evaluate if the privilege is granted
- * @param allAllowed
- * a boolean defining if a {@link Role} with this {@link IPrivilege} has unrestricted access to a {@link
- * Restrictable}
- * @param denyList
- * a list of deny rules for this {@link IPrivilege}
- * @param allowList
- * a list of allow rules for this {@link IPrivilege}
+ * @param name the name of this privilege, which is unique to all privileges known in the
+ * {@link PrivilegeHandler}
+ * @param policy the {@link PrivilegePolicy} configured to evaluate if the privilege is granted
+ * @param allAllowed a boolean defining if a {@link Role} with this {@link Privilege} has unrestricted access to a
+ * {@link Restrictable}
+ * @param denyList a list of deny rules for this {@link Privilege}
+ * @param allowList a list of allow rules for this {@link Privilege}
*/
public PrivilegeRep(String name, String policy, boolean allAllowed, Set denyList, Set allowList) {
this.name = trimOrEmpty(name);
this.policy = trimOrEmpty(policy);
this.allAllowed = allAllowed;
- this.denyList = denyList;
- this.allowList = allowList;
+ setDenyList(denyList == null ? Set.of() : denyList);
+ setAllowList(allowList == null ? Set.of() : allowList);
+ }
+
+ public boolean isReadOnly() {
+ return readOnly;
+ }
+
+ public PrivilegeRep readOnly() {
+ if (this.readOnly)
+ return this;
+ this.readOnly = true;
+ this.denyList = Set.copyOf(this.denyList);
+ this.allowList = Set.copyOf(this.allowList);
+ return this;
+ }
+
+ protected void assertNotReadonly() {
+ if (this.readOnly)
+ throw new IllegalStateException("Privilege is currently readOnly, to modify get a copy!");
}
/**
* Validates that all required fields are set
*/
public void validate() {
-
- if (StringHelper.isEmpty(this.name)) {
+ if (isEmpty(this.name))
throw new PrivilegeException("No name defined!");
- }
-
- if (StringHelper.isEmpty(this.policy)) {
- throw new PrivilegeException("policy is null!");
- }
-
- if (this.denyList == null) {
+ if (isEmpty(this.policy))
+ throw new PrivilegeException("No policy defined!");
+ if (this.denyList == null)
throw new PrivilegeException("denyList is null");
- }
- if (this.allowList == null) {
+ if (this.allowList == null)
throw new PrivilegeException("allowList is null");
- }
}
/**
@@ -95,10 +102,10 @@ public class PrivilegeRep implements Serializable {
}
/**
- * @param name
- * the name to set
+ * @param name the name to set
*/
public void setName(String name) {
+ assertNotReadonly();
this.name = trimOrEmpty(name);
}
@@ -110,10 +117,10 @@ public class PrivilegeRep implements Serializable {
}
/**
- * @param policy
- * the policy to set
+ * @param policy the policy to set
*/
public void setPolicy(String policy) {
+ assertNotReadonly();
this.policy = trimOrEmpty(policy);
}
@@ -125,10 +132,10 @@ public class PrivilegeRep implements Serializable {
}
/**
- * @param allAllowed
- * the allAllowed to set
+ * @param allAllowed the allAllowed to set
*/
public void setAllAllowed(boolean allAllowed) {
+ assertNotReadonly();
this.allAllowed = allAllowed;
}
@@ -136,30 +143,30 @@ public class PrivilegeRep implements Serializable {
* @return the denyList
*/
public Set getDenyList() {
- return this.denyList == null ? new HashSet<>() : this.denyList;
+ return this.denyList;
}
/**
- * @param denyList
- * the denyList to set
+ * @param denyList the denyList to set
*/
public void setDenyList(Set denyList) {
- this.denyList = denyList.stream().map(String::trim).collect(Collectors.toSet());
+ assertNotReadonly();
+ this.denyList = denyList.stream().map(String::trim).collect(HashSet::new, HashSet::add, HashSet::addAll);
}
/**
* @return the allowList
*/
public Set getAllowList() {
- return this.allowList == null ? new HashSet<>() : this.allowList;
+ return this.allowList;
}
/**
- * @param allowList
- * the allowList to set
+ * @param allowList the allowList to set
*/
public void setAllowList(Set allowList) {
- this.allowList = allowList.stream().map(String::trim).collect(Collectors.toSet());
+ assertNotReadonly();
+ this.allowList = allowList.stream().map(String::trim).collect(HashSet::new, HashSet::add, HashSet::addAll);
}
/**
@@ -169,11 +176,8 @@ public class PrivilegeRep implements Serializable {
*/
@Override
public String toString() {
- return "PrivilegeRep [name=" + this.name + ", policy=" + this.policy + ", allAllowed=" + this.allAllowed
- + ", denyList=" + (this.denyList == null ? "null" : this.denyList.size()) + ", allowList=" + (
- this.allowList == null ?
- "null" :
- this.allowList.size()) + "]";
+ return "PrivilegeRep [name=" + this.name + ", policy=" + this.policy + ", allAllowed=" + this.allAllowed +
+ ", denyList=" + this.denyList.size() + ", allowList=" + this.allowList.size() + "]";
}
@Override
@@ -193,10 +197,13 @@ public class PrivilegeRep implements Serializable {
if (getClass() != obj.getClass())
return false;
PrivilegeRep other = (PrivilegeRep) obj;
- if (this.name == null) {
+ if (this.name == null)
return other.name == null;
- } else
- return this.name.equals(other.name);
+ return this.name.equals(other.name);
+ }
+
+ public PrivilegeRep getCopy() {
+ return new PrivilegeRep(this.name, this.policy, this.allAllowed, this.denyList, this.allowList);
}
public T accept(PrivilegeElementVisitor visitor) {
diff --git a/privilege/src/main/java/li/strolch/privilege/model/Restrictable.java b/privilege/src/main/java/li/strolch/privilege/model/Restrictable.java
index 374737002..fa24569fa 100644
--- a/privilege/src/main/java/li/strolch/privilege/model/Restrictable.java
+++ b/privilege/src/main/java/li/strolch/privilege/model/Restrictable.java
@@ -21,7 +21,7 @@ import li.strolch.privilege.policy.PrivilegePolicy;
*
* Objects implementing this interface are used to grant/restrict privileges to them. A {@link PrivilegePolicy}
* implements the logic on granting/restricting privileges for a {@link Restrictable} and the {@link
- * #getPrivilegeName()} is used to find the {@link IPrivilege} which has the associated {@link PrivilegePolicy} for
+ * #getPrivilegeName()} is used to find the {@link Privilege} which has the associated {@link PrivilegePolicy} for
* evaluating access
*
*
@@ -30,9 +30,9 @@ import li.strolch.privilege.policy.PrivilegePolicy;
public interface Restrictable {
/**
- * Returns the name of the {@link IPrivilege} which is to be used to validate privileges against
+ * Returns the name of the {@link Privilege} which is to be used to validate privileges against
*
- * @return the name of the {@link IPrivilege} which is to be used to validate privileges against
+ * @return the name of the {@link Privilege} which is to be used to validate privileges against
*/
String getPrivilegeName();
diff --git a/privilege/src/main/java/li/strolch/privilege/model/RoleRep.java b/privilege/src/main/java/li/strolch/privilege/model/RoleRep.java
index 6ccf045a0..d43d2bfe5 100644
--- a/privilege/src/main/java/li/strolch/privilege/model/RoleRep.java
+++ b/privilege/src/main/java/li/strolch/privilege/model/RoleRep.java
@@ -15,16 +15,16 @@
*/
package li.strolch.privilege.model;
-import static li.strolch.utils.helper.StringHelper.trimOrEmpty;
-
-import java.io.Serializable;
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.List;
-
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.model.internal.Role;
-import li.strolch.utils.helper.StringHelper;
+import li.strolch.utils.dbc.DBC;
+
+import java.text.MessageFormat;
+import java.util.HashMap;
+import java.util.Map;
+
+import static li.strolch.utils.helper.StringHelper.isEmpty;
+import static li.strolch.utils.helper.StringHelper.trimOrEmpty;
/**
* To keep certain details of the {@link Role} itself hidden from remote clients and make sure instances are only edited
@@ -33,40 +33,55 @@ import li.strolch.utils.helper.StringHelper;
*
* @author Robert von Burg
*/
-public class RoleRep implements Serializable {
+public class RoleRep {
private String name;
- private List privileges;
+ private Map privileges;
+
+ private boolean readOnly;
/**
* Default constructor
*
- * @param name
- * the name of this role
- * @param privileges
- * the list of privileges granted to this role
+ * @param name the name of this role
+ * @param privileges the list of privileges granted to this role
*/
- public RoleRep(String name, List privileges) {
+ public RoleRep(String name, Map privileges) {
this.name = trimOrEmpty(name);
- this.privileges = privileges;
+ setPrivileges(privileges == null ? Map.of() : privileges);
+ }
+
+ public boolean isReadOnly() {
+ return readOnly;
+ }
+
+ public RoleRep readOnly() {
+ if (this.readOnly)
+ return this;
+ this.readOnly = true;
+ this.privileges = Map.copyOf(this.privileges);
+ return this;
+ }
+
+ protected void assertNotReadonly() {
+ if (this.readOnly)
+ throw new IllegalStateException("Role is currently readOnly, to modify get a copy!");
}
/**
* validates that all required fields are set
*/
public void validate() {
- if (StringHelper.isEmpty(this.name))
+ if (isEmpty(this.name))
throw new PrivilegeException("name is null");
- if (this.privileges != null && !this.privileges.isEmpty()) {
- for (PrivilegeRep privilege : this.privileges) {
- try {
- privilege.validate();
- } catch (Exception e) {
- String msg = "Privilege {0} is invalid on role {1}";
- msg = MessageFormat.format(msg, privilege.getName(), this.name);
- throw new PrivilegeException(msg, e);
- }
+ for (PrivilegeRep privilege : this.privileges.values()) {
+ try {
+ privilege.validate();
+ } catch (Exception e) {
+ String msg = "Privilege {0} is invalid on role {1}";
+ msg = MessageFormat.format(msg, privilege.getName(), this.name);
+ throw new PrivilegeException(msg, e);
}
}
}
@@ -79,30 +94,29 @@ public class RoleRep implements Serializable {
}
/**
- * @param name
- * the name to set
+ * @param name the name to set
*/
public void setName(String name) {
+ assertNotReadonly();
this.name = trimOrEmpty(name);
}
- /**
- * Returns the privileges assigned to this Role as a list
- *
- * @return the privileges assigned to this Role as a list
- */
- public List getPrivileges() {
- return this.privileges == null ? new ArrayList<>() : this.privileges;
+ public Map getPrivileges() {
+ if (this.privileges == null)
+ return null;
+ return this.privileges;
}
- /**
- * Sets the privileges on this from a list
- *
- * @param privileges
- * the list of privileges to assign to this role
- */
- public void setPrivileges(List privileges) {
- this.privileges = privileges;
+ public void setPrivileges(Map privileges) {
+ assertNotReadonly();
+ DBC.PRE.assertNotNull("privileges must not be null!", privileges);
+ this.privileges = new HashMap<>(privileges);
+ }
+
+ public void addPrivilege(PrivilegeRep privilegeRep) {
+ DBC.PRE.assertFalse(() -> "Privilege " + privilegeRep.getName() + " already on role " + this.name,
+ privileges.containsKey(privilegeRep.getName()));
+ this.privileges.put(privilegeRep.getName(), privilegeRep);
}
/**
@@ -112,8 +126,7 @@ public class RoleRep implements Serializable {
*/
@Override
public String toString() {
- return "RoleRep [name=" + this.name + ", privilegeMap=" + (this.privileges == null ? "null" : this.privileges)
- + "]";
+ return "RoleRep [name=" + this.name + ", privilegeMap=" + this.privileges + "]";
}
@Override
@@ -133,10 +146,13 @@ public class RoleRep implements Serializable {
if (getClass() != obj.getClass())
return false;
RoleRep other = (RoleRep) obj;
- if (this.name == null) {
+ if (this.name == null)
return other.name == null;
- } else
- return this.name.equals(other.name);
+ return this.name.equals(other.name);
+ }
+
+ public RoleRep getCopy() {
+ return new RoleRep(this.name, this.privileges);
}
public T accept(PrivilegeElementVisitor visitor) {
diff --git a/privilege/src/main/java/li/strolch/privilege/model/SimpleRestrictable.java b/privilege/src/main/java/li/strolch/privilege/model/SimpleRestrictable.java
index cbaff2928..86a4546c6 100644
--- a/privilege/src/main/java/li/strolch/privilege/model/SimpleRestrictable.java
+++ b/privilege/src/main/java/li/strolch/privilege/model/SimpleRestrictable.java
@@ -26,10 +26,8 @@ public class SimpleRestrictable implements Restrictable {
private final Object value;
/**
- * @param name
- * the name of the privilege
- * @param value
- * the value allowed on the privilege
+ * @param name the name of the privilege
+ * @param value the value allowed on the privilege
*/
public SimpleRestrictable(String name, Object value) {
DBC.PRE.assertNotEmpty("name must not be empty", name);
diff --git a/privilege/src/main/java/li/strolch/privilege/model/UserRep.java b/privilege/src/main/java/li/strolch/privilege/model/UserRep.java
index 19b0f9da7..8a82e9fbf 100644
--- a/privilege/src/main/java/li/strolch/privilege/model/UserRep.java
+++ b/privilege/src/main/java/li/strolch/privilege/model/UserRep.java
@@ -15,20 +15,19 @@
*/
package li.strolch.privilege.model;
-import static li.strolch.privilege.base.PrivilegeConstants.*;
-import static li.strolch.utils.helper.StringHelper.trimOrEmpty;
-
-import java.io.Serializable;
-import java.text.MessageFormat;
-import java.util.*;
-import java.util.stream.Collectors;
-
import li.strolch.privilege.base.PrivilegeConstants;
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.model.internal.Role;
import li.strolch.privilege.model.internal.User;
import li.strolch.privilege.model.internal.UserHistory;
-import li.strolch.utils.helper.StringHelper;
+import li.strolch.utils.dbc.DBC;
+
+import java.text.MessageFormat;
+import java.util.*;
+
+import static li.strolch.privilege.base.PrivilegeConstants.*;
+import static li.strolch.utils.helper.StringHelper.isEmpty;
+import static li.strolch.utils.helper.StringHelper.trimOrEmpty;
/**
* To keep certain details of the {@link User} itself hidden from remote clients and make sure instances are only edited
@@ -37,7 +36,7 @@ import li.strolch.utils.helper.StringHelper;
*
* @author Robert von Burg
*/
-public class UserRep implements Serializable {
+public class UserRep {
private String userId;
private String username;
@@ -45,47 +44,40 @@ public class UserRep implements Serializable {
private String lastname;
private UserState userState;
private Locale locale;
+ private Set groups;
private Set roles;
private Map properties;
private UserHistory history;
+ private boolean readOnly;
+
/**
* Default constructor
*
- * @param userId
- * the user's id
- * @param username
- * the user's login name
- * @param firstname
- * the user's first name
- * @param lastname
- * the user's last name
- * @param userState
- * the user's {@link UserState}
- * @param roles
- * the set of {@link Role}s assigned to this user
- * @param locale
- * the user's {@link Locale}
- * @param propertyMap
- * a {@link Map} containing string value pairs of properties for this user
+ * @param userId the user's id
+ * @param username the user's login name
+ * @param firstname the user's first name
+ * @param lastname the user's last name
+ * @param userState the user's {@link UserState}
+ * @param groups the set of {@link li.strolch.privilege.model.internal.Group}s assigned to this user
+ * @param roles the set of {@link Role}s assigned to this user
+ * @param locale the user's {@link Locale}
+ * @param propertyMap a {@link Map} containing string value pairs of properties for this user
*/
public UserRep(String userId, String username, String firstname, String lastname, UserState userState,
- Set roles, Locale locale, Map propertyMap, UserHistory history) {
+ Set groups, Set roles, Locale locale, Map propertyMap,
+ UserHistory history) {
this.userId = trimOrEmpty(userId);
this.username = trimOrEmpty(username);
this.firstname = trimOrEmpty(firstname);
this.lastname = trimOrEmpty(lastname);
this.userState = userState;
- this.roles = roles == null ? null : roles.stream().map(String::trim).collect(Collectors.toSet());
this.locale = locale;
-
- if (propertyMap != null) {
- this.properties = new HashMap<>();
- propertyMap.forEach((key, value) -> this.properties.put(key.trim(), value.trim()));
- }
-
- this.history = history;
+ setGroups(groups == null ? Set.of() : groups);
+ setRoles(roles == null ? Set.of() : roles);
+ setProperties(properties == null ? Map.of() : properties);
+ this.history = history == null ? UserHistory.EMPTY : history;
}
@SuppressWarnings("unused")
@@ -97,30 +89,53 @@ public class UserRep implements Serializable {
* Validates that all required fields are set
*/
public void validate() {
+ if (isEmpty(this.userId))
+ throw new PrivilegeException("userId must not be empty");
+ if (isEmpty(this.username))
+ throw new PrivilegeException("username must not be empty");
- if (StringHelper.isEmpty(this.userId))
- throw new PrivilegeException("userId is null or empty");
-
- if (StringHelper.isEmpty(this.username))
- throw new PrivilegeException("username is null or empty");
-
- // username must be at least 2 characters in length
- if (this.username.length() < 2) {
- String msg = MessageFormat.format("The given username ''{0}'' is shorter than 2 characters", this.username);
+ // username must be at least 3 characters in length
+ if (this.username.length() < 3) {
+ String msg = MessageFormat.format("The given username ''{0}'' is shorter than 3 characters", this.username);
throw new PrivilegeException(msg);
}
if (this.userState == null)
- throw new PrivilegeException("userState is null");
+ throw new PrivilegeException("userState may not be null");
- if (StringHelper.isEmpty(this.firstname))
- throw new PrivilegeException("firstname is null or empty");
+ if (this.userState != UserState.SYSTEM) {
+ if (isEmpty(this.firstname))
+ throw new PrivilegeException("firstname may not be empty for non-system users");
+ if (isEmpty(this.lastname))
+ throw new PrivilegeException("lastname may not be empty for non-system users");
+ }
- if (StringHelper.isEmpty(this.lastname))
- throw new PrivilegeException("lastname is null or empty");
+ if (this.groups == null)
+ throw new PrivilegeException("groups may not be null");
+ if (this.roles == null)
+ throw new PrivilegeException("roles may not be null");
- if (this.roles == null || this.roles.isEmpty())
- throw new PrivilegeException("roles is null or empty");
+ if (this.groups.isEmpty() && this.roles.isEmpty())
+ throw new PrivilegeException("User must have at least one group or role assigned!");
+ }
+
+ public boolean isReadOnly() {
+ return readOnly;
+ }
+
+ public UserRep readOnly() {
+ if (this.readOnly)
+ return this;
+ this.readOnly = true;
+ this.groups = Set.copyOf(this.groups);
+ this.roles = Set.copyOf(this.roles);
+ this.properties = Map.copyOf(this.properties);
+ return this;
+ }
+
+ protected void assertNotReadonly() {
+ if (this.readOnly)
+ throw new IllegalStateException("User is currently readOnly, to modify get a copy!");
}
public boolean isSystemUser() {
@@ -145,10 +160,10 @@ public class UserRep implements Serializable {
/**
* Set the userId
*
- * @param userId
- * to set
+ * @param userId to set
*/
public void setUserId(String userId) {
+ assertNotReadonly();
this.userId = trimOrEmpty(userId);
}
@@ -160,10 +175,10 @@ public class UserRep implements Serializable {
}
/**
- * @param username
- * the username to set
+ * @param username the username to set
*/
public void setUsername(String username) {
+ assertNotReadonly();
this.username = trimOrEmpty(username);
}
@@ -175,10 +190,10 @@ public class UserRep implements Serializable {
}
/**
- * @param firstname
- * the firstname to set
+ * @param firstname the firstname to set
*/
public void setFirstname(String firstname) {
+ assertNotReadonly();
this.firstname = trimOrEmpty(firstname);
}
@@ -190,10 +205,10 @@ public class UserRep implements Serializable {
}
/**
- * @param lastname
- * the lastname to set
+ * @param lastname the lastname to set
*/
public void setLastname(String lastname) {
+ assertNotReadonly();
this.lastname = trimOrEmpty(lastname);
}
@@ -205,13 +220,27 @@ public class UserRep implements Serializable {
}
/**
- * @param userState
- * the userState to set
+ * @param userState the userState to set
*/
public void setUserState(UserState userState) {
+ assertNotReadonly();
this.userState = userState;
}
+ public Set getGroups() {
+ return this.groups;
+ }
+
+ public void setGroups(Set groups) {
+ DBC.PRE.assertNotNull("groups must not be null!", groups);
+ assertNotReadonly();
+ this.groups = groups.stream().map(String::trim).collect(HashSet::new, HashSet::add, HashSet::addAll);
+ }
+
+ public boolean hasGroup(String group) {
+ return this.groups.contains(group);
+ }
+
/**
* @return the roles
*/
@@ -220,21 +249,19 @@ public class UserRep implements Serializable {
}
/**
- * @param roles
- * the roles to set
+ * @param roles the roles to set
*/
public void setRoles(Set roles) {
- this.roles = roles.stream().map(String::trim).collect(Collectors.toSet());
+ DBC.PRE.assertNotNull("roles must not be null!", roles);
+ assertNotReadonly();
+ this.roles = roles.stream().map(String::trim).collect(HashSet::new, HashSet::add, HashSet::addAll);
+ }
+
+ public void addRole(String role) {
+ assertNotReadonly();
+ this.roles.add(role);
}
- /**
- * Returns true if this user has the given role
- *
- * @param role
- * the role to check for
- *
- * @return returns true if this user has the given role
- */
public boolean hasRole(String role) {
return this.roles.contains(role);
}
@@ -247,10 +274,10 @@ public class UserRep implements Serializable {
}
/**
- * @param locale
- * the locale to set
+ * @param locale the locale to set
*/
public void setLocale(Locale locale) {
+ assertNotReadonly();
this.locale = locale;
}
@@ -260,18 +287,15 @@ public class UserRep implements Serializable {
* @return the user history
*/
public UserHistory getHistory() {
- if (this.history == null)
- return new UserHistory();
return this.history;
}
/**
- * Returns true if the the given property exists
+ * Returns true if the given property exists
*
- * @param key
- * the property key to check
+ * @param key the property key to check
*
- * @return true if the the given property exists
+ * @return true if the given property exists
*/
public boolean hasProperty(String key) {
return this.properties.containsKey(key);
@@ -280,40 +304,41 @@ public class UserRep implements Serializable {
/**
* Returns the property with the given key
*
- * @param key
- * the key for which the property is to be returned
+ * @param key the key for which the property is to be returned
*
* @return the property with the given key, or null if the property is not defined
*/
public String getProperty(String key) {
- if (this.properties == null)
- return null;
return this.properties.get(key);
}
/**
* Set the property with the key to the value
*
- * @param key
- * the key of the property to set
- * @param value
- * the value of the property to set
+ * @param key the key of the property to set
+ * @param value the value of the property to set
*/
public void setProperty(String key, String value) {
- if (this.properties == null)
- this.properties = new HashMap<>(1);
+ DBC.PRE.assertNotEmpty("key must not be empty!", key);
+ DBC.PRE.assertNotEmpty("value must not be empty!", value);
+ assertNotReadonly();
this.properties.put(key.trim(), value.trim());
}
+ public void setProperties(Map properties) {
+ DBC.PRE.assertNotNull("properties must not be null!", properties);
+ assertNotReadonly();
+ this.properties = new HashMap<>();
+ properties.forEach((key, value) -> this.properties.put(key.trim(), value.trim()));
+ }
+
/**
* Returns the {@link Set} of keys of all properties
*
* @return the {@link Set} of keys of all properties
*/
public Set getPropertyKeySet() {
- if (this.properties == null)
- return new HashSet<>();
- return new HashSet<>(this.properties.keySet());
+ return this.properties.keySet();
}
/**
@@ -322,9 +347,7 @@ public class UserRep implements Serializable {
* @return the map of properties
*/
public Map getProperties() {
- if (this.properties == null)
- return new HashMap<>();
- return new HashMap<>(this.properties);
+ return this.properties;
}
/**
@@ -361,9 +384,9 @@ public class UserRep implements Serializable {
*/
@Override
public String toString() {
- return "UserRep [userId=" + this.userId + ", username=" + this.username + ", firstname=" + this.firstname
- + ", lastname=" + this.lastname + ", userState=" + this.userState + ", locale=" + this.locale
- + ", roles=" + this.roles + "]";
+ return "UserRep [userId=" + this.userId + ", username=" + this.username + ", firstname=" + this.firstname +
+ ", lastname=" + this.lastname + ", userState=" + this.userState + ", locale=" + this.locale +
+ ", roles=" + this.roles + "]";
}
@Override
@@ -390,12 +413,8 @@ public class UserRep implements Serializable {
}
public UserRep getCopy() {
-
- Set roles = new HashSet<>(this.roles);
- Map propertyMap = this.properties == null ? null : new HashMap<>(this.properties);
-
- return new UserRep(this.userId, this.username, this.firstname, this.lastname, this.userState, roles,
- this.locale, propertyMap, this.history == null ? new UserHistory() : this.history.getClone());
+ return new UserRep(this.userId, this.username, this.firstname, this.lastname, this.userState, this.groups,
+ this.roles, this.locale, this.properties, this.history);
}
public T accept(PrivilegeElementVisitor visitor) {
diff --git a/privilege/src/main/java/li/strolch/privilege/model/internal/Group.java b/privilege/src/main/java/li/strolch/privilege/model/internal/Group.java
new file mode 100644
index 000000000..8c2c069de
--- /dev/null
+++ b/privilege/src/main/java/li/strolch/privilege/model/internal/Group.java
@@ -0,0 +1,92 @@
+package li.strolch.privilege.model.internal;
+
+import li.strolch.privilege.base.PrivilegeConstants;
+import li.strolch.utils.dbc.DBC;
+
+import java.util.Map;
+import java.util.Set;
+
+import static li.strolch.privilege.base.PrivilegeConstants.*;
+
+/**
+ * This entity represents a group with which {@link User Users} can be associated. This allows to put roles and
+ * properties which are always duplicated on users on to the group, and the User is then in the group, eliminating
+ * duplication.
+ */
+public record Group(String name, Set roles, Map propertyMap) {
+ public Group(String name, Set roles, Map propertyMap) {
+ DBC.PRE.assertNotEmpty("name must not be empty", name);
+ DBC.PRE.assertNotNull("roles must not be null", roles);
+ DBC.PRE.assertNotNull("propertyMap must not be null", propertyMap);
+ this.name = name;
+ this.roles = Set.copyOf(roles);
+ this.propertyMap = Map.copyOf(propertyMap);
+ }
+
+ /**
+ * Returns true if this group has the specified role
+ *
+ * @param role the name of the {@link Role} to check for
+ *
+ * @return true if this group has the specified role
+ */
+ public boolean hasRole(String role) {
+ return this.roles.contains(role);
+ }
+
+ /**
+ * Returns the property with the given key
+ *
+ * @param key the key for which the property is to be returned
+ *
+ * @return the property with the given key, or null if the property is not defined
+ */
+ public String getProperty(String key) {
+ return this.propertyMap.get(key);
+ }
+
+ /**
+ * Returns the {@link Set} of keys of all properties
+ *
+ * @return the {@link Set} of keys of all properties
+ */
+ public Set getPropertyKeySet() {
+ return this.propertyMap.keySet();
+ }
+
+ /**
+ * Returns the map of properties
+ *
+ * @return the map of properties
+ */
+ public Map getProperties() {
+ return this.propertyMap;
+ }
+
+ /**
+ * Returns the value of the property {@link PrivilegeConstants#REALM}
+ *
+ * @return the value of the property {@link PrivilegeConstants#REALM}
+ */
+ public String getRealm() {
+ return getProperty(REALM);
+ }
+
+ /**
+ * Returns the value of the property {@link PrivilegeConstants#ORGANISATION}
+ *
+ * @return the value of the property {@link PrivilegeConstants#ORGANISATION}
+ */
+ public String getOrganisation() {
+ return getProperty(ORGANISATION);
+ }
+
+ /**
+ * Returns the value of the property {@link PrivilegeConstants#LOCATION}
+ *
+ * @return the value of the property {@link PrivilegeConstants#LOCATION}
+ */
+ public String getLocation() {
+ return getProperty(LOCATION);
+ }
+}
diff --git a/privilege/src/main/java/li/strolch/privilege/model/internal/PasswordCrypt.java b/privilege/src/main/java/li/strolch/privilege/model/internal/PasswordCrypt.java
index e0ba31350..fc749f9ec 100644
--- a/privilege/src/main/java/li/strolch/privilege/model/internal/PasswordCrypt.java
+++ b/privilege/src/main/java/li/strolch/privilege/model/internal/PasswordCrypt.java
@@ -2,48 +2,33 @@ package li.strolch.privilege.model.internal;
import static li.strolch.utils.helper.StringHelper.*;
-public class PasswordCrypt {
+public record PasswordCrypt(byte[] password, byte[] salt, String hashAlgorithm, int hashIterations, int hashKeyLength) {
- private final byte[] password;
- private final byte[] salt;
- private final String hashAlgorithm;
- private final int hashIterations;
- private final int hashKeyLength;
-
- public PasswordCrypt(byte[] password, byte[] salt) {
- this.password = password;
- this.salt = salt;
- this.hashAlgorithm = null;
- this.hashIterations = -1;
- this.hashKeyLength = -1;
+ @Override
+ public String toString() {
+ return buildPasswordString();
}
- public PasswordCrypt(byte[] password, byte[] salt, String hashAlgorithm, int hashIterations, int hashKeyLength) {
- this.password = password;
- this.salt = salt;
- this.hashAlgorithm = hashAlgorithm;
- this.hashIterations = hashIterations;
- this.hashKeyLength = hashKeyLength;
+ public String buildPasswordString() {
+ if (this.password == null || this.salt == null || this.hashAlgorithm == null || this.hashIterations == -1 ||
+ this.hashKeyLength == -1) {
+ return null;
+ }
+
+ return buildPasswordString(this.hashAlgorithm, this.hashIterations, this.hashKeyLength, this.salt,
+ this.password);
}
- public byte[] getPassword() {
- return password;
+ public static String buildPasswordString(String hashAlgorithm, int hashIterations, int hashKeyLength, byte[] salt,
+ byte[] passwordArr) {
+ String algo = hashAlgorithm + "," + hashIterations + "," + hashKeyLength;
+ String hash = toHexString(salt);
+ String password = toHexString(passwordArr);
+ return "$" + algo + "$" + hash + "$" + password;
}
- public byte[] getSalt() {
- return salt;
- }
-
- public String getHashAlgorithm() {
- return hashAlgorithm;
- }
-
- public int getHashIterations() {
- return hashIterations;
- }
-
- public int getHashKeyLength() {
- return hashKeyLength;
+ public static PasswordCrypt of(byte[] password, byte[] salt) {
+ return new PasswordCrypt(password, salt, null, -1, -1);
}
public static PasswordCrypt parse(String passwordS, String saltS) {
@@ -55,14 +40,14 @@ public class PasswordCrypt {
salt = fromHexString(saltS.trim());
if (isEmpty(passwordS))
- return new PasswordCrypt(null, salt);
+ return PasswordCrypt.of(null, salt);
passwordS = passwordS.trim();
byte[] password;
if (!passwordS.startsWith("$")) {
password = fromHexString(passwordS);
- return new PasswordCrypt(password, salt);
+ return PasswordCrypt.of(password, salt);
}
String[] parts = passwordS.split("\\$");
@@ -86,28 +71,4 @@ public class PasswordCrypt {
return new PasswordCrypt(password, salt, hashAlgorithm, hashIterations, hashKeyLength);
}
-
- @Override
- public String toString() {
- return buildPasswordString();
- }
-
- public String buildPasswordString() {
- if (this.password == null || this.salt == null || this.hashAlgorithm == null || this.hashIterations == -1 ||
- this.hashKeyLength == -1) {
- return null;
- }
-
- return buildPasswordString(getHashAlgorithm(), getHashIterations(), getHashKeyLength(), getSalt(),
- getPassword());
-
- }
-
- public static String buildPasswordString(String hashAlgorithm, int hashIterations, int hashKeyLength, byte[] salt,
- byte[] passwordArr) {
- String algo = hashAlgorithm + "," + hashIterations + "," + hashKeyLength;
- String hash = toHexString(salt);
- String password = toHexString(passwordArr);
- return "$" + algo + "$" + hash + "$" + password;
- }
}
diff --git a/privilege/src/main/java/li/strolch/privilege/model/internal/PrivilegeImpl.java b/privilege/src/main/java/li/strolch/privilege/model/internal/PrivilegeImpl.java
deleted file mode 100644
index 076a07581..000000000
--- a/privilege/src/main/java/li/strolch/privilege/model/internal/PrivilegeImpl.java
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * Copyright 2013 Robert von Burg
- *
- * 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.model.internal;
-
-import java.text.MessageFormat;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-import li.strolch.privilege.base.PrivilegeException;
-import li.strolch.privilege.handler.PrivilegeHandler;
-import li.strolch.privilege.model.IPrivilege;
-import li.strolch.privilege.model.PrivilegeRep;
-import li.strolch.privilege.model.Restrictable;
-import li.strolch.privilege.policy.PrivilegePolicy;
-import li.strolch.utils.helper.StringHelper;
-
-/**
- *
- * {@link IPrivilege} is the main model object for Privilege. A {@link Role} has a set of Privileges assigned to it
- * which defines the privileges a logged in user with that role has. If the {@link IPrivilege} has a {@link
- * PrivilegePolicy} defined, then that policy will be used for finer granularity and with the deny and allow lists
- * configured which is used to evaluate if privilege is granted to a {@link Restrictable}
- *
- *
- *
- * {@link IPrivilege}s have allow and deny rules which the configured {@link PrivilegeHandler} uses to
- *
- *
- *
- * Note: This is an internal object which is not to be serialized or passed to clients, {@link PrivilegeRep}s are used
- * for that
- *
- *
- * @author Robert von Burg
- */
-public final class PrivilegeImpl implements IPrivilege {
-
- private final String name;
- private final String policy;
- private final boolean allAllowed;
- private final Set denyList;
- private final Set allowList;
-
- /**
- * Default constructor
- *
- * @param name
- * the name of this privilege, which is unique to all privileges known in the {@link PrivilegeHandler}
- * @param policy
- * the {@link PrivilegePolicy} configured to evaluate if the privilege is granted. If null, then privilege is
- * granted
- * @param allAllowed
- * a boolean defining if a {@link Role} with this {@link PrivilegeImpl} has unrestricted access to a {@link
- * Restrictable} in which case the deny and allow lists are ignored and can be null
- * @param denyList
- * a list of deny rules for this {@link PrivilegeImpl}, can be null if all allowed
- * @param allowList
- * a list of allow rules for this {@link PrivilegeImpl}, can be null if all allowed
- */
- public PrivilegeImpl(String name, String policy, boolean allAllowed, Set denyList, Set allowList) {
-
- if (StringHelper.isEmpty(name)) {
- throw new PrivilegeException("No name defined!");
- }
- if (StringHelper.isEmpty(policy)) {
- throw new PrivilegeException(
- MessageFormat.format("Policy may not be empty for Privilege {0}!", name));
- }
- if (denyList == null) {
- throw new PrivilegeException(
- MessageFormat.format("denyList is null for Privilege {0}!", name));
- }
- if (allowList == null) {
- throw new PrivilegeException(
- MessageFormat.format("allowList is null for Privilege {0}!", name));
- }
-
- this.name = name;
- this.allAllowed = allAllowed;
- this.policy = policy;
- this.denyList = Collections.unmodifiableSet(denyList);
- this.allowList = Collections.unmodifiableSet(allowList);
- }
-
- /**
- * Constructs a {@link PrivilegeImpl} from the {@link PrivilegeRep}
- *
- * @param privilegeRep
- * the {@link PrivilegeRep} from which to create the {@link PrivilegeImpl}
- */
- public PrivilegeImpl(PrivilegeRep privilegeRep) {
- this(privilegeRep.getName(), privilegeRep.getPolicy(), privilegeRep.isAllAllowed(), privilegeRep.getDenyList(),
- privilegeRep.getAllowList());
- }
-
- /**
- * @return a {@link PrivilegeRep} which is a representation of this object used to serialize and view on clients
- */
- @Override
- public PrivilegeRep asPrivilegeRep() {
- return new PrivilegeRep(this.name, this.policy, this.allAllowed, new HashSet<>(this.denyList),
- new HashSet<>(this.allowList));
- }
-
- /**
- * @return the name
- */
- @Override
- public String getName() {
- return this.name;
- }
-
- /**
- * @return the policy
- */
- @Override
- public String getPolicy() {
- return this.policy;
- }
-
- /**
- * @return the allAllowed
- */
- @Override
- public boolean isAllAllowed() {
- return this.allAllowed;
- }
-
- /**
- * @return the allowList
- */
- @Override
- public Set getAllowList() {
- return this.allowList;
- }
-
- /**
- * @return the denyList
- */
- @Override
- public Set getDenyList() {
- return this.denyList;
- }
-
- /**
- * @return true if there are values in the allow list
- */
- @Override
- public boolean hasAllowed() {
- return !this.allowList.isEmpty();
- }
-
- /**
- * @return if the value is in the allow list
- */
- @Override
- public boolean isAllowed(String value) {
- return this.allowList.contains(value);
- }
-
- /**
- * @return true if there are values in the deny list
- */
- @Override
- public boolean hasDenied() {
- return !this.allowList.isEmpty();
- }
-
- /**
- * @return true if the value is in the deny list
- */
- @Override
- public boolean isDenied(String value) {
- return this.denyList.contains(value);
- }
-
- /**
- * Returns a string representation of this object displaying its concrete type and its values
- *
- * @see java.lang.Object#toString()
- */
- @Override
- public String toString() {
- return "Privilege [name=" + this.name + ", policy=" + this.policy + "]";
- }
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((this.name == null) ? 0 : this.name.hashCode());
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- PrivilegeImpl other = (PrivilegeImpl) obj;
- if (this.name == null) {
- return other.name == null;
- } else
- return this.name.equals(other.name);
- }
-}
diff --git a/privilege/src/main/java/li/strolch/privilege/model/internal/Role.java b/privilege/src/main/java/li/strolch/privilege/model/internal/Role.java
index 0b48a20d3..2ac464ef1 100644
--- a/privilege/src/main/java/li/strolch/privilege/model/internal/Role.java
+++ b/privilege/src/main/java/li/strolch/privilege/model/internal/Role.java
@@ -15,14 +15,17 @@
*/
package li.strolch.privilege.model.internal;
-import java.util.*;
-import java.util.Map.Entry;
-
import li.strolch.privilege.base.PrivilegeException;
-import li.strolch.privilege.model.IPrivilege;
+import li.strolch.privilege.model.Privilege;
import li.strolch.privilege.model.PrivilegeRep;
import li.strolch.privilege.model.RoleRep;
-import li.strolch.utils.helper.StringHelper;
+import li.strolch.utils.dbc.DBC;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import static li.strolch.utils.helper.StringHelper.isEmpty;
/**
*
@@ -37,57 +40,32 @@ import li.strolch.utils.helper.StringHelper;
*
* @author Robert von Burg
*/
-public final class Role {
-
- private final String name;
- private final Map privilegeMap;
-
- /**
- * Default constructor
- *
- * @param name
- * the name of the role
- * @param privilegeMap
- * a map of {@link IPrivilege}s granted to this role
- */
- public Role(String name, Map privilegeMap) {
-
- if (StringHelper.isEmpty(name)) {
- throw new PrivilegeException("No name defined!");
- }
- if (privilegeMap == null) {
- throw new PrivilegeException("No privileges defined!");
- }
+public record Role(String name, Map privilegeMap) {
+ public Role(String name, Map privilegeMap) {
+ DBC.PRE.assertNotEmpty("name must not be empty", name);
+ DBC.PRE.assertNotNull("privilegeMap must not be null", privilegeMap);
this.name = name;
- this.privilegeMap = Collections.unmodifiableMap(privilegeMap);
+ this.privilegeMap = Map.copyOf(privilegeMap);
}
/**
* Construct {@link Role} from its representation {@link RoleRep}
*
- * @param roleRep
- * the representation from which to create the {@link Role}
+ * @param roleRep the representation from which to create the {@link Role}
*/
- public Role(RoleRep roleRep) {
-
+ public static Role of(RoleRep roleRep) {
String name = roleRep.getName();
- if (StringHelper.isEmpty(name)) {
+ if (isEmpty(name))
throw new PrivilegeException("No name defined!");
- }
-
- if (roleRep.getPrivileges() == null) {
+ if (roleRep.getPrivileges() == null)
throw new PrivilegeException("Privileges may not be null!");
- }
// build privileges from rep
- Map privilegeMap = new HashMap<>(roleRep.getPrivileges().size());
- for (PrivilegeRep privilege : roleRep.getPrivileges()) {
- privilegeMap.put(privilege.getName(), new PrivilegeImpl(privilege));
- }
+ Map privilegeMap = new HashMap<>(roleRep.getPrivileges().size());
+ roleRep.getPrivileges().values().forEach(p -> privilegeMap.put(p.getName(), Privilege.of(p)));
- this.name = name;
- this.privilegeMap = Collections.unmodifiableMap(privilegeMap);
+ return new Role(name, privilegeMap);
}
/**
@@ -98,30 +76,29 @@ public final class Role {
}
/**
- * Returns the {@link Set} of names for the currently stored {@link IPrivilege Privileges}
+ * Returns the {@link Set} of names for the currently stored {@link Privilege Privileges}
*
- * @return the {@link Set} of names for the currently stored {@link IPrivilege Privileges}
+ * @return the {@link Set} of names for the currently stored {@link Privilege Privileges}
*/
public Set getPrivilegeNames() {
return this.privilegeMap.keySet();
}
/**
- * Returns the {@link IPrivilege} for the given name, null if it does not exist
+ * Returns the {@link Privilege} for the given name, null if it does not exist
*
- * @return the {@link IPrivilege} for the given name, null if it does not exist
+ * @return the {@link Privilege} for the given name, null if it does not exist
*/
- public IPrivilege getPrivilege(String name) {
+ public Privilege getPrivilege(String name) {
return this.privilegeMap.get(name);
}
/**
- * Determines if this {@link Role} has the {@link IPrivilege} with the given name
+ * Determines if this {@link Role} has the {@link Privilege} with the given name
*
- * @param name
- * the name of the {@link IPrivilege}
+ * @param name the name of the {@link Privilege}
*
- * @return true if this {@link Role} has the {@link IPrivilege} with the given name
+ * @return true if this {@link Role} has the {@link Privilege} with the given name
*/
public boolean hasPrivilege(String name) {
return this.privilegeMap.containsKey(name);
@@ -131,10 +108,8 @@ public final class Role {
* @return a {@link RoleRep} which is a representation of this object used to serialize and view on clients
*/
public RoleRep asRoleRep() {
- List privileges = new ArrayList<>();
- for (Entry entry : this.privilegeMap.entrySet()) {
- privileges.add(entry.getValue().asPrivilegeRep());
- }
+ Map privileges = new HashMap<>();
+ this.privilegeMap.values().forEach(p -> privileges.put(p.getName(), p.asPrivilegeRep()));
return new RoleRep(this.name, privileges);
}
diff --git a/privilege/src/main/java/li/strolch/privilege/model/internal/User.java b/privilege/src/main/java/li/strolch/privilege/model/internal/User.java
index 72c3b327f..ef4cdd7a5 100644
--- a/privilege/src/main/java/li/strolch/privilege/model/internal/User.java
+++ b/privilege/src/main/java/li/strolch/privilege/model/internal/User.java
@@ -16,12 +16,14 @@
package li.strolch.privilege.model.internal;
import li.strolch.privilege.base.PrivilegeConstants;
-import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.model.UserRep;
import li.strolch.privilege.model.UserState;
-import li.strolch.utils.helper.StringHelper;
+import li.strolch.utils.dbc.DBC;
-import java.util.*;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
import static li.strolch.privilege.base.PrivilegeConstants.*;
@@ -34,59 +36,36 @@ import static li.strolch.privilege.base.PrivilegeConstants.*;
* that
*
*
+ * @param userId the user's id
+ * @param username the user's login name
+ * @param passwordCrypt the {@link PasswordCrypt} containing user's password information
+ * @param firstname the user's first name
+ * @param lastname the user's lastname
+ * @param userState the user's {@link UserState}
+ * @param groups the set of {@link Group}s assigned to this user
+ * @param roles the set of {@link Role}s assigned to this user
+ * @param locale the user's {@link Locale}
+ * @param propertyMap a {@link Map} containing string value pairs of properties for this user
+ *
* @author Robert von Burg
*/
-public final class User {
+public record User(String userId, String username, PasswordCrypt passwordCrypt, String firstname, String lastname,
+ UserState userState, Set groups, Set roles, Locale locale,
+ Map propertyMap, boolean passwordChangeRequested, UserHistory history) {
- private final String userId;
-
- private final String username;
- private final PasswordCrypt passwordCrypt;
-
- private final String firstname;
- private final String lastname;
-
- private final Set roles;
-
- private final UserState userState;
- private final Map propertyMap;
- private final Locale locale;
-
- private final boolean passwordChangeRequested;
- private final UserHistory history;
-
- /**
- * Default constructor
- *
- * @param userId the user's id
- * @param username the user's login name
- * @param passwordCrypt the {@link PasswordCrypt} containing user's password information
- * @param firstname the user's first name
- * @param lastname the user's lastname
- * @param userState the user's {@link UserState}
- * @param roles the set of {@link Role}s assigned to this user
- * @param locale the user's {@link Locale}
- * @param propertyMap a {@link Map} containing string value pairs of properties for this user
- */
public User(String userId, String username, PasswordCrypt passwordCrypt, String firstname, String lastname,
- UserState userState, Set roles, Locale locale, Map propertyMap,
+ UserState userState, Set groups, Set roles, Locale locale, Map propertyMap,
boolean passwordChangeRequested, UserHistory history) {
- if (StringHelper.isEmpty(userId))
- throw new PrivilegeException("No UserId defined!");
- if (userState == null)
- throw new PrivilegeException("No userState defined!");
- if (StringHelper.isEmpty(username))
- throw new PrivilegeException("No username defined!");
- if (userState != UserState.SYSTEM) {
- if (StringHelper.isEmpty(lastname))
- throw new PrivilegeException("No lastname defined!");
- if (StringHelper.isEmpty(firstname))
- throw new PrivilegeException("No firstname defined!");
- }
+ DBC.PRE.assertNotEmpty("userId must not be empty", userId);
+ DBC.PRE.assertNotEmpty("username must not be empty", username);
+ DBC.PRE.assertNotNull("userState must not be null", userState);
+ DBC.PRE.assertNotNull("history must not be null", history);
- if (history == null)
- throw new PrivilegeException("History must not be null!");
+ if (userState != UserState.SYSTEM) {
+ DBC.PRE.assertNotEmpty("lastname must not be empty when not system user!", username);
+ DBC.PRE.assertNotEmpty("firstname must not be empty when not system user!", firstname);
+ }
// passwordCrypt may be null, meaning not able to login
// roles may be null, meaning not able to login and must be added later
@@ -103,35 +82,19 @@ public final class User {
this.firstname = firstname;
this.lastname = lastname;
- if (roles == null)
- this.roles = Collections.emptySet();
- else
- this.roles = Set.copyOf(roles);
-
- if (locale == null)
- this.locale = Locale.getDefault();
- else
- this.locale = locale;
-
- if (propertyMap == null)
- this.propertyMap = Collections.emptyMap();
- else
- this.propertyMap = Map.copyOf(propertyMap);
+ this.groups = groups == null ? Set.of() : Set.copyOf(groups);
+ this.roles = roles == null ? Set.of() : Set.copyOf(roles);
+ this.locale = locale == null ? Locale.getDefault() : locale;
+ this.propertyMap = propertyMap == null ? Map.of() : Map.copyOf(propertyMap);
this.passwordChangeRequested = passwordChangeRequested;
this.history = history;
}
- /**
- * @return the userId
- */
public String getUserId() {
return this.userId;
}
- /**
- * @return the username
- */
public String getUsername() {
return this.username;
}
@@ -145,48 +108,34 @@ public final class User {
return this.passwordCrypt;
}
- /**
- * @return the first name
- */
public String getFirstname() {
return this.firstname;
}
- /**
- * @return the last name
- */
public String getLastname() {
return this.lastname;
}
- /**
- * @return the userState
- */
public UserState getUserState() {
return this.userState;
}
- /**
- * @return the roles
- */
+ public Set getGroups() {
+ return this.groups;
+ }
+
public Set getRoles() {
return this.roles;
}
- /**
- * Returns true if this user has the specified role
- *
- * @param role the name of the {@link Role} to check for
- *
- * @return true if the this user has the specified role
- */
+ public boolean hasGroup(String group) {
+ return this.groups.contains(group);
+ }
+
public boolean hasRole(String role) {
return this.roles.contains(role);
}
- /**
- * @return the locale
- */
public Locale getLocale() {
return this.locale;
}
@@ -195,11 +144,6 @@ public final class User {
return this.passwordChangeRequested;
}
- /**
- * Returns the History object
- *
- * @return the History object
- */
public UserHistory getHistory() {
return this.history;
}
@@ -282,8 +226,8 @@ public final class User {
* @return a {@link UserRep} which is a representation of this object used to serialize and view on clients
*/
public UserRep asUserRep() {
- return new UserRep(this.userId, this.username, this.firstname, this.lastname, this.userState,
- new HashSet<>(this.roles), this.locale, new HashMap<>(this.propertyMap), this.history.getClone());
+ return new UserRep(this.userId, this.username, this.firstname, this.lastname, this.userState, this.groups,
+ this.roles, this.locale, new HashMap<>(this.propertyMap), this.history);
}
/**
@@ -315,9 +259,13 @@ public final class User {
if (getClass() != obj.getClass())
return false;
User other = (User) obj;
- if (this.userId == null) {
+ if (this.userId == null)
return other.userId == null;
- } else
- return this.userId.equals(other.userId);
+ return this.userId.equals(other.userId);
+ }
+
+ public User withHistory(UserHistory history) {
+ return new User(this.userId, this.username, this.passwordCrypt, this.firstname, this.lastname, this.userState,
+ this.groups, this.roles, this.locale, this.propertyMap, this.passwordChangeRequested, history);
}
}
diff --git a/privilege/src/main/java/li/strolch/privilege/model/internal/UserChallenge.java b/privilege/src/main/java/li/strolch/privilege/model/internal/UserChallenge.java
index 808810df4..f16e852db 100644
--- a/privilege/src/main/java/li/strolch/privilege/model/internal/UserChallenge.java
+++ b/privilege/src/main/java/li/strolch/privilege/model/internal/UserChallenge.java
@@ -1,10 +1,11 @@
package li.strolch.privilege.model.internal;
+import li.strolch.privilege.model.Usage;
+import li.strolch.utils.dbc.DBC;
+
import java.time.LocalDateTime;
-import li.strolch.privilege.model.Usage;
-
-public class UserChallenge {
+public final class UserChallenge {
private final User user;
private final String challenge;
private final String source;
@@ -13,6 +14,10 @@ public class UserChallenge {
private boolean fulfilled;
public UserChallenge(Usage usage, User user, String challenge, String source) {
+ DBC.PRE.assertNotNull("usage may not be null", usage);
+ DBC.PRE.assertNotNull("user may not be null", user);
+ DBC.PRE.assertNotNull("challenge may not be empty", challenge);
+ DBC.PRE.assertNotNull("source may not be empty", source);
this.usage = usage;
this.user = user;
this.challenge = challenge;
diff --git a/privilege/src/main/java/li/strolch/privilege/model/internal/UserHistory.java b/privilege/src/main/java/li/strolch/privilege/model/internal/UserHistory.java
index adb5d9f6d..e899f7796 100644
--- a/privilege/src/main/java/li/strolch/privilege/model/internal/UserHistory.java
+++ b/privilege/src/main/java/li/strolch/privilege/model/internal/UserHistory.java
@@ -1,32 +1,20 @@
package li.strolch.privilege.model.internal;
-import java.io.Serializable;
import java.time.ZonedDateTime;
-import li.strolch.utils.iso8601.ISO8601;
+import static li.strolch.utils.iso8601.ISO8601.EMPTY_VALUE_ZONED_DATE;
-public class UserHistory implements Serializable {
+public record UserHistory(ZonedDateTime firstLogin, ZonedDateTime lastLogin, ZonedDateTime lastPasswordChange) {
- private ZonedDateTime firstLogin;
- private ZonedDateTime lastLogin;
- private ZonedDateTime lastPasswordChange;
-
- public UserHistory() {
- this.firstLogin = ISO8601.EMPTY_VALUE_ZONED_DATE;
- this.lastLogin = ISO8601.EMPTY_VALUE_ZONED_DATE;
- this.lastPasswordChange = ISO8601.EMPTY_VALUE_ZONED_DATE;
- }
+ public static final UserHistory EMPTY = new UserHistory(EMPTY_VALUE_ZONED_DATE, EMPTY_VALUE_ZONED_DATE,
+ EMPTY_VALUE_ZONED_DATE);
public ZonedDateTime getFirstLogin() {
return this.firstLogin;
}
public boolean isFirstLoginEmpty() {
- return this.firstLogin.equals(ISO8601.EMPTY_VALUE_ZONED_DATE);
- }
-
- public void setFirstLogin(ZonedDateTime firstLogin) {
- this.firstLogin = firstLogin;
+ return this.firstLogin.equals(EMPTY_VALUE_ZONED_DATE);
}
public ZonedDateTime getLastLogin() {
@@ -34,11 +22,7 @@ public class UserHistory implements Serializable {
}
public boolean isLastLoginEmpty() {
- return this.lastLogin.equals(ISO8601.EMPTY_VALUE_ZONED_DATE);
- }
-
- public void setLastLogin(ZonedDateTime lastLogin) {
- this.lastLogin = lastLogin;
+ return this.lastLogin.equals(EMPTY_VALUE_ZONED_DATE);
}
public ZonedDateTime getLastPasswordChange() {
@@ -46,22 +30,26 @@ public class UserHistory implements Serializable {
}
public boolean isLastPasswordChangeEmpty() {
- return this.lastPasswordChange.equals(ISO8601.EMPTY_VALUE_ZONED_DATE);
- }
-
- public void setLastPasswordChange(ZonedDateTime lastPasswordChange) {
- this.lastPasswordChange = lastPasswordChange;
+ return this.lastPasswordChange.equals(EMPTY_VALUE_ZONED_DATE);
}
public boolean isEmpty() {
return isFirstLoginEmpty() && isLastLoginEmpty() && isLastPasswordChangeEmpty();
}
- public UserHistory getClone() {
- UserHistory clone = new UserHistory();
- clone.firstLogin = this.firstLogin;
- clone.lastLogin = this.lastLogin;
- clone.lastPasswordChange = this.lastPasswordChange;
- return clone;
+ public UserHistory withFirstLogin(ZonedDateTime firstLogin) {
+ return new UserHistory(firstLogin, this.lastLogin, lastPasswordChange);
+ }
+
+ public UserHistory withLastLogin(ZonedDateTime lastLogin) {
+ return new UserHistory(this.firstLogin, lastLogin, this.lastPasswordChange);
+ }
+
+ public UserHistory withLogin(ZonedDateTime lastLogin) {
+ return new UserHistory(isFirstLoginEmpty() ? lastLogin : this.firstLogin, lastLogin, this.lastPasswordChange);
+ }
+
+ public UserHistory withLastPasswordChange(ZonedDateTime lastPasswordChange) {
+ return new UserHistory(this.firstLogin, this.lastLogin, lastPasswordChange);
}
}
diff --git a/privilege/src/main/java/li/strolch/privilege/policy/DefaultPrivilege.java b/privilege/src/main/java/li/strolch/privilege/policy/DefaultPrivilege.java
index 72c8c2852..6fe66b372 100644
--- a/privilege/src/main/java/li/strolch/privilege/policy/DefaultPrivilege.java
+++ b/privilege/src/main/java/li/strolch/privilege/policy/DefaultPrivilege.java
@@ -22,7 +22,7 @@ import java.text.MessageFormat;
import li.strolch.privilege.base.AccessDeniedException;
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.i18n.PrivilegeMessages;
-import li.strolch.privilege.model.IPrivilege;
+import li.strolch.privilege.model.Privilege;
import li.strolch.privilege.model.PrivilegeContext;
import li.strolch.privilege.model.Restrictable;
import li.strolch.privilege.model.internal.Role;
@@ -38,10 +38,10 @@ public class DefaultPrivilege implements PrivilegePolicy {
/**
* The value of {@link Restrictable#getPrivilegeValue()} is used to check if the {@link Role} has this privilege
*
- * @see li.strolch.privilege.policy.PrivilegePolicy#validateAction(PrivilegeContext, IPrivilege, Restrictable)
+ * @see li.strolch.privilege.policy.PrivilegePolicy#validateAction(PrivilegeContext, Privilege, Restrictable)
*/
@Override
- public void validateAction(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable)
+ public void validateAction(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable)
throws AccessDeniedException {
String privilegeValue = validatePrivilegeValue(privilege, restrictable);
@@ -54,7 +54,7 @@ public class DefaultPrivilege implements PrivilegePolicy {
}
@Override
- public boolean hasPrivilege(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable) {
+ public boolean hasPrivilege(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable) {
String privilegeValue = validatePrivilegeValue(privilege, restrictable);
@@ -65,7 +65,7 @@ public class DefaultPrivilege implements PrivilegePolicy {
return checkByAllowDenyValues(ctx, privilege, restrictable, privilegeValue, false);
}
- private String validatePrivilegeValue(IPrivilege privilege, Restrictable restrictable) {
+ private String validatePrivilegeValue(Privilege privilege, Restrictable restrictable) {
PrivilegePolicyHelper.preValidate(privilege, restrictable);
// get the value on which the action is to be performed
diff --git a/privilege/src/main/java/li/strolch/privilege/policy/PrivilegePolicy.java b/privilege/src/main/java/li/strolch/privilege/policy/PrivilegePolicy.java
index dcdd97d2d..119fbc950 100644
--- a/privilege/src/main/java/li/strolch/privilege/policy/PrivilegePolicy.java
+++ b/privilege/src/main/java/li/strolch/privilege/policy/PrivilegePolicy.java
@@ -17,7 +17,7 @@ package li.strolch.privilege.policy;
import li.strolch.privilege.base.AccessDeniedException;
import li.strolch.privilege.base.PrivilegeException;
-import li.strolch.privilege.model.IPrivilege;
+import li.strolch.privilege.model.Privilege;
import li.strolch.privilege.model.PrivilegeContext;
import li.strolch.privilege.model.Restrictable;
import li.strolch.privilege.model.internal.Role;
@@ -26,7 +26,7 @@ import li.strolch.privilege.model.internal.User;
/**
*
* {@link PrivilegePolicy} implements logic to determine if a {@link User} which has the given {@link Role} and the
- * given {@link IPrivilege} has access to the given {@link Restrictable}
+ * given {@link Privilege} has access to the given {@link Restrictable}
*
*
*
@@ -38,29 +38,29 @@ import li.strolch.privilege.model.internal.User;
public interface PrivilegePolicy {
/**
- * Checks if the given {@link Role} and the given {@link IPrivilege} has access to the given {@link Restrictable}
+ * Checks if the given {@link Role} and the given {@link Privilege} has access to the given {@link Restrictable}
*
* @param context
* the privilege context
* @param privilege
- * the {@link IPrivilege} containing the permissions
+ * the {@link Privilege} containing the permissions
* @param restrictable
* the {@link Restrictable} to which the user wants access
*
* @throws AccessDeniedException
* if action not allowed
*/
- void validateAction(PrivilegeContext context, IPrivilege privilege, Restrictable restrictable)
+ void validateAction(PrivilegeContext context, Privilege privilege, Restrictable restrictable)
throws AccessDeniedException;
/**
- * Returns true if the given {@link Role} and the given {@link IPrivilege} has access to the given {@link
+ * Returns true if the given {@link Role} and the given {@link Privilege} has access to the given {@link
* Restrictable}
*
* @param context
* the privilege context
* @param privilege
- * the {@link IPrivilege} containing the permissions
+ * the {@link Privilege} containing the permissions
* @param restrictable
* the {@link Restrictable} to which the user wants access
*
@@ -69,6 +69,6 @@ public interface PrivilegePolicy {
* @throws AccessDeniedException
* if something goes wrong with the validate
*/
- boolean hasPrivilege(PrivilegeContext context, IPrivilege privilege, Restrictable restrictable)
+ boolean hasPrivilege(PrivilegeContext context, Privilege privilege, Restrictable restrictable)
throws PrivilegeException;
}
diff --git a/privilege/src/main/java/li/strolch/privilege/policy/PrivilegePolicyHelper.java b/privilege/src/main/java/li/strolch/privilege/policy/PrivilegePolicyHelper.java
index 21efe70c4..e4d0ac639 100644
--- a/privilege/src/main/java/li/strolch/privilege/policy/PrivilegePolicyHelper.java
+++ b/privilege/src/main/java/li/strolch/privilege/policy/PrivilegePolicyHelper.java
@@ -20,7 +20,7 @@ import java.text.MessageFormat;
import li.strolch.privilege.base.AccessDeniedException;
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.i18n.PrivilegeMessages;
-import li.strolch.privilege.model.IPrivilege;
+import li.strolch.privilege.model.Privilege;
import li.strolch.privilege.model.PrivilegeContext;
import li.strolch.privilege.model.Restrictable;
import li.strolch.utils.helper.StringHelper;
@@ -34,7 +34,7 @@ public class PrivilegePolicyHelper {
* Validates the given values and returns the privilege name
*
* @param privilege
- * the {@link IPrivilege}
+ * the {@link Privilege}
* @param restrictable
* the {@link Restrictable}
*
@@ -43,7 +43,7 @@ public class PrivilegePolicyHelper {
* @throws PrivilegeException
* if something is wrong
*/
- public static String preValidate(IPrivilege privilege, Restrictable restrictable) throws PrivilegeException {
+ public static String preValidate(Privilege privilege, Restrictable restrictable) throws PrivilegeException {
if (privilege == null)
throw new PrivilegeException(PrivilegeMessages.getString("Privilege.privilegeNull"));
if (restrictable == null)
@@ -88,7 +88,7 @@ public class PrivilegePolicyHelper {
* @throws AccessDeniedException
* if access is denied
*/
- public static boolean checkByAllowDenyValues(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable,
+ public static boolean checkByAllowDenyValues(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable,
String privilegeValue, boolean assertHasPrivilege) throws AccessDeniedException {
// first check values not allowed
@@ -102,7 +102,7 @@ public class PrivilegePolicyHelper {
return handleAccessDenied(ctx, privilege, restrictable, privilegeValue, assertHasPrivilege);
}
- private static boolean handleAccessDenied(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable,
+ private static boolean handleAccessDenied(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable,
String privilegeValue, boolean assertHasPrivilege) {
if (assertHasPrivilege) {
diff --git a/privilege/src/main/java/li/strolch/privilege/policy/RoleAccessPrivilege.java b/privilege/src/main/java/li/strolch/privilege/policy/RoleAccessPrivilege.java
index 527950af1..7754a0301 100644
--- a/privilege/src/main/java/li/strolch/privilege/policy/RoleAccessPrivilege.java
+++ b/privilege/src/main/java/li/strolch/privilege/policy/RoleAccessPrivilege.java
@@ -24,7 +24,7 @@ import li.strolch.privilege.base.AccessDeniedException;
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.handler.PrivilegeHandler;
import li.strolch.privilege.i18n.PrivilegeMessages;
-import li.strolch.privilege.model.IPrivilege;
+import li.strolch.privilege.model.Privilege;
import li.strolch.privilege.model.PrivilegeContext;
import li.strolch.privilege.model.Restrictable;
import li.strolch.privilege.model.internal.Role;
@@ -42,18 +42,18 @@ import li.strolch.utils.dbc.DBC;
public class RoleAccessPrivilege implements PrivilegePolicy {
@Override
- public void validateAction(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable)
+ public void validateAction(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable)
throws AccessDeniedException {
validateAction(ctx, privilege, restrictable, true);
}
@Override
- public boolean hasPrivilege(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable)
+ public boolean hasPrivilege(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable)
throws PrivilegeException {
return validateAction(ctx, privilege, restrictable, false);
}
- private boolean validateAction(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable,
+ private boolean validateAction(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable,
boolean assertHasPrivilege) throws AccessDeniedException {
String privilegeName = preValidate(privilege, restrictable);
diff --git a/privilege/src/main/java/li/strolch/privilege/policy/UserAccessPrivilege.java b/privilege/src/main/java/li/strolch/privilege/policy/UserAccessPrivilege.java
index 080fae322..39feeda4a 100644
--- a/privilege/src/main/java/li/strolch/privilege/policy/UserAccessPrivilege.java
+++ b/privilege/src/main/java/li/strolch/privilege/policy/UserAccessPrivilege.java
@@ -24,7 +24,7 @@ import li.strolch.privilege.base.AccessDeniedException;
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.handler.PrivilegeHandler;
import li.strolch.privilege.i18n.PrivilegeMessages;
-import li.strolch.privilege.model.IPrivilege;
+import li.strolch.privilege.model.Privilege;
import li.strolch.privilege.model.PrivilegeContext;
import li.strolch.privilege.model.Restrictable;
import li.strolch.privilege.model.internal.User;
@@ -41,18 +41,18 @@ import li.strolch.utils.dbc.DBC;
public class UserAccessPrivilege implements PrivilegePolicy {
@Override
- public void validateAction(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable)
+ public void validateAction(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable)
throws AccessDeniedException {
validateAction(ctx, privilege, restrictable, true);
}
@Override
- public boolean hasPrivilege(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable)
+ public boolean hasPrivilege(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable)
throws PrivilegeException {
return validateAction(ctx, privilege, restrictable, false);
}
- protected boolean validateAction(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable,
+ protected boolean validateAction(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable,
boolean assertHasPrivilege) throws AccessDeniedException {
String privilegeName = preValidate(privilege, restrictable);
diff --git a/privilege/src/main/java/li/strolch/privilege/policy/UserAccessWithSameOrganisationPrivilege.java b/privilege/src/main/java/li/strolch/privilege/policy/UserAccessWithSameOrganisationPrivilege.java
index b697776e2..c05803d33 100644
--- a/privilege/src/main/java/li/strolch/privilege/policy/UserAccessWithSameOrganisationPrivilege.java
+++ b/privilege/src/main/java/li/strolch/privilege/policy/UserAccessWithSameOrganisationPrivilege.java
@@ -28,7 +28,7 @@ import li.strolch.privilege.base.AccessDeniedException;
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.handler.PrivilegeHandler;
import li.strolch.privilege.i18n.PrivilegeMessages;
-import li.strolch.privilege.model.IPrivilege;
+import li.strolch.privilege.model.Privilege;
import li.strolch.privilege.model.PrivilegeContext;
import li.strolch.privilege.model.Restrictable;
import li.strolch.privilege.model.internal.User;
@@ -43,13 +43,13 @@ import li.strolch.utils.dbc.DBC;
public class UserAccessWithSameOrganisationPrivilege extends UserAccessPrivilege {
@Override
- public void validateAction(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable)
+ public void validateAction(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable)
throws AccessDeniedException {
validateAction(ctx, privilege, restrictable, true);
}
@Override
- public boolean hasPrivilege(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable)
+ public boolean hasPrivilege(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable)
throws PrivilegeException {
return validateAction(ctx, privilege, restrictable, false);
}
@@ -59,7 +59,7 @@ public class UserAccessWithSameOrganisationPrivilege extends UserAccessPrivilege
}
@Override
- protected boolean validateAction(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable,
+ protected boolean validateAction(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable,
boolean assertHasPrivilege) throws AccessDeniedException {
String privilegeName = preValidate(privilege, restrictable);
diff --git a/privilege/src/main/java/li/strolch/privilege/policy/UsernameFromCertificatePrivilege.java b/privilege/src/main/java/li/strolch/privilege/policy/UsernameFromCertificatePrivilege.java
index 414faf8a5..6bb1d8c27 100644
--- a/privilege/src/main/java/li/strolch/privilege/policy/UsernameFromCertificatePrivilege.java
+++ b/privilege/src/main/java/li/strolch/privilege/policy/UsernameFromCertificatePrivilege.java
@@ -24,7 +24,7 @@ import li.strolch.privilege.base.AccessDeniedException;
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.i18n.PrivilegeMessages;
import li.strolch.privilege.model.Certificate;
-import li.strolch.privilege.model.IPrivilege;
+import li.strolch.privilege.model.Privilege;
import li.strolch.privilege.model.PrivilegeContext;
import li.strolch.privilege.model.Restrictable;
@@ -44,18 +44,18 @@ import li.strolch.privilege.model.Restrictable;
public class UsernameFromCertificatePrivilege implements PrivilegePolicy {
@Override
- public void validateAction(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable)
+ public void validateAction(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable)
throws AccessDeniedException {
validateAction(ctx, privilege, restrictable, true);
}
@Override
- public boolean hasPrivilege(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable)
+ public boolean hasPrivilege(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable)
throws PrivilegeException {
return validateAction(ctx, privilege, restrictable, false);
}
- protected boolean validateAction(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable,
+ protected boolean validateAction(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable,
boolean assertHasPrivilege) throws AccessDeniedException {
preValidate(privilege, restrictable);
diff --git a/privilege/src/main/java/li/strolch/privilege/policy/UsernameFromCertificateWithSameOrganisationPrivilege.java b/privilege/src/main/java/li/strolch/privilege/policy/UsernameFromCertificateWithSameOrganisationPrivilege.java
index ba654e270..46bec6302 100644
--- a/privilege/src/main/java/li/strolch/privilege/policy/UsernameFromCertificateWithSameOrganisationPrivilege.java
+++ b/privilege/src/main/java/li/strolch/privilege/policy/UsernameFromCertificateWithSameOrganisationPrivilege.java
@@ -28,7 +28,7 @@ import li.strolch.privilege.base.AccessDeniedException;
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.i18n.PrivilegeMessages;
import li.strolch.privilege.model.Certificate;
-import li.strolch.privilege.model.IPrivilege;
+import li.strolch.privilege.model.Privilege;
import li.strolch.privilege.model.PrivilegeContext;
import li.strolch.privilege.model.Restrictable;
@@ -48,19 +48,19 @@ import li.strolch.privilege.model.Restrictable;
public class UsernameFromCertificateWithSameOrganisationPrivilege extends UsernameFromCertificatePrivilege {
@Override
- public void validateAction(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable)
+ public void validateAction(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable)
throws AccessDeniedException {
validateAction(ctx, privilege, restrictable, true);
}
@Override
- public boolean hasPrivilege(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable)
+ public boolean hasPrivilege(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable)
throws PrivilegeException {
return validateAction(ctx, privilege, restrictable, false);
}
@Override
- protected boolean validateAction(PrivilegeContext ctx, IPrivilege privilege, Restrictable restrictable,
+ protected boolean validateAction(PrivilegeContext ctx, Privilege privilege, Restrictable restrictable,
boolean assertHasPrivilege) throws AccessDeniedException {
preValidate(privilege, restrictable);
diff --git a/privilege/src/main/java/li/strolch/privilege/xml/CertificateStubsDomWriter.java b/privilege/src/main/java/li/strolch/privilege/xml/CertificateStubsDomWriter.java
deleted file mode 100644
index 293386de4..000000000
--- a/privilege/src/main/java/li/strolch/privilege/xml/CertificateStubsDomWriter.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright 2013 Robert von Burg
- *
- * 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
- */
-public class CertificateStubsDomWriter {
-
- private final List certificates;
- private final OutputStream outputStream;
-
- public CertificateStubsDomWriter(List 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);
- }
-}
diff --git a/privilege/src/main/java/li/strolch/privilege/xml/CertificateStubsSaxReader.java b/privilege/src/main/java/li/strolch/privilege/xml/CertificateStubsSaxReader.java
index 5f7a3975b..2d306974d 100644
--- a/privilege/src/main/java/li/strolch/privilege/xml/CertificateStubsSaxReader.java
+++ b/privilege/src/main/java/li/strolch/privilege/xml/CertificateStubsSaxReader.java
@@ -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
*/
@@ -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 ROOT_CERTIFICATES -> {
+ }
+ case CERTIFICATE -> {
+ CertificateStub stub = new CertificateStub();
+ stub.usage = Usage.valueOf(attributes.getValue(ATTR_USAGE).trim());
+ stub.sessionId = attributes.getValue(ATTR_SESSION_ID).trim();
+ stub.username = attributes.getValue(ATTR_USERNAME).trim();
+ stub.authToken = attributes.getValue(ATTR_AUTH_TOKEN).trim();
+ stub.source = attributes.getValue(ATTR_SOURCE).trim();
+ stub.locale = Locale.forLanguageTag(attributes.getValue(ATTR_LOCALE).trim());
+ stub.loginTime = ISO8601.parseToZdt(attributes.getValue(ATTR_LOGIN_TIME).trim());
+ stub.lastAccess = ISO8601.parseToZdt(attributes.getValue(ATTR_LAST_ACCESS).trim());
+ stub.keepAlive = Boolean.parseBoolean(attributes.getValue(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);
}
}
diff --git a/privilege/src/main/java/li/strolch/privilege/xml/CertificateStubsSaxWriter.java b/privilege/src/main/java/li/strolch/privilege/xml/CertificateStubsSaxWriter.java
new file mode 100644
index 000000000..7351ce28c
--- /dev/null
+++ b/privilege/src/main/java/li/strolch/privilege/xml/CertificateStubsSaxWriter.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2013 Robert von Burg
+ *
+ * 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
+ */
+public class CertificateStubsSaxWriter {
+
+ private final List certificates;
+ private final OutputStream outputStream;
+
+ public CertificateStubsSaxWriter(List 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(ROOT_CERTIFICATES);
+
+ List certificates = new ArrayList<>(this.certificates);
+ certificates.sort(comparing(Certificate::getSessionId));
+ for (Certificate cert : certificates) {
+
+ // create the certificate element
+ xmlWriter.writeStartElement(CERTIFICATE);
+
+ // sessionId;
+ xmlWriter.writeAttribute(ATTR_SESSION_ID, cert.getSessionId());
+
+ // usage;
+ xmlWriter.writeAttribute(ATTR_USAGE, cert.getUsage().name());
+
+ // username;
+ xmlWriter.writeAttribute(ATTR_USERNAME, cert.getUsername());
+
+ // authToken;
+ xmlWriter.writeAttribute(ATTR_AUTH_TOKEN, cert.getAuthToken());
+
+ // source;
+ xmlWriter.writeAttribute(ATTR_SOURCE, cert.getSource());
+
+ // locale;
+ xmlWriter.writeAttribute(ATTR_LOCALE, cert.getLocale().toLanguageTag());
+
+ // loginTime;
+ xmlWriter.writeAttribute(ATTR_LOGIN_TIME, ISO8601.toString(cert.getLoginTime()));
+
+ // lastAccess;
+ xmlWriter.writeAttribute(ATTR_LAST_ACCESS, ISO8601.toString(cert.getLastAccess()));
+
+ // keepAlive;
+ xmlWriter.writeAttribute(ATTR_KEEP_ALIVE, String.valueOf(cert.isKeepAlive()));
+ }
+
+ // and now end
+ xmlWriter.writeEndDocument();
+ xmlWriter.flush();
+ }
+}
diff --git a/privilege/src/main/java/li/strolch/privilege/xml/ElementParser.java b/privilege/src/main/java/li/strolch/privilege/xml/ElementParser.java
index 1d66d3a7c..2b1c3b3e9 100644
--- a/privilege/src/main/java/li/strolch/privilege/xml/ElementParser.java
+++ b/privilege/src/main/java/li/strolch/privilege/xml/ElementParser.java
@@ -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);
diff --git a/privilege/src/main/java/li/strolch/privilege/xml/PrivilegeConfigDomWriter.java b/privilege/src/main/java/li/strolch/privilege/xml/PrivilegeConfigDomWriter.java
deleted file mode 100644
index eca2a0135..000000000
--- a/privilege/src/main/java/li/strolch/privilege/xml/PrivilegeConfigDomWriter.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright 2013 Robert von Burg
- *
- * 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
- */
-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 parameterMap) {
-
- if (parameterMap != null && !parameterMap.isEmpty()) {
- Element parametersElement = doc.createElement(XML_PARAMETERS);
- for (Entry 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);
- }
- }
-}
diff --git a/privilege/src/main/java/li/strolch/privilege/xml/PrivilegeConfigSaxReader.java b/privilege/src/main/java/li/strolch/privilege/xml/PrivilegeConfigSaxReader.java
index ef4ae6a3c..1d956b65c 100644
--- a/privilege/src/main/java/li/strolch/privilege/xml/PrivilegeConfigSaxReader.java
+++ b/privilege/src/main/java/li/strolch/privilege/xml/PrivilegeConfigSaxReader.java
@@ -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
@@ -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 CONTAINER -> this.buildersStack.push(new ContainerParser());
+ case PARAMETERS -> this.buildersStack.push(new ParametersParser());
+ case POLICIES -> this.buildersStack.push(new PoliciesParser());
+ default -> {
+ // nothing to do, probably handle on stack
+ }
}
if (!this.buildersStack.isEmpty())
@@ -73,7 +72,7 @@ public class PrivilegeConfigSaxReader extends DefaultHandler {
this.buildersStack.peek().endElement(uri, localName, qName);
ElementParser elementParser = switch (qName) {
- case XML_CONTAINER, XML_PARAMETERS, XML_POLICIES -> this.buildersStack.pop();
+ case CONTAINER, PARAMETERS, POLICIES -> this.buildersStack.pop();
default -> null;
};
@@ -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 CONTAINER -> this.currentElement = qName;
+ case HANDLER_PRIVILEGE -> {
+ this.currentElement = qName;
+ String className = attributes.getValue(ATTR_CLASS).trim();
+ getContainerModel().setPrivilegeHandlerClassName(className);
+ }
+ case HANDLER_ENCRYPTION -> {
+ this.currentElement = qName;
+ String className = attributes.getValue(ATTR_CLASS).trim();
+ getContainerModel().setEncryptionHandlerClassName(className);
+ }
+ case HANDLER_PASSWORD_STRENGTH -> {
+ this.currentElement = qName;
+ String className = attributes.getValue(ATTR_CLASS).trim();
+ getContainerModel().setPasswordStrengthHandlerClassName(className);
+ }
+ case HANDLER_PERSISTENCE -> {
+ this.currentElement = qName;
+ String className = attributes.getValue(ATTR_CLASS).trim();
+ getContainerModel().setPersistenceHandlerClassName(className);
+ }
+ case HANDLER_USER_CHALLENGE -> {
+ this.currentElement = qName;
+ String className = attributes.getValue(ATTR_CLASS).trim();
+ getContainerModel().setUserChallengeHandlerClassName(className);
+ }
+ case HANDLER_SSO -> {
+ this.currentElement = qName;
+ String className = attributes.getValue(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 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 CONTAINER -> getContainerModel().setParameterMap(params);
+ case HANDLER_PRIVILEGE -> getContainerModel().setPrivilegeHandlerParameterMap(params);
+ case HANDLER_ENCRYPTION -> getContainerModel().setEncryptionHandlerParameterMap(params);
+ case HANDLER_PASSWORD_STRENGTH ->
+ getContainerModel().setPasswordStrengthHandlerParameterMap(params);
+ case HANDLER_PERSISTENCE -> getContainerModel().setPersistenceHandlerParameterMap(params);
+ case HANDLER_USER_CHALLENGE -> getContainerModel().setUserChallengeHandlerParameterMap(params);
+ case HANDLER_SSO -> getContainerModel().setSsoHandlerParameterMap(params);
+ default -> throw new IllegalStateException("Unexpected value: " + this.currentElement);
}
}
}
@@ -155,9 +151,9 @@ public class PrivilegeConfigSaxReader extends DefaultHandler {
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) {
- if (qName.equals(XML_PARAMETER)) {
- String key = attributes.getValue(XML_ATTR_NAME).trim();
- String value = attributes.getValue(XML_ATTR_VALUE).trim();
+ if (qName.equals(PARAMETER)) {
+ String key = attributes.getValue(ATTR_NAME).trim();
+ String value = attributes.getValue(ATTR_VALUE).trim();
this.parameterMap.put(key, value);
}
}
@@ -176,9 +172,9 @@ public class PrivilegeConfigSaxReader extends DefaultHandler {
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) {
- if (qName.equals(XML_POLICY)) {
- String policyName = attributes.getValue(XML_ATTR_NAME).trim();
- String policyClassName = attributes.getValue(XML_ATTR_CLASS).trim();
+ if (qName.equals(POLICY)) {
+ String policyName = attributes.getValue(ATTR_NAME).trim();
+ String policyClassName = attributes.getValue(ATTR_CLASS).trim();
getContainerModel().addPolicy(policyName, policyClassName);
}
diff --git a/privilege/src/main/java/li/strolch/privilege/xml/PrivilegeConfigSaxWriter.java b/privilege/src/main/java/li/strolch/privilege/xml/PrivilegeConfigSaxWriter.java
new file mode 100644
index 000000000..6732b66f6
--- /dev/null
+++ b/privilege/src/main/java/li/strolch/privilege/xml/PrivilegeConfigSaxWriter.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2013 Robert von Burg
+ *
+ * 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
+ */
+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(ROOT_PRIVILEGE);
+
+ // write container element
+ xmlWriter.writeStartElement(CONTAINER);
+ writeStringMapElement(xmlWriter, this.containerModel.getParameterMap(), PARAMETERS, PARAMETER);
+
+ {
+ // write PrivilegeHandler
+ if (this.containerModel.getPrivilegeHandlerClassName() != null)
+ writeHandler(xmlWriter, HANDLER_PRIVILEGE, this.containerModel.getPrivilegeHandlerClassName(),
+ this.containerModel.getPrivilegeHandlerParameterMap());
+
+ // write EncryptionHandler
+ writeHandler(xmlWriter, HANDLER_ENCRYPTION, this.containerModel.getEncryptionHandlerClassName(),
+ this.containerModel.getEncryptionHandlerParameterMap());
+
+ // write PersistenceHandler
+ writeHandler(xmlWriter, HANDLER_PERSISTENCE, this.containerModel.getPersistenceHandlerClassName(),
+ this.containerModel.getPersistenceHandlerParameterMap());
+
+ // write PasswordStrengthHandler
+ if (this.containerModel.getPasswordStrengthHandlerClassName() != null)
+ writeHandler(xmlWriter, HANDLER_PASSWORD_STRENGTH,
+ this.containerModel.getPasswordStrengthHandlerClassName(),
+ this.containerModel.getPasswordStrengthHandlerParameterMap());
+
+ // write UserChallengeHandler
+ if (this.containerModel.getUserChallengeHandlerClassName() != null)
+ writeHandler(xmlWriter, HANDLER_USER_CHALLENGE,
+ this.containerModel.getUserChallengeHandlerClassName(),
+ this.containerModel.getUserChallengeHandlerParameterMap());
+
+ // write SingleSignOnHandler
+ if (this.containerModel.getSsoHandlerClassName() != null)
+ writeHandler(xmlWriter, HANDLER_SSO, this.containerModel.getSsoHandlerClassName(),
+ this.containerModel.getSsoHandlerParameterMap());
+ }
+
+ xmlWriter.writeEndElement();
+
+ // Policies
+ Map policies = new HashMap<>();
+ this.containerModel.getPolicies().forEach((key, value) -> policies.put(key, value.getName()));
+ writeStringMapElement(xmlWriter, policies, POLICIES, POLICY, ATTR_CLASS);
+
+ // and now end
+ xmlWriter.writeEndDocument();
+ xmlWriter.flush();
+ }
+ }
+
+ private void writeHandler(IndentingXMLStreamWriter xmlWriter, String handleName, String className,
+ Map parameters) throws XMLStreamException {
+ if (parameters.isEmpty())
+ xmlWriter.writeEmptyElement(handleName);
+ else
+ xmlWriter.writeStartElement(handleName);
+ xmlWriter.writeAttribute(ATTR_CLASS, className);
+
+ writeStringMapElement(xmlWriter, parameters, PARAMETERS, PARAMETER);
+
+ if (!parameters.isEmpty())
+ xmlWriter.writeEndElement();
+ }
+}
diff --git a/privilege/src/main/java/li/strolch/privilege/xml/PrivilegeGroupsSaxReader.java b/privilege/src/main/java/li/strolch/privilege/xml/PrivilegeGroupsSaxReader.java
new file mode 100644
index 000000000..fe6a834e1
--- /dev/null
+++ b/privilege/src/main/java/li/strolch/privilege/xml/PrivilegeGroupsSaxReader.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright 2013 Robert von Burg
+ *
+ * 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.model.internal.Group;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+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
+ */
+public class PrivilegeGroupsSaxReader extends DefaultHandler {
+
+ protected static final Logger logger = LoggerFactory.getLogger(PrivilegeGroupsSaxReader.class);
+
+ private final Deque buildersStack = new ArrayDeque<>();
+
+ private final Map groups;
+
+ public PrivilegeGroupsSaxReader() {
+ this.groups = new HashMap<>();
+ }
+
+ /**
+ * @return the users
+ */
+ public Map getGroups() {
+ return this.groups;
+ }
+
+ @Override
+ public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
+ if (qName.equals(GROUP)) {
+ if (this.buildersStack.stream().anyMatch(e -> e.getClass().equals(GroupParser.class)))
+ throw new IllegalArgumentException("Previous Group not closed!");
+ this.buildersStack.push(new GroupParser());
+ } else if (qName.equals(PROPERTIES)) {
+ if (this.buildersStack.stream().anyMatch(e -> e.getClass().equals(PropertyParser.class)))
+ throw new IllegalArgumentException("Previous Properties not closed!");
+ this.buildersStack.push(new PropertyParser());
+ }
+
+ if (!this.buildersStack.isEmpty())
+ this.buildersStack.peek().startElement(uri, localName, qName, attributes);
+ }
+
+ @Override
+ public void characters(char[] ch, int start, int length) throws SAXException {
+ if (!this.buildersStack.isEmpty())
+ this.buildersStack.peek().characters(ch, start, length);
+ }
+
+ @Override
+ public void endElement(String uri, String localName, String qName) throws SAXException {
+
+ if (!this.buildersStack.isEmpty())
+ this.buildersStack.peek().endElement(uri, localName, qName);
+
+ ElementParser elementParser = null;
+ if (qName.equals(GROUP)) {
+ elementParser = this.buildersStack.pop();
+ } else if (qName.equals(PROPERTIES)) {
+ elementParser = this.buildersStack.pop();
+ }
+
+ if (!this.buildersStack.isEmpty() && elementParser != null)
+ this.buildersStack.peek().notifyChild(elementParser);
+ }
+
+ //
+ // Application
+ // Administrator
+ // ENABLED
+ // en-GB
+ //
+ // PrivilegeAdmin
+ // AppUser
+ //
+ //
+ //
+ //
+ //
+ //
+ // 2021-02-19T15:32:09.592+01:00
+ // 2021-02-19T15:32:09.592+01:00
+ // 2021-02-19T15:32:09.592+01:00
+ //
+ //
+
+ public class GroupParser extends ElementParserAdapter {
+
+ StringBuilder text;
+
+ String name;
+ final Set roles;
+ Map parameters;
+
+ public GroupParser() {
+ this.roles = new HashSet<>();
+ this.parameters = new HashMap<>();
+ }
+
+ @Override
+ public void startElement(String uri, String localName, String qName, Attributes attributes) {
+
+ this.text = new StringBuilder();
+
+ if (qName.equals(GROUP)) {
+ this.name = attributes.getValue(ATTR_NAME).trim();
+ }
+ }
+
+ @Override
+ public void characters(char[] ch, int start, int length) {
+ this.text.append(ch, start, length);
+ }
+
+ @Override
+ public void endElement(String uri, String localName, String qName) {
+
+ switch (qName) {
+ case ROLE -> this.roles.add(getText());
+ case GROUP -> {
+
+ Group group = new Group(this.name, this.roles, this.parameters);
+
+ logger.info(MessageFormat.format("New Group: {0}", group));
+ groups.put(this.name, group);
+ }
+ default -> {
+ if (!(qName.equals(GROUPS) //
+ || qName.equals(ROLES) //
+ || qName.equals(PARAMETER) //
+ || qName.equals(PARAMETERS))) {
+ throw new IllegalArgumentException("Unhandled tag " + qName);
+ }
+ }
+ }
+ }
+
+ private String getText() {
+ return this.text.toString().trim();
+ }
+
+ @Override
+ public void notifyChild(ElementParser child) {
+ if (child instanceof PropertyParser) {
+ this.parameters = ((PropertyParser) child).parameterMap;
+ }
+ }
+ }
+
+}
diff --git a/privilege/src/main/java/li/strolch/privilege/xml/PrivilegeGroupsSaxWriter.java b/privilege/src/main/java/li/strolch/privilege/xml/PrivilegeGroupsSaxWriter.java
new file mode 100644
index 000000000..cc3a9f752
--- /dev/null
+++ b/privilege/src/main/java/li/strolch/privilege/xml/PrivilegeGroupsSaxWriter.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2013 Robert von Burg
+ *
+ * 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.Group;
+
+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 java.util.Map;
+
+import static java.util.Comparator.comparing;
+import static li.strolch.privilege.helper.XmlConstants.*;
+import static li.strolch.privilege.helper.XmlHelper.*;
+
+/**
+ * @author Robert von Burg
+ */
+public class PrivilegeGroupsSaxWriter {
+
+ private final List groups;
+ private final File modelFile;
+
+ public PrivilegeGroupsSaxWriter(List groups, File modelFile) {
+ this.groups = groups;
+ 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(GROUPS);
+
+ List groups = new ArrayList<>(this.groups);
+ groups.sort(comparing(g -> g.name().toLowerCase(Locale.ROOT)));
+ for (Group group : this.groups) {
+
+ // start the user element
+ xmlWriter.writeStartElement(GROUP);
+
+ xmlWriter.writeAttribute(ATTR_NAME, group.name());
+
+ // add all the role elements
+ if (!group.roles().isEmpty()) {
+ xmlWriter.writeStartElement(ROLES);
+ writeStringList(xmlWriter, ROLE, group.roles());
+ xmlWriter.writeEndElement();
+ }
+
+ // add the parameters
+ Map properties = group.getProperties();
+ if (!properties.isEmpty())
+ writeStringMapElement(xmlWriter, properties, PROPERTIES, PROPERTY);
+
+ xmlWriter.writeEndElement();
+ }
+
+ // and now end
+ xmlWriter.writeEndDocument();
+ xmlWriter.flush();
+ }
+ }
+}
diff --git a/privilege/src/main/java/li/strolch/privilege/xml/PrivilegeRolesDomWriter.java b/privilege/src/main/java/li/strolch/privilege/xml/PrivilegeRolesDomWriter.java
deleted file mode 100644
index f88b2e283..000000000
--- a/privilege/src/main/java/li/strolch/privilege/xml/PrivilegeRolesDomWriter.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright 2013 Robert von Burg
- *
- * 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
- */
-public class PrivilegeRolesDomWriter {
-
- private final List roles;
- private final File modelFile;
-
- public PrivilegeRolesDomWriter(List 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);
- }
-}
diff --git a/privilege/src/main/java/li/strolch/privilege/xml/PrivilegeRolesSaxReader.java b/privilege/src/main/java/li/strolch/privilege/xml/PrivilegeRolesSaxReader.java
index 3bf062544..eb333cc23 100644
--- a/privilege/src/main/java/li/strolch/privilege/xml/PrivilegeRolesSaxReader.java
+++ b/privilege/src/main/java/li/strolch/privilege/xml/PrivilegeRolesSaxReader.java
@@ -15,12 +15,7 @@
*/
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.Privilege;
import li.strolch.privilege.model.internal.Role;
import li.strolch.utils.helper.StringHelper;
import org.slf4j.Logger;
@@ -29,6 +24,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
*/
@@ -51,9 +51,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(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(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 +78,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(ROLE)) {
elementParser = this.buildersStack.pop();
- } else if (qName.equals(XmlConstants.XML_PROPERTIES)) {
+ } else if (qName.equals(PROPERTIES)) {
elementParser = this.buildersStack.pop();
}
@@ -109,7 +113,7 @@ public class PrivilegeRolesSaxReader extends DefaultHandler {
private Set denyList;
private Set allowList;
- private Map privileges;
+ private Map privileges;
public RoleParser() {
init();
@@ -134,20 +138,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 ROLE -> this.roleName = attributes.getValue(ATTR_NAME).trim();
+ case PRIVILEGE -> {
+ this.privilegeName = attributes.getValue(ATTR_NAME).trim();
+ this.privilegePolicy = attributes.getValue(ATTR_POLICY).trim();
+ }
+ case ALLOW, DENY, ALL_ALLOWED -> {
+ }
// no-op
- break;
- default:
- throw new IllegalArgumentException("Unhandled tag " + qName);
+ default -> throw new IllegalArgumentException("Unhandled tag " + qName);
}
}
@@ -159,31 +158,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 ALL_ALLOWED -> this.allAllowed = StringHelper.parseBoolean(getText());
+ case ALLOW -> this.allowList.add(getText());
+ case DENY -> this.denyList.add(getText());
+ case PRIVILEGE -> {
+ Privilege privilege = new Privilege(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 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 +195,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(PROPERTY)) {
+ String key = attributes.getValue(ATTR_NAME).trim();
+ String value = attributes.getValue(ATTR_VALUE).trim();
this.parameterMap.put(key, value);
- } else if (!qName.equals(XmlConstants.XML_PROPERTIES)) {
+ } else if (!qName.equals(PROPERTIES)) {
throw new IllegalArgumentException("Unhandled tag " + qName);
}
}
diff --git a/privilege/src/main/java/li/strolch/privilege/xml/PrivilegeRolesSaxWriter.java b/privilege/src/main/java/li/strolch/privilege/xml/PrivilegeRolesSaxWriter.java
new file mode 100644
index 000000000..1645509c1
--- /dev/null
+++ b/privilege/src/main/java/li/strolch/privilege/xml/PrivilegeRolesSaxWriter.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2013 Robert von Burg
+ *
+ * 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.Privilege;
+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
+ */
+public class PrivilegeRolesSaxWriter {
+
+ private final List roles;
+ private final File modelFile;
+
+ public PrivilegeRolesSaxWriter(List 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(ROLES);
+
+ List roles = new ArrayList<>(this.roles);
+ roles.sort(comparing(r -> r.getName().toLowerCase(Locale.ROOT)));
+ for (Role role : roles) {
+
+ // start the role element
+ xmlWriter.writeStartElement(ROLE);
+ xmlWriter.writeAttribute(ATTR_NAME, role.getName());
+
+ List privilegeNames = new ArrayList<>(role.getPrivilegeNames());
+ privilegeNames.sort(null);
+ for (String privilegeName : privilegeNames) {
+ Privilege privilege = role.getPrivilege(privilegeName);
+
+ xmlWriter.writeStartElement(PRIVILEGE);
+ xmlWriter.writeAttribute(ATTR_NAME, privilege.getName());
+ xmlWriter.writeAttribute(ATTR_POLICY, privilege.getPolicy());
+
+ if (privilege.isAllAllowed())
+ writeStringElement(xmlWriter, ALL_ALLOWED, "true");
+ writeStringList(xmlWriter, DENY, privilege.getDenyList());
+ writeStringList(xmlWriter, ALLOW, privilege.getAllowList());
+
+ xmlWriter.writeEndElement();
+ }
+
+ xmlWriter.writeEndElement();
+ }
+
+ // and now end
+ xmlWriter.writeEndDocument();
+ xmlWriter.flush();
+ }
+ }
+}
diff --git a/privilege/src/main/java/li/strolch/privilege/xml/PrivilegeUsersDomWriter.java b/privilege/src/main/java/li/strolch/privilege/xml/PrivilegeUsersDomWriter.java
deleted file mode 100644
index 3621c5d58..000000000
--- a/privilege/src/main/java/li/strolch/privilege/xml/PrivilegeUsersDomWriter.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright 2013 Robert von Burg
- *
- * 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
- */
-public class PrivilegeUsersDomWriter {
-
- private final List users;
- private final File modelFile;
-
- public PrivilegeUsersDomWriter(List 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()));
- }
- }
-}
diff --git a/privilege/src/main/java/li/strolch/privilege/xml/PrivilegeUsersSaxReader.java b/privilege/src/main/java/li/strolch/privilege/xml/PrivilegeUsersSaxReader.java
index 2bfb2c8ff..ae33fff87 100644
--- a/privilege/src/main/java/li/strolch/privilege/xml/PrivilegeUsersSaxReader.java
+++ b/privilege/src/main/java/li/strolch/privilege/xml/PrivilegeUsersSaxReader.java
@@ -15,16 +15,11 @@
*/
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.Group;
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 +27,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
*/
@@ -58,9 +58,13 @@ 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 (qName.equals(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)) {
+ } else if (qName.equals(PROPERTIES)) {
+ if (this.buildersStack.stream().anyMatch(e -> e.getClass().equals(PropertyParser.class)))
+ throw new IllegalArgumentException("Previous Properties not closed!");
this.buildersStack.push(new PropertyParser());
}
@@ -81,9 +85,9 @@ public class PrivilegeUsersSaxReader extends DefaultHandler {
this.buildersStack.peek().endElement(uri, localName, qName);
ElementParser elementParser = null;
- if (qName.equals(XML_USER)) {
+ if (qName.equals(USER)) {
elementParser = this.buildersStack.pop();
- } else if (qName.equals(XML_PROPERTIES)) {
+ } else if (qName.equals(PROPERTIES)) {
elementParser = this.buildersStack.pop();
}
@@ -122,12 +126,14 @@ public class PrivilegeUsersSaxReader extends DefaultHandler {
String lastname;
UserState userState;
Locale locale;
+ final Set groups;
final Set userRoles;
Map parameters;
UserHistory history;
boolean passwordChangeRequested;
public UserParser() {
+ this.groups = new HashSet<>();
this.userRoles = new HashSet<>();
}
@@ -136,15 +142,15 @@ public class PrivilegeUsersSaxReader extends DefaultHandler {
this.text = new StringBuilder();
- if (qName.equals(XML_USER)) {
- this.userId = attributes.getValue(XML_ATTR_USER_ID).trim();
- this.username = attributes.getValue(XML_ATTR_USERNAME).trim();
+ if (qName.equals(USER)) {
+ this.userId = attributes.getValue(ATTR_USER_ID).trim();
+ this.username = attributes.getValue(ATTR_USERNAME).trim();
- String password = attributes.getValue(XML_ATTR_PASSWORD);
- String salt = attributes.getValue(XML_ATTR_SALT);
+ String password = attributes.getValue(ATTR_PASSWORD);
+ String salt = attributes.getValue(ATTR_SALT);
this.passwordCrypt = PasswordCrypt.parse(password, salt);
- } else if (qName.equals(XML_HISTORY)) {
- this.history = new UserHistory();
+ } else if (qName.equals(HISTORY)) {
+ this.history = UserHistory.EMPTY;
}
}
@@ -157,40 +163,45 @@ 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_USER -> {
+ case FIRSTNAME -> this.firstName = getText();
+ case LASTNAME -> this.lastname = getText();
+ case STATE -> this.userState = UserState.valueOf(getText());
+ case LOCALE -> this.locale = Locale.forLanguageTag(getText());
+ case PASSWORD_CHANGE_REQUESTED -> this.passwordChangeRequested = Boolean.parseBoolean(getText());
+ case FIRST_LOGIN -> this.history = this.history.withFirstLogin(ISO8601.parseToZdt(getText()));
+ case LAST_LOGIN -> this.history = this.history.withLastLogin(ISO8601.parseToZdt(getText()));
+ case LAST_PASSWORD_CHANGE ->
+ this.history = this.history.withLastPasswordChange(ISO8601.parseToZdt(getText()));
+ case GROUP -> this.groups.add(getText());
+ case ROLE -> this.userRoles.add(getText());
+ case USER -> {
if (this.history == null)
- this.history = new UserHistory();
+ this.history = UserHistory.EMPTY;
User user = new User(this.userId, this.username, this.passwordCrypt, this.firstName, this.lastname,
- this.userState, this.userRoles, this.locale, this.parameters, this.passwordChangeRequested,
- this.history);
+ this.userState, this.groups, this.userRoles, this.locale, this.parameters,
+ this.passwordChangeRequested, this.history);
logger.info(MessageFormat.format("New User: {0}", user));
String username = caseInsensitiveUsername ? user.getUsername().toLowerCase() : user.getUsername();
users.put(username, user);
}
default -> {
- if (!(qName.equals(XML_ROLES) //
- || qName.equals(XML_PARAMETER) //
- || qName.equals(XML_HISTORY) //
- || qName.equals(XML_PARAMETERS))) {
+ if (!(qName.equals(ROLES) //
+ || qName.equals(GROUPS) //
+ || qName.equals(PARAMETER) //
+ || qName.equals(HISTORY) //
+ || qName.equals(PARAMETERS))) {
throw new IllegalArgumentException("Unhandled tag " + qName);
}
}
}
}
+ private String getText() {
+ return this.text.toString().trim();
+ }
+
@Override
public void notifyChild(ElementParser child) {
if (child instanceof PropertyParser) {
@@ -198,29 +209,4 @@ public class PrivilegeUsersSaxReader extends DefaultHandler {
}
}
}
-
- static class PropertyParser extends ElementParserAdapter {
-
- //
-
- public final Map parameterMap = new HashMap<>();
-
- @Override
- public void startElement(String uri, String localName, String qName, Attributes attributes) {
-
- 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(XML_PROPERTIES)) {
- throw new IllegalArgumentException("Unhandled tag " + qName);
- }
- }
- }
-
- public Map getParameterMap() {
- return this.parameterMap;
- }
- }
}
diff --git a/privilege/src/main/java/li/strolch/privilege/xml/PrivilegeUsersSaxWriter.java b/privilege/src/main/java/li/strolch/privilege/xml/PrivilegeUsersSaxWriter.java
new file mode 100644
index 000000000..0780d1490
--- /dev/null
+++ b/privilege/src/main/java/li/strolch/privilege/xml/PrivilegeUsersSaxWriter.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2013 Robert von Burg
+ *
+ * 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
+ */
+public class PrivilegeUsersSaxWriter {
+
+ private final List users;
+ private final File modelFile;
+
+ public PrivilegeUsersSaxWriter(List users, File modelFile) {
+ this.users = users;
+ 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(USERS);
+
+ List 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(USER);
+
+ xmlWriter.writeAttribute(ATTR_USER_ID, user.getUserId());
+ xmlWriter.writeAttribute(ATTR_USERNAME, user.getUsername());
+ writePassword(user, xmlWriter);
+
+ // add first name element
+ if (isNotEmpty(user.getFirstname()))
+ writeStringElement(xmlWriter, FIRSTNAME, user.getFirstname());
+
+ // add last name element
+ if (isNotEmpty(user.getLastname()))
+ writeStringElement(xmlWriter, LASTNAME, user.getLastname());
+
+ // add state element
+ writeStringElement(xmlWriter, STATE, user.getUserState().toString());
+
+ // add locale element
+ writeStringElement(xmlWriter, LOCALE, user.getLocale().toLanguageTag());
+
+ // add password change requested element
+ if (user.isPasswordChangeRequested())
+ writeStringElement(xmlWriter, PASSWORD_CHANGE_REQUESTED, "true");
+
+ // add all the group elements
+ if (!user.getGroups().isEmpty()) {
+ xmlWriter.writeStartElement(GROUPS);
+ writeStringList(xmlWriter, GROUP, user.getGroups());
+ xmlWriter.writeEndElement();
+ }
+
+ // add all the role elements
+ if (!user.getRoles().isEmpty()) {
+ xmlWriter.writeStartElement(ROLES);
+ writeStringList(xmlWriter, ROLE, user.getRoles());
+ xmlWriter.writeEndElement();
+ }
+
+ // add the parameters
+ Map properties = user.getProperties();
+ if (!properties.isEmpty())
+ writeStringMapElement(xmlWriter, properties, PROPERTIES, PROPERTY);
+
+ if (!user.isHistoryEmpty()) {
+ UserHistory history = user.getHistory();
+ xmlWriter.writeStartElement(HISTORY);
+
+ if (!history.isFirstLoginEmpty())
+ writeStringElement(xmlWriter, FIRST_LOGIN, ISO8601.toString(history.getFirstLogin()));
+
+ if (!history.isLastLoginEmpty())
+ writeStringElement(xmlWriter, LAST_LOGIN, ISO8601.toString(history.getLastLogin()));
+
+ if (!history.isLastPasswordChangeEmpty())
+ writeStringElement(xmlWriter, 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(ATTR_PASSWORD, passwordString);
+ } else {
+ if (passwordCrypt.password() != null)
+ xmlStreamWriter.writeAttribute(ATTR_PASSWORD, toHexString(passwordCrypt.password()));
+ if (passwordCrypt.salt() != null)
+ xmlStreamWriter.writeAttribute(ATTR_SALT, toHexString(passwordCrypt.salt()));
+ }
+ }
+}
diff --git a/privilege/src/main/java/li/strolch/privilege/xml/PropertyParser.java b/privilege/src/main/java/li/strolch/privilege/xml/PropertyParser.java
new file mode 100644
index 000000000..a0ea1d2dc
--- /dev/null
+++ b/privilege/src/main/java/li/strolch/privilege/xml/PropertyParser.java
@@ -0,0 +1,33 @@
+package li.strolch.privilege.xml;
+
+import org.xml.sax.Attributes;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static li.strolch.privilege.helper.XmlConstants.*;
+
+class PropertyParser extends ElementParserAdapter {
+
+ //
+
+ public final Map parameterMap = new HashMap<>();
+
+ @Override
+ public void startElement(String uri, String localName, String qName, Attributes attributes) {
+
+ if (qName.equals(PROPERTY)) {
+ String key = attributes.getValue(ATTR_NAME).trim();
+ String value = attributes.getValue(ATTR_VALUE).trim();
+ this.parameterMap.put(key, value);
+ } else {
+ if (!qName.equals(PROPERTIES)) {
+ throw new IllegalArgumentException("Unhandled tag " + qName);
+ }
+ }
+ }
+
+ public Map getParameterMap() {
+ return this.parameterMap;
+ }
+}
diff --git a/privilege/src/main/resources/PrivilegeMessages.properties b/privilege/src/main/resources/PrivilegeMessages.properties
index 4b7b3a77f..c4507b136 100644
--- a/privilege/src/main/resources/PrivilegeMessages.properties
+++ b/privilege/src/main/resources/PrivilegeMessages.properties
@@ -11,6 +11,7 @@ Privilege.privilegeNameEmpty=The PrivilegeName for the Restrictable is null or e
Privilege.privilegeNull=Privilege may not be null\!
Privilege.restrictableNull=Restrictable may not be null\!
Privilege.noprivilege=No Privilege exists with name {0}
+Privilege.noprivilege.group=User {0} does not belong to group {1}
Privilege.noprivilege.role=User {0} does not have the role {1}
Privilege.noprivilege.user=User {0} does not have the privilege {1}
Privilege.roleAccessPrivilege.unknownPrivilege=Unhandled privilege {0} for policy {1}
diff --git a/privilege/src/test/java/li/strolch/privilege/test/AbstractPrivilegeTest.java b/privilege/src/test/java/li/strolch/privilege/test/AbstractPrivilegeTest.java
index d6f6b5b87..bb00bd2e4 100644
--- a/privilege/src/test/java/li/strolch/privilege/test/AbstractPrivilegeTest.java
+++ b/privilege/src/test/java/li/strolch/privilege/test/AbstractPrivilegeTest.java
@@ -1,12 +1,5 @@
package li.strolch.privilege.test;
-import static org.junit.Assert.assertNotNull;
-
-import java.io.File;
-import java.nio.file.Files;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.handler.PrivilegeHandler;
import li.strolch.privilege.helper.PrivilegeInitializer;
@@ -18,6 +11,13 @@ import org.junit.BeforeClass;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.io.File;
+import java.nio.file.Files;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+
+import static org.junit.Assert.assertNotNull;
+
public class AbstractPrivilegeTest {
protected static final Logger logger = LoggerFactory.getLogger(AbstractPrivilegeTest.class);
@@ -57,13 +57,14 @@ public class AbstractPrivilegeTest {
}
}
- protected static void prepareConfigs(String dst, String configFilename, String usersFilename,
+ protected static void prepareConfigs(String dst, String configFilename, String usersFilename, String groupsFilename,
String rolesFilename) {
try {
File configPath = new File("src/test/resources/config");
File privilegeConfigFile = new File(configPath, configFilename);
File privilegeUsersFile = new File(configPath, usersFilename);
+ File privilegeGroupsFile = new File(configPath, groupsFilename);
File privilegeRolesFile = new File(configPath, rolesFilename);
File targetPath = new File("target/" + dst);
@@ -72,6 +73,7 @@ public class AbstractPrivilegeTest {
File dstConfig = new File(targetPath, configFilename);
File dstUsers = new File(targetPath, usersFilename);
+ File dstGroups = new File(targetPath, groupsFilename);
File dstRoles = new File(targetPath, rolesFilename);
// write config
@@ -81,6 +83,7 @@ public class AbstractPrivilegeTest {
// copy model
Files.copy(privilegeUsersFile.toPath(), dstUsers.toPath());
+ Files.copy(privilegeGroupsFile.toPath(), dstGroups.toPath());
Files.copy(privilegeRolesFile.toPath(), dstRoles.toPath());
} catch (Exception e) {
diff --git a/privilege/src/test/java/li/strolch/privilege/test/CryptTest.java b/privilege/src/test/java/li/strolch/privilege/test/CryptTest.java
index e13c7e1d0..377869432 100644
--- a/privilege/src/test/java/li/strolch/privilege/test/CryptTest.java
+++ b/privilege/src/test/java/li/strolch/privilege/test/CryptTest.java
@@ -20,9 +20,9 @@ public class CryptTest {
@BeforeClass
public static void beforeClass() {
Map parameterMap = new HashMap<>();
- parameterMap.put(XML_PARAM_HASH_ALGORITHM, DEFAULT_ALGORITHM);
- parameterMap.put(XML_PARAM_HASH_ITERATIONS, "" + DEFAULT_SMALL_ITERATIONS);
- parameterMap.put(XML_PARAM_HASH_KEY_LENGTH, "" + DEFAULT_KEY_LENGTH);
+ parameterMap.put(PARAM_HASH_ALGORITHM, DEFAULT_ALGORITHM);
+ parameterMap.put(PARAM_HASH_ITERATIONS, "" + DEFAULT_SMALL_ITERATIONS);
+ parameterMap.put(PARAM_HASH_KEY_LENGTH, "" + DEFAULT_KEY_LENGTH);
encryptionHandler = new DefaultEncryptionHandler();
encryptionHandler.initialize(parameterMap);
@@ -41,7 +41,7 @@ public class CryptTest {
PasswordCrypt passwordCrypt = encryptionHandler.hashPassword(password, salt, "PBKDF2WithHmacSHA512", 100000,
256);
- assertArrayEquals(passwordCrypt.getPassword(), parsedCryptHash.getPassword());
+ assertArrayEquals(passwordCrypt.password(), parsedCryptHash.password());
}
@Test
@@ -53,9 +53,9 @@ public class CryptTest {
assertNotNull(parsedCryptHash);
char[] password = "admin".toCharArray();
- PasswordCrypt passwordCrypt = encryptionHandler.hashPassword(password, parsedCryptHash.getSalt(),
+ PasswordCrypt passwordCrypt = encryptionHandler.hashPassword(password, parsedCryptHash.salt(),
"PBKDF2WithHmacSHA512", 100000, 256);
- assertArrayEquals(passwordCrypt.getPassword(), parsedCryptHash.getPassword());
+ assertArrayEquals(passwordCrypt.password(), parsedCryptHash.password());
}
}
diff --git a/privilege/src/test/java/li/strolch/privilege/test/PersistSessionsTest.java b/privilege/src/test/java/li/strolch/privilege/test/PersistSessionsTest.java
index ad8ac6b27..5029abb88 100644
--- a/privilege/src/test/java/li/strolch/privilege/test/PersistSessionsTest.java
+++ b/privilege/src/test/java/li/strolch/privilege/test/PersistSessionsTest.java
@@ -16,7 +16,7 @@ public class PersistSessionsTest extends AbstractPrivilegeTest {
public static void init() {
removeConfigs(PersistSessionsTest.class.getSimpleName());
prepareConfigs(PersistSessionsTest.class.getSimpleName(), "PrivilegeConfig.xml", "PrivilegeUsers.xml",
- "PrivilegeRoles.xml");
+ "PrivilegeGroups.xml", "PrivilegeRoles.xml");
}
@AfterClass
diff --git a/privilege/src/test/java/li/strolch/privilege/test/PrivilegeConflictMergeTest.java b/privilege/src/test/java/li/strolch/privilege/test/PrivilegeConflictMergeTest.java
index 6fe6ed34c..68152e9bc 100644
--- a/privilege/src/test/java/li/strolch/privilege/test/PrivilegeConflictMergeTest.java
+++ b/privilege/src/test/java/li/strolch/privilege/test/PrivilegeConflictMergeTest.java
@@ -15,14 +15,16 @@
*/
package li.strolch.privilege.test;
-import static org.junit.Assert.*;
-
-import li.strolch.privilege.model.IPrivilege;
+import li.strolch.privilege.model.Privilege;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
+import java.util.Set;
+
+import static org.junit.Assert.*;
+
/**
* @author Robert von Burg
*/
@@ -32,7 +34,7 @@ public class PrivilegeConflictMergeTest extends AbstractPrivilegeTest {
public static void init() {
removeConfigs(PrivilegeConflictMergeTest.class.getSimpleName());
prepareConfigs(PrivilegeConflictMergeTest.class.getSimpleName(), "PrivilegeConfigMerge.xml",
- "PrivilegeUsersMerge.xml", "PrivilegeRolesMerge.xml");
+ "PrivilegeUsersMerge.xml", "PrivilegeGroupsMerge.xml", "PrivilegeRolesMerge.xml");
}
@AfterClass
@@ -49,7 +51,16 @@ public class PrivilegeConflictMergeTest extends AbstractPrivilegeTest {
public void shouldMergePrivileges1() {
try {
login("userA", "admin".toCharArray());
- IPrivilege privilege = this.ctx.getPrivilege("Foo");
+ assertEquals(Set.of(), this.ctx.getUserRep().getGroups());
+ assertFalse(this.ctx.hasGroup("GroupA1"));
+ assertFalse(this.ctx.hasGroup("GroupA2"));
+ assertEquals(Set.of("RoleA1", "RoleA2"), this.ctx.getUserRep().getRoles());
+ assertTrue(this.ctx.hasRole("RoleA1"));
+ assertTrue(this.ctx.hasRole("RoleA2"));
+ assertFalse(this.ctx.hasRole("RoleB2"));
+ assertNull(this.ctx.getUserRep().getLocation());
+ assertEquals(Set.of(), this.ctx.getUserRep().getPropertyKeySet());
+ Privilege privilege = this.ctx.getPrivilege("Foo");
assertTrue(privilege.isAllAllowed());
assertTrue(privilege.getAllowList().isEmpty());
assertTrue(privilege.getDenyList().isEmpty());
@@ -63,7 +74,16 @@ public class PrivilegeConflictMergeTest extends AbstractPrivilegeTest {
public void shouldMergePrivileges2() {
try {
login("userB", "admin".toCharArray());
- IPrivilege privilege = this.ctx.getPrivilege("Bar");
+ assertEquals(Set.of(), this.ctx.getUserRep().getGroups());
+ assertFalse(this.ctx.hasGroup("GroupB1"));
+ assertFalse(this.ctx.hasGroup("GroupB2"));
+ assertEquals(Set.of("RoleB1", "RoleB2"), this.ctx.getUserRep().getRoles());
+ assertTrue(this.ctx.hasRole("RoleB1"));
+ assertTrue(this.ctx.hasRole("RoleB2"));
+ assertFalse(this.ctx.hasRole("RoleA2"));
+ assertNull(this.ctx.getUserRep().getLocation());
+ assertEquals(Set.of(), this.ctx.getUserRep().getPropertyKeySet());
+ Privilege privilege = this.ctx.getPrivilege("Bar");
assertFalse(privilege.isAllAllowed());
assertEquals(2, privilege.getAllowList().size());
assertEquals(2, privilege.getDenyList().size());
@@ -71,4 +91,53 @@ public class PrivilegeConflictMergeTest extends AbstractPrivilegeTest {
logout();
}
}
+
+ @Test
+ public void shouldMergePrivileges3() {
+ try {
+ login("userC", "admin".toCharArray());
+ assertEquals(Set.of("GroupA1", "GroupA2"), this.ctx.getUserRep().getGroups());
+ assertTrue(this.ctx.hasGroup("GroupA1"));
+ assertTrue(this.ctx.hasGroup("GroupA2"));
+ assertFalse(this.ctx.hasGroup("GroupB2"));
+ assertEquals(Set.of("RoleA1", "RoleA2"), this.ctx.getUserRep().getRoles());
+ assertTrue(this.ctx.hasRole("RoleA1"));
+ assertTrue(this.ctx.hasRole("RoleA2"));
+ assertFalse(this.ctx.hasRole("RoleB2"));
+ assertEquals("LocationA2", this.ctx.getUserRep().getLocation());
+ assertEquals(Set.of("location"), this.ctx.getUserRep().getPropertyKeySet());
+ Privilege privilege = this.ctx.getPrivilege("Foo");
+ assertTrue(privilege.isAllAllowed());
+ assertTrue(privilege.getAllowList().isEmpty());
+ assertTrue(privilege.getDenyList().isEmpty());
+
+ } finally {
+ logout();
+ }
+ }
+
+ @Test
+ public void shouldMergePrivileges4() {
+ try {
+ login("userD", "admin".toCharArray());
+ assertEquals(Set.of("GroupB1", "GroupB2"), this.ctx.getUserRep().getGroups());
+ assertTrue(this.ctx.hasGroup("GroupB1"));
+ assertTrue(this.ctx.hasGroup("GroupB2"));
+ assertFalse(this.ctx.hasGroup("GroupA2"));
+ assertEquals(Set.of("RoleB1", "RoleB2"), this.ctx.getUserRep().getRoles());
+ assertTrue(this.ctx.hasRole("RoleB1"));
+ assertTrue(this.ctx.hasRole("RoleB2"));
+ assertFalse(this.ctx.hasRole("RoleA2"));
+ assertEquals("LocationB2", this.ctx.getUserRep().getLocation());
+ assertEquals(Set.of("location"), this.ctx.getUserRep().getPropertyKeySet());
+ Privilege privilege = this.ctx.getPrivilege("Bar");
+ assertFalse(privilege.isAllAllowed());
+ assertEquals(2, privilege.getAllowList().size());
+ assertEquals(2, privilege.getDenyList().size());
+ assertEquals(Set.of("allow1", "allow2"), privilege.getAllowList());
+ assertEquals(Set.of("deny1", "deny2"), privilege.getDenyList());
+ } finally {
+ logout();
+ }
+ }
}
diff --git a/privilege/src/test/java/li/strolch/privilege/test/PrivilegeTest.java b/privilege/src/test/java/li/strolch/privilege/test/PrivilegeTest.java
index e285de9d2..354532f97 100644
--- a/privilege/src/test/java/li/strolch/privilege/test/PrivilegeTest.java
+++ b/privilege/src/test/java/li/strolch/privilege/test/PrivilegeTest.java
@@ -15,12 +15,6 @@
*/
package li.strolch.privilege.test;
-import static org.hamcrest.Matchers.containsString;
-import static org.junit.Assert.*;
-
-import java.text.MessageFormat;
-import java.util.*;
-
import li.strolch.privilege.base.AccessDeniedException;
import li.strolch.privilege.base.InvalidCredentialsException;
import li.strolch.privilege.base.PrivilegeException;
@@ -41,9 +35,15 @@ import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.text.MessageFormat;
+import java.util.*;
+
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.*;
+
/**
* JUnit for performing Privilege tests. This JUnit is by no means complete, but checks the bare minimum.br />
- *
+ *
* TODO add more tests, especially with deny and allow lists
*
* @author Robert von Burg
@@ -77,12 +77,12 @@ public class PrivilegeTest extends AbstractPrivilegeTest {
public static void init() {
removeConfigs(PrivilegeTest.class.getSimpleName());
prepareConfigs(PrivilegeTest.class.getSimpleName(), "PrivilegeConfig.xml", "PrivilegeUsers.xml",
- "PrivilegeRoles.xml");
+ "PrivilegeGroups.xml", "PrivilegeRoles.xml");
}
@AfterClass
public static void destroy() {
- removeConfigs(PrivilegeTest.class.getSimpleName());
+ //removeConfigs(PrivilegeTest.class.getSimpleName());
}
@Before
@@ -137,7 +137,7 @@ public class PrivilegeTest extends AbstractPrivilegeTest {
try {
login(ADMIN, ArraysHelper.copyOf(PASS_ADMIN));
- RoleRep roleRep = new RoleRep(ROLE_TEMP, new ArrayList<>());
+ RoleRep roleRep = new RoleRep(ROLE_TEMP, Map.of());
Certificate certificate = this.ctx.getCertificate();
this.privilegeHandler.addRole(certificate, roleRep);
@@ -209,7 +209,9 @@ public class PrivilegeTest extends AbstractPrivilegeTest {
}
});
MatcherAssert.assertThat(exception.getMessage(), containsString(
- "User system_admin2 does not have the privilege li.strolch.privilege.handler.SystemAction with value li.strolch.privilege.test.model.TestSystemUserActionDeny needed for Restrictable li.strolch.privilege.test.model.TestSystemUserActionDeny"));
+ "User system_admin2 does not have the privilege li.strolch.privilege.handler.SystemAction with value " +
+ "li.strolch.privilege.test.model.TestSystemUserActionDeny needed for Restrictable " +
+ "li.strolch.privilege.test.model.TestSystemUserActionDeny"));
}
/**
@@ -251,9 +253,12 @@ public class PrivilegeTest extends AbstractPrivilegeTest {
assertNotEquals("The", user.getFirstname());
assertNotEquals("Admin", user.getLastname());
- // let's add a new user bob
- UserRep userRep = new UserRep(null, ADMIN, "The", "Admin", null, null, null, null, null);
- this.privilegeHandler.updateUser(certificate, userRep);
+ // set new name
+ user.setFirstname("The");
+ user.setLastname("Admin");
+
+ // update user
+ this.privilegeHandler.updateUser(certificate, user, null);
user = this.privilegeHandler.getUser(certificate, ADMIN);
assertEquals("The", user.getFirstname());
@@ -273,8 +278,9 @@ public class PrivilegeTest extends AbstractPrivilegeTest {
Certificate certificate = this.ctx.getCertificate();
// let's add a new user bob
- UserRep userRep = new UserRep(null, BOB, null, null, null, null, null, null, null);
- this.privilegeHandler.updateUser(certificate, userRep);
+ UserRep userRep = new UserRep(BOB, BOB, "Bob", "Anderson", UserState.ENABLED,
+ Set.of("AppUserLocationA"), null, null, null, null);
+ this.privilegeHandler.updateUser(certificate, userRep, null);
} finally {
logout();
}
@@ -282,25 +288,6 @@ public class PrivilegeTest extends AbstractPrivilegeTest {
MatcherAssert.assertThat(exception.getMessage(), containsString("User bob does not exist"));
}
- @Test
- public void shouldFailUpdateAdminNoChanges() {
- PrivilegeException exception = assertThrows(PrivilegeException.class, () -> {
- try {
- login(ADMIN, ArraysHelper.copyOf(PASS_ADMIN));
-
- Certificate certificate = this.ctx.getCertificate();
-
- // let's add a new user bob
- UserRep userRep = new UserRep(null, ADMIN, null, null, null, null, null, null, null);
- this.privilegeHandler.updateUser(certificate, userRep);
- } finally {
- logout();
- }
- });
- MatcherAssert.assertThat(exception.getMessage(),
- containsString("All updateable fields are empty for update of user admin"));
- }
-
@Test
public void shouldQueryUsers() {
try {
@@ -308,7 +295,24 @@ public class PrivilegeTest extends AbstractPrivilegeTest {
Certificate certificate = this.ctx.getCertificate();
- UserRep selectorRep = new UserRep(null, ADMIN, null, null, null, null, null, null, null);
+ UserRep selectorRep = new UserRep(null, ADMIN, null, null, null, null, null, null, null, null);
+ List users = this.privilegeHandler.queryUsers(certificate, selectorRep);
+ assertEquals(1, users.size());
+ assertEquals(ADMIN, users.get(0).getUsername());
+
+ } finally {
+ logout();
+ }
+ }
+
+ @Test
+ public void shouldQueryUsersByGroups() {
+ try {
+ login(ADMIN, ArraysHelper.copyOf(PASS_ADMIN));
+
+ Certificate certificate = this.ctx.getCertificate();
+
+ UserRep selectorRep = new UserRep(null, null, null, null, null, Set.of("GroupA"), null, null, null, null);
List users = this.privilegeHandler.queryUsers(certificate, selectorRep);
assertEquals(1, users.size());
assertEquals(ADMIN, users.get(0).getUsername());
@@ -325,8 +329,8 @@ public class PrivilegeTest extends AbstractPrivilegeTest {
Certificate certificate = this.ctx.getCertificate();
- UserRep selectorRep = new UserRep(null, null, null, null, null,
- new HashSet<>(Collections.singletonList("PrivilegeAdmin")), null, null, null);
+ UserRep selectorRep = new UserRep(null, null, null, null, null, null, Set.of("PrivilegeAdmin"), null, null,
+ null);
List users = this.privilegeHandler.queryUsers(certificate, selectorRep);
assertEquals(2, users.size());
assertEquals(ADMIN, users.get(0).getUsername());
@@ -344,7 +348,7 @@ public class PrivilegeTest extends AbstractPrivilegeTest {
Certificate certificate = this.ctx.getCertificate();
UserRep selectorRep = new UserRep(null, null, null, null, null,
- new HashSet<>(Collections.singletonList(ROLE_TEMP)), null, null, null);
+ new HashSet<>(Collections.singletonList(ROLE_TEMP)), null, null, null, null);
List users = this.privilegeHandler.queryUsers(certificate, selectorRep);
assertEquals(0, users.size());
@@ -360,8 +364,10 @@ public class PrivilegeTest extends AbstractPrivilegeTest {
login(ADMIN, ArraysHelper.copyOf(PASS_ADMIN));
Certificate certificate = this.ctx.getCertificate();
PrivilegeRep privilegeRep = new PrivilegeRep(PrivilegeHandler.PRIVILEGE_ACTION, "DefaultPrivilege",
- true, Collections.emptySet(), Collections.emptySet());
- this.privilegeHandler.addOrReplacePrivilegeOnRole(certificate, ROLE_APP_USER, privilegeRep);
+ true, Set.of(), Set.of());
+ RoleRep role = this.privilegeHandler.getRole(certificate, ROLE_APP_USER);
+ role.addPrivilege(privilegeRep);
+ this.privilegeHandler.replaceRole(certificate, role);
} finally {
logout();
}
@@ -375,8 +381,10 @@ public class PrivilegeTest extends AbstractPrivilegeTest {
try {
login(ADMIN, ArraysHelper.copyOf(PASS_ADMIN));
Certificate certificate = this.ctx.getCertificate();
- this.privilegeHandler.addRoleToUser(certificate, ADMIN, ROLE_MY);
- this.privilegeHandler.addRoleToUser(certificate, ADMIN, ROLE_MY2);
+ UserRep user = this.privilegeHandler.getUser(certificate, ADMIN);
+ user.addRole(ROLE_MY);
+ user.addRole(ROLE_MY2);
+ this.privilegeHandler.updateUser(certificate, user, null);
} finally {
logout();
}
@@ -540,15 +548,21 @@ public class PrivilegeTest extends AbstractPrivilegeTest {
login(ADMIN, ArraysHelper.copyOf(PASS_ADMIN));
PrivilegeRep passwordRep = new PrivilegeRep(PrivilegeHandler.PRIVILEGE_SET_USER_PASSWORD,
- PRIVILEGE_USER_ACCESS, false, Collections.emptySet(), Collections.emptySet());
+ PRIVILEGE_USER_ACCESS, false, Set.of(), Set.of());
PrivilegeRep localeRep = new PrivilegeRep(PrivilegeHandler.PRIVILEGE_SET_USER_LOCALE, PRIVILEGE_USER_ACCESS,
- false, Collections.emptySet(), Collections.emptySet());
+ false, Set.of(), Set.of());
- RoleRep roleRep = new RoleRep(ROLE_CHANGE_PW, Arrays.asList(passwordRep, localeRep));
+ Map privileges = new HashMap<>();
+ privileges.put(passwordRep.getName(), passwordRep);
+ privileges.put(localeRep.getName(), localeRep);
+ RoleRep roleRep = new RoleRep(ROLE_CHANGE_PW, privileges);
Certificate certificate = this.ctx.getCertificate();
this.privilegeHandler.addRole(certificate, roleRep);
- this.privilegeHandler.addRoleToUser(certificate, TED, ROLE_CHANGE_PW);
+
+ UserRep ted = this.privilegeHandler.getUser(certificate, TED);
+ ted.addRole(ROLE_CHANGE_PW);
+ this.privilegeHandler.updateUser(certificate, ted, null);
logger.info("Added " + ROLE_CHANGE_PW + " to " + TED);
this.privilegeHandler.persist(certificate);
} finally {
@@ -574,7 +588,9 @@ public class PrivilegeTest extends AbstractPrivilegeTest {
// testAddAppRoleToBob
login(ADMIN, ArraysHelper.copyOf(PASS_ADMIN));
Certificate certificate = this.ctx.getCertificate();
- this.privilegeHandler.addRoleToUser(certificate, BOB, ROLE_APP_USER);
+ UserRep bob = this.privilegeHandler.getUser(certificate, BOB);
+ bob.addRole(ROLE_APP_USER);
+ this.privilegeHandler.updateUser(certificate, bob, null);
logger.info("Added " + ROLE_APP_USER + " to " + BOB);
this.privilegeHandler.persist(certificate);
} finally {
@@ -593,7 +609,10 @@ public class PrivilegeTest extends AbstractPrivilegeTest {
this.ctx.validateAction(restrictable);
fail("Should fail as bob does not have role app");
} catch (AccessDeniedException e) {
- String msg = "User bob does not have the privilege li.strolch.privilege.test.model.TestRestrictable needed for Restrictable li.strolch.privilege.test.model.TestRestrictable and value li.strolch.privilege.test.model.TestRestrictable";
+ String msg =
+ "User bob does not have the privilege li.strolch.privilege.test.model.TestRestrictable needed for " +
+ "Restrictable li.strolch.privilege.test.model.TestRestrictable and value " +
+ "li.strolch.privilege.test.model.TestRestrictable";
assertEquals(msg, e.getLocalizedMessage());
} finally {
logout();
@@ -656,7 +675,8 @@ public class PrivilegeTest extends AbstractPrivilegeTest {
// let's add a new user ted
HashSet roles = new HashSet<>();
roles.add(ROLE_USER);
- userRep = new UserRep(null, TED, "Ted", "Newman", UserState.ENABLED, roles, null, new HashMap<>(), null);
+ userRep = new UserRep(null, TED, "Ted", "Newman", UserState.ENABLED, Set.of(), roles, null, new HashMap<>(),
+ null);
Certificate certificate = this.ctx.getCertificate();
this.privilegeHandler.addUser(certificate, userRep, null);
logger.info("Added user " + TED);
@@ -671,7 +691,9 @@ public class PrivilegeTest extends AbstractPrivilegeTest {
// testAddAdminRoleToBob
login(ADMIN, ArraysHelper.copyOf(PASS_ADMIN));
Certificate certificate = this.ctx.getCertificate();
- this.privilegeHandler.addRoleToUser(certificate, BOB, ROLE_PRIVILEGE_ADMIN);
+ UserRep bob = this.privilegeHandler.getUser(certificate, BOB);
+ bob.addRole(ROLE_PRIVILEGE_ADMIN);
+ this.privilegeHandler.updateUser(certificate, bob, null);
logger.info("Added " + ROLE_PRIVILEGE_ADMIN + " to " + ADMIN);
this.privilegeHandler.persist(certificate);
} finally {
@@ -688,14 +710,14 @@ public class PrivilegeTest extends AbstractPrivilegeTest {
// auth as Bob
login(BOB, ArraysHelper.copyOf(PASS_BOB));
// let's add a new user Ted
- userRep = new UserRep("1", TED, "Ted", "And then Some", UserState.NEW, new HashSet<>(), null,
+ userRep = new UserRep("1", TED, "Ted", "And then Some", UserState.NEW, Set.of(), Set.of(), null,
new HashMap<>(), null);
certificate = this.ctx.getCertificate();
this.privilegeHandler.addUser(certificate, userRep, null);
fail("User bob may not add a user as bob does not have admin rights!");
} catch (PrivilegeException e) {
- String msg = MessageFormat.format(PrivilegeMessages.getString("Privilege.noprivilege.user"),
- BOB, PrivilegeHandler.PRIVILEGE_ADD_USER);
+ String msg = MessageFormat.format(PrivilegeMessages.getString("Privilege.noprivilege.user"), BOB,
+ PrivilegeHandler.PRIVILEGE_ADD_USER);
assertEquals(msg, e.getMessage());
} finally {
logout();
@@ -716,7 +738,9 @@ public class PrivilegeTest extends AbstractPrivilegeTest {
// testAddRoleUserToBob
login(ADMIN, ArraysHelper.copyOf(PASS_ADMIN));
Certificate certificate = this.ctx.getCertificate();
- this.privilegeHandler.addRoleToUser(certificate, BOB, ROLE_USER);
+ UserRep bob = this.privilegeHandler.getUser(certificate, BOB);
+ bob.addRole(ROLE_USER);
+ this.privilegeHandler.updateUser(certificate, bob, null);
this.privilegeHandler.persist(certificate);
logout();
} finally {
@@ -728,7 +752,7 @@ public class PrivilegeTest extends AbstractPrivilegeTest {
try {
// add role user
login(ADMIN, ArraysHelper.copyOf(PASS_ADMIN));
- RoleRep roleRep = new RoleRep(ROLE_USER, new ArrayList<>());
+ RoleRep roleRep = new RoleRep(ROLE_USER, Map.of());
Certificate certificate = this.ctx.getCertificate();
this.privilegeHandler.addRole(certificate, roleRep);
this.privilegeHandler.persist(certificate);
@@ -768,8 +792,8 @@ public class PrivilegeTest extends AbstractPrivilegeTest {
login(ADMIN, ArraysHelper.copyOf(PASS_ADMIN));
// let's add a new user bob
- UserRep userRep = new UserRep(null, BOB, "Bob", "Newman", UserState.NEW,
- new HashSet<>(Collections.singletonList(ROLE_MY)), null, new HashMap<>(), null);
+ UserRep userRep = new UserRep(null, BOB, "Bob", "Newman", UserState.NEW, Set.of(), Set.of(ROLE_MY), null,
+ new HashMap<>(), null);
Certificate certificate = this.ctx.getCertificate();
this.privilegeHandler.addUser(certificate, userRep, null);
logger.info("Added user " + BOB);
diff --git a/privilege/src/test/java/li/strolch/privilege/test/SsoHandlerTest.java b/privilege/src/test/java/li/strolch/privilege/test/SsoHandlerTest.java
index 9c9dacd92..36a7b468e 100644
--- a/privilege/src/test/java/li/strolch/privilege/test/SsoHandlerTest.java
+++ b/privilege/src/test/java/li/strolch/privilege/test/SsoHandlerTest.java
@@ -17,7 +17,7 @@ public class SsoHandlerTest extends AbstractPrivilegeTest {
public static void init() {
removeConfigs(SsoHandlerTest.class.getSimpleName());
prepareConfigs(SsoHandlerTest.class.getSimpleName(), "PrivilegeConfig.xml", "PrivilegeUsers.xml",
- "PrivilegeRoles.xml");
+ "PrivilegeGroups.xml", "PrivilegeRoles.xml");
}
@AfterClass
@@ -39,6 +39,7 @@ public class SsoHandlerTest extends AbstractPrivilegeTest {
data.put("username", "admin");
data.put("firstName", "Admin");
data.put("lastName", "Istrator");
+ data.put("groups", "AppUserLocationA");
data.put("roles", "PrivilegeAdmin, AppUser");
// auth
diff --git a/privilege/src/test/java/li/strolch/privilege/test/WriteRolesFileHelperTest.java b/privilege/src/test/java/li/strolch/privilege/test/WriteRolesFileHelperTest.java
index 5a63375a4..15859469e 100644
--- a/privilege/src/test/java/li/strolch/privilege/test/WriteRolesFileHelperTest.java
+++ b/privilege/src/test/java/li/strolch/privilege/test/WriteRolesFileHelperTest.java
@@ -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());
}
diff --git a/privilege/src/test/java/li/strolch/privilege/test/XmlTest.java b/privilege/src/test/java/li/strolch/privilege/test/XmlTest.java
index e8c1a4745..06f09948d 100644
--- a/privilege/src/test/java/li/strolch/privilege/test/XmlTest.java
+++ b/privilege/src/test/java/li/strolch/privilege/test/XmlTest.java
@@ -15,11 +15,8 @@
*/
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.model.IPrivilege;
+import li.strolch.privilege.handler.*;
+import li.strolch.privilege.model.Privilege;
import li.strolch.privilege.model.UserState;
import li.strolch.privilege.model.internal.*;
import li.strolch.privilege.test.model.DummySsoHandler;
@@ -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;
@@ -80,6 +80,11 @@ public class XmlTest {
throw new RuntimeException("Tmp still exists and can not be deleted at " + tmpFile.getAbsolutePath());
}
+ tmpFile = new File(TARGET_TEST + "PrivilegeGroupsTest.xml");
+ if (tmpFile.exists() && !tmpFile.delete()) {
+ throw new RuntimeException("Tmp still exists and can not be deleted at " + tmpFile.getAbsolutePath());
+ }
+
tmpFile = new File(TARGET_TEST + "PrivilegeRolesTest.xml");
if (tmpFile.exists() && !tmpFile.delete()) {
throw new RuntimeException("Tmp still exists and can not be deleted at " + tmpFile.getAbsolutePath());
@@ -115,7 +120,7 @@ public class XmlTest {
}
@Test
- public void canWriteConfig() {
+ public void canWriteConfig() throws XMLStreamException, IOException {
Map parameterMap = new HashMap<>();
Map encryptionHandlerParameterMap = new HashMap<>();
@@ -128,6 +133,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 +144,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 = """
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ """;
+
+ assertEquals(expected, Files.readString(configFile.toPath()));
}
@Test
@@ -166,12 +199,13 @@ public class XmlTest {
assertEquals("1", admin.getUserId());
assertEquals("admin", admin.getUsername());
assertEquals("cb69962946617da006a2f95776d78b49e5ec7941d2bdb2d25cdb05f957f64344",
- StringHelper.toHexString(admin.getPasswordCrypt().getPassword()));
- assertEquals("61646d696e", StringHelper.toHexString(admin.getPasswordCrypt().getSalt()));
+ StringHelper.toHexString(admin.getPasswordCrypt().password()));
+ assertEquals("61646d696e", StringHelper.toHexString(admin.getPasswordCrypt().salt()));
assertEquals("Application", admin.getFirstname());
assertEquals("Administrator", admin.getLastname());
assertEquals(UserState.ENABLED, admin.getUserState());
assertEquals("en-GB", admin.getLocale().toLanguageTag());
+ assertEquals(Set.of("GroupA"), admin.getGroups());
MatcherAssert.assertThat(admin.getRoles(), containsInAnyOrder("PrivilegeAdmin", "AppUser"));
Map properties = admin.getProperties();
assertEquals(new HashSet<>(Arrays.asList("organization", "organizationalUnit")), properties.keySet());
@@ -187,8 +221,54 @@ public class XmlTest {
assertEquals("Administrator", systemAdmin.getLastname());
assertEquals(UserState.SYSTEM, systemAdmin.getUserState());
assertEquals("en-GB", systemAdmin.getLocale().toLanguageTag());
+ assertEquals(Set.of(), systemAdmin.getGroups());
MatcherAssert.assertThat(systemAdmin.getRoles(), containsInAnyOrder("system_admin_privileges"));
assertTrue(systemAdmin.getProperties().isEmpty());
+
+ // admin2
+ User admin2 = findUser("admin2", users);
+ assertEquals("1", admin2.getUserId());
+ assertEquals("admin2", admin2.getUsername());
+ assertEquals("8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918",
+ StringHelper.toHexString(admin2.getPasswordCrypt().password()));
+ assertEquals("Application", admin2.getFirstname());
+ assertEquals("Administrator", admin2.getLastname());
+ assertEquals(UserState.ENABLED, admin2.getUserState());
+ assertEquals("en-GB", admin2.getLocale().toLanguageTag());
+ MatcherAssert.assertThat(admin2.getGroups(), containsInAnyOrder("AppUserLocationA"));
+ MatcherAssert.assertThat(admin2.getRoles(), containsInAnyOrder("PrivilegeAdmin"));
+ properties = admin2.getProperties();
+ assertEquals(new HashSet<>(Arrays.asList("organization", "organizationalUnit")), properties.keySet());
+ assertEquals("eitchnet.ch", properties.get("organization"));
+ assertEquals("Development", properties.get("organizationalUnit"));
+
+ }
+
+ @Test
+ public void canReadGroups() {
+
+ PrivilegeGroupsSaxReader xmlHandler = new PrivilegeGroupsSaxReader();
+ File xmlFile = new File(SRC_TEST + "PrivilegeGroups.xml");
+ XmlHelper.parseDocument(xmlFile, xmlHandler);
+
+ Map groups = xmlHandler.getGroups();
+ assertNotNull(groups);
+
+ assertEquals(2, groups.size());
+
+ // group AppUserLocationA
+ Group group = groups.get("AppUserLocationA");
+ assertEquals("AppUserLocationA", group.name());
+ MatcherAssert.assertThat(group.roles(), containsInAnyOrder("AppUser", "ModelAccessor", "UserPrivileges"));
+ Map properties = group.getProperties();
+ assertEquals(new HashSet<>(List.of("location")), properties.keySet());
+ assertEquals("LocationA", properties.get("location"));
+
+ group = groups.get("GroupA");
+ assertEquals("GroupA", group.name());
+ properties = group.getProperties();
+ assertTrue(properties.isEmpty());
+ assertTrue(group.roles().isEmpty());
}
@Test
@@ -212,23 +292,22 @@ public class XmlTest {
// PrivilegeAdmin
Role privilegeAdmin = findRole("PrivilegeAdmin", roles);
assertEquals("PrivilegeAdmin", privilegeAdmin.getName());
- assertEquals(18, privilegeAdmin.getPrivilegeNames().size());
- IPrivilege privilegeAction = privilegeAdmin.getPrivilege(PrivilegeHandler.PRIVILEGE_ACTION);
+ assertEquals(16, privilegeAdmin.getPrivilegeNames().size());
+ Privilege privilegeAction = privilegeAdmin.getPrivilege(PrivilegeHandler.PRIVILEGE_ACTION);
assertFalse(privilegeAction.isAllAllowed());
assertEquals(5, privilegeAction.getAllowList().size());
assertEquals(0, privilegeAction.getDenyList().size());
assertEquals("DefaultPrivilege", privilegeAction.getPolicy());
- IPrivilege privilegeAddRole = privilegeAdmin.getPrivilege(PrivilegeHandler.PRIVILEGE_ADD_ROLE);
+ Privilege privilegeAddRole = privilegeAdmin.getPrivilege(PrivilegeHandler.PRIVILEGE_ADD_ROLE);
assertTrue(privilegeAddRole.isAllAllowed());
assertEquals(0, privilegeAddRole.getAllowList().size());
assertEquals(0, privilegeAddRole.getDenyList().size());
- IPrivilege privilegeRemRoleFromUser = privilegeAdmin.getPrivilege(
- PrivilegeHandler.PRIVILEGE_REMOVE_ROLE_FROM_USER);
- assertTrue(privilegeRemRoleFromUser.isAllAllowed());
- assertEquals(0, privilegeRemRoleFromUser.getAllowList().size());
- assertEquals(0, privilegeRemRoleFromUser.getDenyList().size());
+ Privilege privilegeRemRole = privilegeAdmin.getPrivilege(PrivilegeHandler.PRIVILEGE_REMOVE_ROLE);
+ assertTrue(privilegeRemRole.isAllAllowed());
+ assertEquals(0, privilegeRemRole.getAllowList().size());
+ assertEquals(0, privilegeRemRole.getDenyList().size());
// AppUser
Role appUser = findRole("AppUser", roles);
@@ -236,7 +315,7 @@ public class XmlTest {
assertEquals(new HashSet<>(Collections.singletonList("li.strolch.privilege.test.model.TestRestrictable")),
appUser.getPrivilegeNames());
- IPrivilege testRestrictable = appUser.getPrivilege("li.strolch.privilege.test.model.TestRestrictable");
+ Privilege testRestrictable = appUser.getPrivilege("li.strolch.privilege.test.model.TestRestrictable");
assertEquals("li.strolch.privilege.test.model.TestRestrictable", testRestrictable.getName());
assertEquals("DefaultPrivilege", testRestrictable.getPolicy());
assertTrue(testRestrictable.isAllAllowed());
@@ -251,7 +330,7 @@ public class XmlTest {
containsInAnyOrder("li.strolch.privilege.handler.SystemAction",
"li.strolch.privilege.test.model.TestSystemRestrictable"));
- IPrivilege testSystemUserAction = systemAdminPrivileges.getPrivilege(
+ Privilege testSystemUserAction = systemAdminPrivileges.getPrivilege(
"li.strolch.privilege.handler.SystemAction");
assertEquals("li.strolch.privilege.handler.SystemAction", testSystemUserAction.getName());
assertEquals("DefaultPrivilege", testSystemUserAction.getPolicy());
@@ -259,7 +338,7 @@ public class XmlTest {
assertEquals(1, testSystemUserAction.getAllowList().size());
assertEquals(1, testSystemUserAction.getDenyList().size());
- IPrivilege testSystemRestrictable = systemAdminPrivileges.getPrivilege(
+ Privilege testSystemRestrictable = systemAdminPrivileges.getPrivilege(
"li.strolch.privilege.test.model.TestSystemRestrictable");
assertEquals("li.strolch.privilege.test.model.TestSystemRestrictable", testSystemRestrictable.getName());
assertEquals("DefaultPrivilege", testSystemRestrictable.getPolicy());
@@ -274,7 +353,7 @@ public class XmlTest {
MatcherAssert.assertThat(restrictedRole.getPrivilegeNames(),
containsInAnyOrder("li.strolch.privilege.handler.SystemAction"));
- IPrivilege testSystemUserAction2 = restrictedRole.getPrivilege("li.strolch.privilege.handler.SystemAction");
+ Privilege testSystemUserAction2 = restrictedRole.getPrivilege("li.strolch.privilege.handler.SystemAction");
assertEquals("li.strolch.privilege.handler.SystemAction", testSystemUserAction2.getName());
assertEquals("DefaultPrivilege", testSystemUserAction2.getPolicy());
assertFalse(testSystemUserAction2.isAllAllowed());
@@ -295,36 +374,42 @@ public class XmlTest {
}
@Test
- public void canWriteUsers() {
+ public void canWriteUsers() throws XMLStreamException, IOException {
Map propertyMap;
+ Set groups;
Set userRoles;
List users = new ArrayList<>();
propertyMap = new HashMap<>();
propertyMap.put("prop1", "value1");
+ groups = new HashSet<>();
+ groups.add("group1");
userRoles = new HashSet<>();
userRoles.add("role1");
- UserHistory history = new UserHistory();
- history.setFirstLogin(ZonedDateTime.of(LocalDateTime.of(2020, 1, 2, 2, 3, 4, 5), ZoneId.systemDefault()));
+ UserHistory history = UserHistory.EMPTY.withFirstLogin(
+ ZonedDateTime.of(LocalDateTime.of(2020, 1, 2, 2, 3, 4, 5), ZoneId.systemDefault()));
User user1 = new User("1", "user1",
new PasswordCrypt("blabla".getBytes(), "blabla".getBytes(), "PBKDF2WithHmacSHA512", 10000, 256), "Bob",
- "White", UserState.DISABLED, userRoles, Locale.ENGLISH, propertyMap, false, history);
+ "White", UserState.DISABLED, groups, userRoles, Locale.ENGLISH, propertyMap, false, history);
users.add(user1);
propertyMap = new HashMap<>();
propertyMap.put("prop2", "value2");
+ groups = new HashSet<>();
+ groups.add("group2");
userRoles = new HashSet<>();
userRoles.add("role2");
- history = new UserHistory();
- history.setFirstLogin(ZonedDateTime.of(LocalDateTime.of(2020, 1, 2, 2, 3, 4, 5), ZoneId.systemDefault()));
- history.setLastLogin(ZonedDateTime.of(LocalDateTime.of(2020, 1, 5, 2, 3, 4, 5), ZoneId.systemDefault()));
+ history = UserHistory.EMPTY.withFirstLogin(
+ ZonedDateTime.of(LocalDateTime.of(2020, 1, 2, 2, 3, 4, 5), ZoneId.systemDefault()))
+ .withLastLogin(ZonedDateTime.of(LocalDateTime.of(2020, 1, 5, 2, 3, 4, 5), ZoneId.systemDefault()));
User user2 = new User("2", "user2", new PasswordCrypt("haha".getBytes(), "haha".getBytes(), null, -1, -1),
- "Leonard", "Sheldon", UserState.ENABLED, userRoles, Locale.ENGLISH, propertyMap, false, history);
+ "Leonard", "Sheldon", UserState.ENABLED, groups, userRoles, Locale.ENGLISH, propertyMap, false,
+ history);
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);
@@ -342,8 +427,8 @@ public class XmlTest {
assertEquals(user1.getFirstname(), parsedUser1.getFirstname());
assertEquals(user1.getLastname(), parsedUser1.getLastname());
assertEquals(user1.getLocale(), parsedUser1.getLocale());
- assertArrayEquals(user1.getPasswordCrypt().getPassword(), parsedUser1.getPasswordCrypt().getPassword());
- assertArrayEquals(user1.getPasswordCrypt().getSalt(), parsedUser1.getPasswordCrypt().getSalt());
+ assertArrayEquals(user1.getPasswordCrypt().password(), parsedUser1.getPasswordCrypt().password());
+ assertArrayEquals(user1.getPasswordCrypt().salt(), parsedUser1.getPasswordCrypt().salt());
assertEquals(user1.getProperties(), parsedUser1.getProperties());
assertEquals(user1.getUserId(), parsedUser1.getUserId());
assertEquals(user1.getUserState(), parsedUser1.getUserState());
@@ -352,8 +437,8 @@ public class XmlTest {
assertEquals(user2.getFirstname(), parsedUser2.getFirstname());
assertEquals(user2.getLastname(), parsedUser2.getLastname());
assertEquals(user2.getLocale(), parsedUser2.getLocale());
- assertArrayEquals(user2.getPasswordCrypt().getPassword(), parsedUser2.getPasswordCrypt().getPassword());
- assertArrayEquals(user2.getPasswordCrypt().getSalt(), parsedUser2.getPasswordCrypt().getSalt());
+ assertArrayEquals(user2.getPasswordCrypt().password(), parsedUser2.getPasswordCrypt().password());
+ assertArrayEquals(user2.getPasswordCrypt().salt(), parsedUser2.getPasswordCrypt().salt());
assertEquals(user2.getProperties(), parsedUser2.getProperties());
assertEquals(user2.getUserId(), parsedUser2.getUserId());
assertEquals(user2.getUserState(), parsedUser2.getUserState());
@@ -361,13 +446,48 @@ public class XmlTest {
}
@Test
- public void canWriteRoles() {
+ public void canWriteGroups() throws XMLStreamException, IOException {
- Map privilegeMap;
+ Map propertyMap;
+ Set roles;
+
+ List groups = new ArrayList<>();
+ propertyMap = new HashMap<>();
+ propertyMap.put("prop1", "value1");
+ roles = new HashSet<>();
+ roles.add("role1");
+ Group newGroup = new Group("group1", roles, propertyMap);
+ groups.add(newGroup);
+
+ File modelFile = new File(TARGET_TEST + "PrivilegeGroupsTest.xml");
+ PrivilegeGroupsSaxWriter configSaxWriter = new PrivilegeGroupsSaxWriter(groups, modelFile);
+ configSaxWriter.write();
+
+ PrivilegeGroupsSaxReader xmlHandler = new PrivilegeGroupsSaxReader();
+ XmlHelper.parseDocument(modelFile, xmlHandler);
+
+ Map parsedGroups = xmlHandler.getGroups();
+ assertNotNull(parsedGroups);
+ assertEquals(1, parsedGroups.size());
+
+ // group group1
+ Group parsedGroup1 = parsedGroups.get("group1");
+ assertNotNull(parsedGroup1);
+ assertEquals("group1", parsedGroup1.name());
+ MatcherAssert.assertThat(parsedGroup1.roles(), containsInAnyOrder("role1"));
+ Map properties = parsedGroup1.getProperties();
+ assertEquals(new HashSet<>(List.of("prop1")), properties.keySet());
+ assertEquals("value1", properties.get("prop1"));
+ }
+
+ @Test
+ public void canWriteRoles() throws XMLStreamException, IOException {
+
+ Map privilegeMap;
List roles = new ArrayList<>();
Set list = Collections.emptySet();
privilegeMap = new HashMap<>();
- privilegeMap.put("priv1", new PrivilegeImpl("priv1", "DefaultPrivilege", true, list, list));
+ privilegeMap.put("priv1", new Privilege("priv1", "DefaultPrivilege", true, list, list));
Role role1 = new Role("role1", privilegeMap);
roles.add(role1);
@@ -376,13 +496,13 @@ public class XmlTest {
denyList.add("myself");
Set allowList = new HashSet<>();
allowList.add("other");
- privilegeMap.put("priv2", new PrivilegeImpl("priv2", "DefaultPrivilege", false, denyList, allowList));
+ privilegeMap.put("priv2", new Privilege("priv2", "DefaultPrivilege", false, denyList, allowList));
Role role2 = new Role("role2", privilegeMap);
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);
@@ -400,8 +520,8 @@ public class XmlTest {
Set privilegeNames = role1.getPrivilegeNames();
assertEquals(privilegeNames, parsedRole1.getPrivilegeNames());
for (String privilegeName : privilegeNames) {
- IPrivilege privilege = role1.getPrivilege(privilegeName);
- IPrivilege privilege2 = parsedRole1.getPrivilege(privilegeName);
+ Privilege privilege = role1.getPrivilege(privilegeName);
+ Privilege privilege2 = parsedRole1.getPrivilege(privilegeName);
assertNotNull(privilege);
assertNotNull(privilege2);
@@ -415,8 +535,8 @@ public class XmlTest {
assertEquals(role2.getPrivilegeNames(), parsedRole2.getPrivilegeNames());
privilegeNames = role2.getPrivilegeNames();
for (String privilegeName : privilegeNames) {
- IPrivilege privilege = role2.getPrivilege(privilegeName);
- IPrivilege privilege2 = parsedRole2.getPrivilege(privilegeName);
+ Privilege privilege = role2.getPrivilege(privilegeName);
+ Privilege privilege2 = parsedRole2.getPrivilege(privilegeName);
assertNotNull(privilege);
assertNotNull(privilege2);
diff --git a/privilege/src/test/java/li/strolch/privilege/test/model/DummySsoHandler.java b/privilege/src/test/java/li/strolch/privilege/test/model/DummySsoHandler.java
index 98432ceb9..1acdb05c6 100644
--- a/privilege/src/test/java/li/strolch/privilege/test/model/DummySsoHandler.java
+++ b/privilege/src/test/java/li/strolch/privilege/test/model/DummySsoHandler.java
@@ -28,9 +28,10 @@ public class DummySsoHandler implements SingleSignOnHandler {
@SuppressWarnings("unchecked") Map map = (Map) data;
+ Set groups = Arrays.stream(map.get("groups").split(",")).map(String::trim).collect(Collectors.toSet());
Set roles = Arrays.stream(map.get("roles").split(",")).map(String::trim).collect(Collectors.toSet());
Map properties = new HashMap<>();
return new User(map.get("userId"), map.get("username"), null, map.get("firstName"), map.get("lastName"),
- UserState.REMOTE, roles, Locale.ENGLISH, properties, false, new UserHistory());
+ UserState.REMOTE, groups, roles, Locale.ENGLISH, properties, false, UserHistory.EMPTY);
}
}
diff --git a/privilege/src/test/resources/config/PrivilegeConfigMerge.xml b/privilege/src/test/resources/config/PrivilegeConfigMerge.xml
index 98fd39c2a..b49a8416c 100644
--- a/privilege/src/test/resources/config/PrivilegeConfigMerge.xml
+++ b/privilege/src/test/resources/config/PrivilegeConfigMerge.xml
@@ -27,6 +27,7 @@
+
diff --git a/privilege/src/test/resources/config/PrivilegeGroups.xml b/privilege/src/test/resources/config/PrivilegeGroups.xml
new file mode 100644
index 000000000..a06069366
--- /dev/null
+++ b/privilege/src/test/resources/config/PrivilegeGroups.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+ AppUser
+ ModelAccessor
+ UserPrivileges
+
+
+
+
+
+
\ No newline at end of file
diff --git a/privilege/src/test/resources/config/PrivilegeGroupsMerge.xml b/privilege/src/test/resources/config/PrivilegeGroupsMerge.xml
new file mode 100644
index 000000000..287714813
--- /dev/null
+++ b/privilege/src/test/resources/config/PrivilegeGroupsMerge.xml
@@ -0,0 +1,37 @@
+
+
+
+
+ RoleA1
+
+
+
+
+
+
+
+ RoleA2
+
+
+
+
+
+
+
+
+ RoleB1
+
+
+
+
+
+
+
+
+ RoleB2
+
+
+
+
+
+
\ No newline at end of file
diff --git a/privilege/src/test/resources/config/PrivilegeRoles.xml b/privilege/src/test/resources/config/PrivilegeRoles.xml
index 0c6b5c06c..2fb60662b 100644
--- a/privilege/src/test/resources/config/PrivilegeRoles.xml
+++ b/privilege/src/test/resources/config/PrivilegeRoles.xml
@@ -2,61 +2,32 @@
-
- li.strolch.service.privilege.users.PrivilegeUpdateUserService
- li.strolch.service.privilege.users.PrivilegeUpdateUserRolesService
- li.strolch.service.privilege.users.PrivilegeSetUserPasswordService
- li.strolch.service.privilege.users.PrivilegeSetUserLocaleService
- li.strolch.service.privilege.users.PrivilegeRemoveUserService
- li.strolch.service.privilege.users.PrivilegeRemoveRoleFromUserService
- li.strolch.service.privilege.users.PrivilegeAddUserService
- li.strolch.service.privilege.users.PrivilegeAddRoleToUserService
- li.strolch.service.privilege.roles.PrivilegeUpdateRoleService
- li.strolch.service.privilege.roles.PrivilegeRemoveRoleService
- li.strolch.service.privilege.roles.PrivilegeRemovePrivilegeFromRoleService
- li.strolch.service.privilege.roles.PrivilegeAddRoleService
- li.strolch.service.privilege.roles.PrivilegeAddOrReplacePrivilegeOnRoleService
-
-
- true
-
-
+
true
true
-
- true
-
-
- true
-
-
- true
-
- Reload
+ GetCertificates
GetPolicies
Persist
- GetCertificates
PersistSessions
+ Reload
-
+
true
-
- SYSTEM
- DISABLED
- ENABLED
-
-
+
true
true
-
+
+ true
+
+
true
@@ -65,15 +36,35 @@
true
-
+
true
-
+
true
-
+
true
+
+ SYSTEM
+ DISABLED
+ ENABLED
+
+
+ true
+
+
+ li.strolch.service.privilege.roles.PrivilegeAddRoleService
+ li.strolch.service.privilege.roles.PrivilegeRemoveRoleService
+ li.strolch.service.privilege.roles.PrivilegeUpdateRoleService
+ li.strolch.service.privilege.users.PrivilegeAddUserService
+ li.strolch.service.privilege.users.PrivilegeRemoveUserService
+ li.strolch.service.privilege.users.PrivilegeSetUserLocaleService
+ li.strolch.service.privilege.users.PrivilegeSetUserPasswordService
+ li.strolch.service.privilege.users.PrivilegeSetUserStateService
+ li.strolch.service.privilege.users.PrivilegeUpdateUserRolesService
+ li.strolch.service.privilege.users.PrivilegeUpdateUserService
+
diff --git a/privilege/src/test/resources/config/PrivilegeUsers.xml b/privilege/src/test/resources/config/PrivilegeUsers.xml
index e0a38b179..d1a7f1b3d 100644
--- a/privilege/src/test/resources/config/PrivilegeUsers.xml
+++ b/privilege/src/test/resources/config/PrivilegeUsers.xml
@@ -6,6 +6,9 @@
Administrator
ENABLED
en-GB
+
+ GroupA
+
PrivilegeAdmin
AppUser
@@ -21,9 +24,11 @@
Administrator
ENABLED
en-GB
+
+ AppUserLocationA
+
PrivilegeAdmin
- AppUser
diff --git a/privilege/src/test/resources/config/PrivilegeUsersMerge.xml b/privilege/src/test/resources/config/PrivilegeUsersMerge.xml
index 72f075877..bf473df6c 100644
--- a/privilege/src/test/resources/config/PrivilegeUsersMerge.xml
+++ b/privilege/src/test/resources/config/PrivilegeUsersMerge.xml
@@ -23,4 +23,26 @@
+
+ System User
+ Administrator
+ ENABLED
+ en-GB
+
+ GroupA1
+ GroupA2
+
+
+
+
+ System User
+ Administrator
+ ENABLED
+ en-GB
+
+ GroupB1
+ GroupB2
+
+
+
\ No newline at end of file
diff --git a/service/src/main/java/li/strolch/execution/EventBasedExecutionHandler.java b/service/src/main/java/li/strolch/execution/EventBasedExecutionHandler.java
index 9452a99dc..58d5a0160 100644
--- a/service/src/main/java/li/strolch/execution/EventBasedExecutionHandler.java
+++ b/service/src/main/java/li/strolch/execution/EventBasedExecutionHandler.java
@@ -1,15 +1,5 @@
package li.strolch.execution;
-import static java.util.Collections.emptyMap;
-import static java.util.Collections.emptySet;
-import static li.strolch.model.StrolchModelConstants.*;
-import static li.strolch.runtime.StrolchConstants.SYSTEM_USER_AGENT;
-import static li.strolch.utils.collections.SynchronizedCollections.synchronizedMapOfMaps;
-
-import java.util.*;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.stream.Stream;
-
import li.strolch.agent.api.ComponentContainer;
import li.strolch.agent.api.ObserverEvent;
import li.strolch.agent.api.StrolchRealm;
@@ -28,6 +18,16 @@ import li.strolch.privilege.model.Certificate;
import li.strolch.privilege.model.PrivilegeContext;
import li.strolch.utils.collections.MapOfMaps;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Stream;
+
+import static java.util.Collections.emptyMap;
+import static java.util.Collections.emptySet;
+import static li.strolch.model.StrolchModelConstants.*;
+import static li.strolch.runtime.StrolchConstants.SYSTEM_USER_AGENT;
+import static li.strolch.utils.collections.SynchronizedCollections.synchronizedMapOfMaps;
+
/**
* The event based execution handler waits for events in that the {@link ExecutionPolicy} implementations must call the
* relevant methods when the work is complete. Afterwards the next {@link Action} in the procedure is executed
@@ -51,12 +51,12 @@ public class EventBasedExecutionHandler extends ExecutionHandler {
@Override
public boolean isControlling(Activity activity) {
- return this.controllers.containsElement(getDefaultRealm(), activity.getLocator());
+ return this.controllers.containsElement(getDefaultRealm(), activity.getRootElement().getLocator());
}
@Override
public boolean isControlling(String realm, Activity activity) {
- return this.controllers.containsElement(realm, activity.getLocator());
+ return this.controllers.containsElement(realm, activity.getRootElement().getLocator());
}
@Override
@@ -83,12 +83,12 @@ public class EventBasedExecutionHandler extends ExecutionHandler {
@Override
public Controller getController(Activity activity) {
- return getController(getDefaultRealm(), activity.getLocator());
+ return getController(getDefaultRealm(), activity.getRootElement().getLocator());
}
@Override
public Controller getController(String realm, Activity activity) {
- return this.controllers.getElement(realm, activity.getLocator());
+ return this.controllers.getElement(realm, activity.getRootElement().getLocator());
}
@Override
@@ -157,7 +157,7 @@ public class EventBasedExecutionHandler extends ExecutionHandler {
synchronized (this.controllers) {
Map map = this.controllers.getMap(realm);
if (map == null) {
- logger.error("No controllers for realm " + realm);
+ logger.info("No controllers for realm " + realm);
return;
}
@@ -171,26 +171,28 @@ public class EventBasedExecutionHandler extends ExecutionHandler {
}
@Override
- public void addForExecution(Activity activity) {
- addForExecution(getDefaultRealm(), activity);
+ public Controller addForExecution(Activity activity) {
+ return addForExecution(getDefaultRealm(), activity);
}
@Override
- public void addForExecution(String realm, Activity activity) {
+ public Controller addForExecution(String realm, Activity activity) {
ExecutionHandlerState state = this.statesByRealm.getOrDefault(realm, ExecutionHandlerState.Running);
if (state == ExecutionHandlerState.HaltNew)
throw new IllegalStateException(
"ExecutionHandler state is " + state + ", can not add activities for execution!");
- if (this.controllers.containsElement(realm, activity.getLocator()))
- throw new IllegalStateException(activity.getLocator() + " is already registered for execution!");
+ Locator locator = activity.getRootElement().getLocator();
+ if (this.controllers.containsElement(realm, locator))
+ throw new IllegalStateException(locator + " is already registered for execution!");
- logger.info("Added " + activity.getLocator() + " @ " + realm);
+ logger.info("Added " + locator + " @ " + realm);
Controller controller = newController(realm, activity);
- this.controllers.addElement(realm, activity.getLocator(), controller);
+ this.controllers.addElement(realm, locator, controller);
notifyObserverAdd(controller);
triggerExecution(realm);
+ return controller;
}
@Override
@@ -205,10 +207,11 @@ public class EventBasedExecutionHandler extends ExecutionHandler {
throw new IllegalStateException(
"ExecutionHandler state is " + state + ", can not add activities for execution!");
- Controller controller = this.controllers.getElement(realm, activity.getLocator());
+ Locator locator = activity.getRootElement().getLocator();
+ Controller controller = this.controllers.getElement(realm, locator);
if (controller == null) {
controller = newController(realm, activity);
- this.controllers.addElement(realm, activity.getLocator(), controller);
+ this.controllers.addElement(realm, locator, controller);
notifyObserverAdd(controller);
}
@@ -296,7 +299,8 @@ public class EventBasedExecutionHandler extends ExecutionHandler {
if (activity.isReadOnly())
activity = activity.getClone(true);
- logger.info("Restarting Execution of " + activity.getLocator() + " on realm " + realmName);
+ Locator locator = activity.getRootElement().getLocator();
+ logger.info("Restarting Execution of " + locator + " on realm " + realmName);
// in execution actions need to be in state STOPPED to restart
activity.findActionsDeep(a -> a.getState().inExecutionPhase()).forEach(a -> {
@@ -309,7 +313,7 @@ public class EventBasedExecutionHandler extends ExecutionHandler {
// register for execution
Controller controller = newController(realmName, activity);
- this.controllers.addElement(realmName, activity.getLocator(), controller);
+ this.controllers.addElement(realmName, locator, controller);
});
// commit changes to state
diff --git a/service/src/main/java/li/strolch/execution/ExecutionHandler.java b/service/src/main/java/li/strolch/execution/ExecutionHandler.java
index e88eddb17..97bbe1d7e 100644
--- a/service/src/main/java/li/strolch/execution/ExecutionHandler.java
+++ b/service/src/main/java/li/strolch/execution/ExecutionHandler.java
@@ -219,7 +219,7 @@ public abstract class ExecutionHandler extends StrolchComponent {
* @throws IllegalStateException
* if the default realm is not set!
*/
- public abstract void addForExecution(Activity activity);
+ public abstract Controller addForExecution(Activity activity);
/**
* Registers the given {@link Activity} for execution. Execution is started when the concrete implementation deems
@@ -230,7 +230,7 @@ public abstract class ExecutionHandler extends StrolchComponent {
* @param activity
* the {@link Activity}
*/
- public abstract void addForExecution(String realm, Activity activity);
+ public abstract Controller addForExecution(String realm, Activity activity);
/**
* Registers the given {@link Activity} for execution on the default realm, and submits it for execution immediately
diff --git a/service/src/main/java/li/strolch/execution/policy/ExecutionPolicy.java b/service/src/main/java/li/strolch/execution/policy/ExecutionPolicy.java
index 25963e605..277aab548 100644
--- a/service/src/main/java/li/strolch/execution/policy/ExecutionPolicy.java
+++ b/service/src/main/java/li/strolch/execution/policy/ExecutionPolicy.java
@@ -20,8 +20,12 @@ import li.strolch.privilege.model.PrivilegeContext;
import li.strolch.runtime.StrolchConstants;
import li.strolch.runtime.privilege.PrivilegedRunnable;
import li.strolch.runtime.privilege.PrivilegedRunnableWithResult;
+import li.strolch.utils.time.PeriodDuration;
import java.time.Duration;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
@@ -53,6 +57,8 @@ public abstract class ExecutionPolicy extends StrolchPolicy {
protected Locator resourceLoc;
protected Locator actionLoc;
+ protected List> futures;
+
/**
* The TX for this execution policy. The TX needs to be updated when this execution policy has a longer life time
* than the actual TX
@@ -63,6 +69,7 @@ public abstract class ExecutionPolicy extends StrolchPolicy {
super(tx);
this.tx = tx;
this.realm = tx.getRealmName();
+ this.futures = new ArrayList<>();
}
/**
@@ -225,6 +232,7 @@ public abstract class ExecutionPolicy extends StrolchPolicy {
public void stop() {
this.stopped = true;
try {
+ this.futures.forEach(future -> future.cancel(false));
handleStopped();
} catch (Exception e) {
logger.error("Stopping failed for " + this.actionLoc, e);
@@ -246,6 +254,9 @@ public abstract class ExecutionPolicy extends StrolchPolicy {
* @param state the new state to set
*/
protected void setActionState(Action action, State state) {
+ if (action.getState().inClosedPhase())
+ throw new IllegalStateException("Action " + action.getLocator() + " has state " + action.getState() +
+ " and can not be changed to " + state);
action.setState(state);
@@ -270,6 +281,17 @@ public abstract class ExecutionPolicy extends StrolchPolicy {
return action.findObjectivesParam(PARAM_DURATION, true);
}
+ /**
+ * Delays the given {@link Runnable} by the given {@link PeriodDuration}
+ *
+ * @param duration the duration to delay
+ * @param runnable the action to delay
+ */
+ public void delay(PeriodDuration duration, Runnable runnable) {
+ long delayMs = duration.toMillis();
+ this.futures.add(getDelayedExecutionTimer().delay(delayMs, runnable));
+ }
+
/**
* Delays the given {@link Runnable} by the given {@link Duration}
*
@@ -278,7 +300,7 @@ public abstract class ExecutionPolicy extends StrolchPolicy {
*/
public void delay(Duration duration, Runnable runnable) {
long delayMs = duration.toMillis();
- getDelayedExecutionTimer().delay(delayMs, runnable);
+ this.futures.add(getDelayedExecutionTimer().delay(delayMs, runnable));
}
/**
@@ -321,7 +343,7 @@ public abstract class ExecutionPolicy extends StrolchPolicy {
delayMs = 20;
}
logger.info("Delaying runnable " + runnable + " by " + formatMillisecondsDuration(delayMs));
- getDelayedExecutionTimer().delay(delayMs, runnable);
+ this.futures.add(getDelayedExecutionTimer().delay(delayMs, runnable));
}
/**
diff --git a/service/src/main/java/li/strolch/execution/policy/SimpleExecution.java b/service/src/main/java/li/strolch/execution/policy/SimpleExecution.java
index 89b408702..461f69b82 100644
--- a/service/src/main/java/li/strolch/execution/policy/SimpleExecution.java
+++ b/service/src/main/java/li/strolch/execution/policy/SimpleExecution.java
@@ -92,7 +92,7 @@ public class SimpleExecution extends ExecutionPolicy {
protected void toWarning(LogMessage message) {
cancelWarningTask();
addMessage(message);
- getExecutionHandler().toWarning(this.realm, message.getLocator());
+ getExecutionHandler().toWarning(this.realm, this.actionLoc);
}
protected void toExecuted() throws Exception {
@@ -126,7 +126,7 @@ public class SimpleExecution extends ExecutionPolicy {
stop();
logger.error("Action " + message.getLocator() + " failed because of: " + message.formatMessage());
addMessage(message);
- getExecutionHandler().toError(this.realm, message.getLocator());
+ getExecutionHandler().toError(this.realm, this.actionLoc);
}
protected void setActionStateWithValueChange(Action action, State execution, double value) {
diff --git a/service/src/main/java/li/strolch/report/ReportSearch.java b/service/src/main/java/li/strolch/report/ReportSearch.java
index 77d55674f..e15b204b1 100644
--- a/service/src/main/java/li/strolch/report/ReportSearch.java
+++ b/service/src/main/java/li/strolch/report/ReportSearch.java
@@ -5,7 +5,7 @@ import static li.strolch.report.ReportConstants.TYPE_REPORT;
import java.util.Set;
import li.strolch.persistence.api.StrolchTransaction;
-import li.strolch.privilege.model.IPrivilege;
+import li.strolch.privilege.model.Privilege;
import li.strolch.search.ResourceSearch;
/**
@@ -18,7 +18,7 @@ public class ReportSearch extends ResourceSearch {
public ReportSearch(StrolchTransaction tx) {
types(TYPE_REPORT);
- IPrivilege reportPrivilege = tx.getPrivilegeContext().getPrivilege(ReportSearch.class.getName());
+ Privilege reportPrivilege = tx.getPrivilegeContext().getPrivilege(ReportSearch.class.getName());
if (!reportPrivilege.isAllAllowed()) {
Set allowedReportIds = reportPrivilege.getAllowList();
where(id().isIn(allowedReportIds));
diff --git a/service/src/main/java/li/strolch/service/privilege/roles/PrivilegeAddOrReplacePrivilegeOnRoleArgument.java b/service/src/main/java/li/strolch/service/privilege/roles/PrivilegeAddOrReplacePrivilegeOnRoleArgument.java
deleted file mode 100644
index 180cb9075..000000000
--- a/service/src/main/java/li/strolch/service/privilege/roles/PrivilegeAddOrReplacePrivilegeOnRoleArgument.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2015 Robert von Burg
- *
- * 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.service.privilege.roles;
-
-import li.strolch.privilege.model.PrivilegeRep;
-import li.strolch.service.api.ServiceArgument;
-
-public class PrivilegeAddOrReplacePrivilegeOnRoleArgument extends ServiceArgument {
- public String roleName;
- public PrivilegeRep privilegeRep;
-}
diff --git a/service/src/main/java/li/strolch/service/privilege/roles/PrivilegeAddOrReplacePrivilegeOnRoleService.java b/service/src/main/java/li/strolch/service/privilege/roles/PrivilegeAddOrReplacePrivilegeOnRoleService.java
deleted file mode 100644
index 1d758008d..000000000
--- a/service/src/main/java/li/strolch/service/privilege/roles/PrivilegeAddOrReplacePrivilegeOnRoleService.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2015 Robert von Burg
- *
- * 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.service.privilege.roles;
-
-import li.strolch.model.audit.AccessType;
-import li.strolch.model.audit.Audit;
-import li.strolch.persistence.api.StrolchTransaction;
-import li.strolch.privilege.handler.PrivilegeHandler;
-import li.strolch.privilege.model.RoleRep;
-import li.strolch.runtime.StrolchConstants.StrolchPrivilegeConstants;
-import li.strolch.service.api.AbstractService;
-import li.strolch.service.api.ServiceResultState;
-
-/**
- * @author Robert von Burg
- */
-public class PrivilegeAddOrReplacePrivilegeOnRoleService
- extends AbstractService {
-
- @Override
- protected PrivilegeRoleResult getResultInstance() {
- return new PrivilegeRoleResult(ServiceResultState.FAILED);
- }
-
- @Override
- public PrivilegeAddOrReplacePrivilegeOnRoleArgument getArgumentInstance() {
- return new PrivilegeAddOrReplacePrivilegeOnRoleArgument();
- }
-
- @Override
- protected PrivilegeRoleResult internalDoService(PrivilegeAddOrReplacePrivilegeOnRoleArgument arg) {
-
- li.strolch.runtime.privilege.PrivilegeHandler strolchPrivilegeHandler = getContainer().getPrivilegeHandler();
- PrivilegeHandler privilegeHandler = strolchPrivilegeHandler.getPrivilegeHandler();
-
- RoleRep role;
- try (StrolchTransaction tx = openArgOrUserTx(arg, PrivilegeHandler.PRIVILEGE_MODIFY_ROLE)) {
- tx.setSuppressAudits(true);
-
- role = privilegeHandler.addOrReplacePrivilegeOnRole(getCertificate(), arg.roleName, arg.privilegeRep);
- privilegeHandler.persist(getCertificate());
-
- Audit audit = tx
- .auditFrom(AccessType.UPDATE, StrolchPrivilegeConstants.PRIVILEGE, StrolchPrivilegeConstants.ROLE,
- role.getName());
- tx.getAuditTrail().add(tx, audit);
- }
-
- return new PrivilegeRoleResult(role);
- }
-}
diff --git a/service/src/main/java/li/strolch/service/privilege/roles/PrivilegeRemovePrivilegeFromRoleArgument.java b/service/src/main/java/li/strolch/service/privilege/roles/PrivilegeRemovePrivilegeFromRoleArgument.java
deleted file mode 100644
index 10c4fb1df..000000000
--- a/service/src/main/java/li/strolch/service/privilege/roles/PrivilegeRemovePrivilegeFromRoleArgument.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright 2015 Robert von Burg
- *
- * 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.service.privilege.roles;
-
-import li.strolch.service.api.ServiceArgument;
-
-public class PrivilegeRemovePrivilegeFromRoleArgument extends ServiceArgument {
- public String roleName;
- public String privilegeName;
-}
diff --git a/service/src/main/java/li/strolch/service/privilege/roles/PrivilegeRemovePrivilegeFromRoleService.java b/service/src/main/java/li/strolch/service/privilege/roles/PrivilegeRemovePrivilegeFromRoleService.java
deleted file mode 100644
index ca731b3bb..000000000
--- a/service/src/main/java/li/strolch/service/privilege/roles/PrivilegeRemovePrivilegeFromRoleService.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2015 Robert von Burg
- *
- * 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.service.privilege.roles;
-
-import li.strolch.model.audit.AccessType;
-import li.strolch.model.audit.Audit;
-import li.strolch.persistence.api.StrolchTransaction;
-import li.strolch.privilege.handler.PrivilegeHandler;
-import li.strolch.privilege.model.RoleRep;
-import li.strolch.runtime.StrolchConstants.StrolchPrivilegeConstants;
-import li.strolch.service.api.AbstractService;
-import li.strolch.service.api.ServiceResultState;
-
-/**
- * @author Robert von Burg
- */
-public class PrivilegeRemovePrivilegeFromRoleService
- extends AbstractService {
-
- @Override
- protected PrivilegeRoleResult getResultInstance() {
- return new PrivilegeRoleResult(ServiceResultState.FAILED);
- }
-
- @Override
- public PrivilegeRemovePrivilegeFromRoleArgument getArgumentInstance() {
- return new PrivilegeRemovePrivilegeFromRoleArgument();
- }
-
- @Override
- protected PrivilegeRoleResult internalDoService(PrivilegeRemovePrivilegeFromRoleArgument arg) {
-
- li.strolch.runtime.privilege.PrivilegeHandler strolchPrivilegeHandler = getContainer().getPrivilegeHandler();
- PrivilegeHandler privilegeHandler = strolchPrivilegeHandler.getPrivilegeHandler();
-
- RoleRep role;
- try (StrolchTransaction tx = openArgOrUserTx(arg, StrolchPrivilegeConstants.PRIVILEGE_MODIFY_ROLE)) {
- tx.setSuppressAudits(true);
-
- role = privilegeHandler.removePrivilegeFromRole(getCertificate(), arg.roleName, arg.privilegeName);
- privilegeHandler.persist(getCertificate());
-
- Audit audit = tx
- .auditFrom(AccessType.UPDATE, StrolchPrivilegeConstants.PRIVILEGE, StrolchPrivilegeConstants.ROLE,
- role.getName());
- tx.getAuditTrail().add(tx, audit);
- }
-
- return new PrivilegeRoleResult(role);
- }
-}
diff --git a/service/src/main/java/li/strolch/service/privilege/users/PrivilegeAddRoleToUserService.java b/service/src/main/java/li/strolch/service/privilege/users/PrivilegeAddRoleToUserService.java
deleted file mode 100644
index dc5de32d9..000000000
--- a/service/src/main/java/li/strolch/service/privilege/users/PrivilegeAddRoleToUserService.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2015 Robert von Burg
- *
- * 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.service.privilege.users;
-
-import li.strolch.model.audit.AccessType;
-import li.strolch.model.audit.Audit;
-import li.strolch.persistence.api.StrolchTransaction;
-import li.strolch.privilege.handler.PrivilegeHandler;
-import li.strolch.privilege.model.UserRep;
-import li.strolch.runtime.StrolchConstants.StrolchPrivilegeConstants;
-import li.strolch.service.api.AbstractService;
-import li.strolch.service.api.ServiceResultState;
-
-/**
- * @author Robert von Burg
- */
-public class PrivilegeAddRoleToUserService
- extends AbstractService {
-
- @Override
- protected PrivilegeUserResult getResultInstance() {
- return new PrivilegeUserResult(ServiceResultState.FAILED);
- }
-
- @Override
- public PrivilegeRoleUserNamesArgument getArgumentInstance() {
- return new PrivilegeRoleUserNamesArgument();
- }
-
- @Override
- protected PrivilegeUserResult internalDoService(PrivilegeRoleUserNamesArgument arg) {
-
- li.strolch.runtime.privilege.PrivilegeHandler strolchPrivilegeHandler = getContainer().getPrivilegeHandler();
- PrivilegeHandler privilegeHandler = strolchPrivilegeHandler.getPrivilegeHandler();
-
- UserRep user;
- try (StrolchTransaction tx = openArgOrUserTx(arg, PrivilegeHandler.PRIVILEGE_ADD_ROLE_TO_USER)) {
- tx.setSuppressAudits(true);
-
- user = privilegeHandler.addRoleToUser(getCertificate(), arg.username, arg.rolename);
- if (privilegeHandler.isPersistOnUserDataChanged())
- privilegeHandler.persist(getCertificate());
-
- Audit audit = tx.auditFrom(AccessType.UPDATE, StrolchPrivilegeConstants.PRIVILEGE,
- StrolchPrivilegeConstants.USER, user.getUsername());
- tx.getAuditTrail().add(tx, audit);
- }
-
- return new PrivilegeUserResult(user);
- }
-}
diff --git a/service/src/main/java/li/strolch/service/privilege/users/PrivilegeRemoveRoleFromUserService.java b/service/src/main/java/li/strolch/service/privilege/users/PrivilegeRemoveRoleFromUserService.java
deleted file mode 100644
index 6ff55b727..000000000
--- a/service/src/main/java/li/strolch/service/privilege/users/PrivilegeRemoveRoleFromUserService.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright 2015 Robert von Burg
- *
- * 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.service.privilege.users;
-
-import li.strolch.model.audit.AccessType;
-import li.strolch.model.audit.Audit;
-import li.strolch.persistence.api.StrolchTransaction;
-import li.strolch.privilege.handler.PrivilegeHandler;
-import li.strolch.privilege.model.UserRep;
-import li.strolch.runtime.StrolchConstants.StrolchPrivilegeConstants;
-import li.strolch.service.api.AbstractService;
-
-/**
- * @author Robert von Burg
- */
-public class PrivilegeRemoveRoleFromUserService
- extends AbstractService {
-
- @Override
- protected PrivilegeUserResult getResultInstance() {
- return new PrivilegeUserResult();
- }
-
- @Override
- public PrivilegeRoleUserNamesArgument getArgumentInstance() {
- return new PrivilegeRoleUserNamesArgument();
- }
-
- @Override
- protected PrivilegeUserResult internalDoService(PrivilegeRoleUserNamesArgument arg) {
-
- li.strolch.runtime.privilege.PrivilegeHandler strolchPrivilegeHandler = getContainer().getPrivilegeHandler();
- PrivilegeHandler privilegeHandler = strolchPrivilegeHandler.getPrivilegeHandler();
-
- UserRep user;
- try (StrolchTransaction tx = openArgOrUserTx(arg, PrivilegeHandler.PRIVILEGE_REMOVE_ROLE_FROM_USER)) {
- tx.setSuppressAudits(true);
-
- user = privilegeHandler.removeRoleFromUser(getCertificate(), arg.username, arg.rolename);
- if (privilegeHandler.isPersistOnUserDataChanged())
- privilegeHandler.persist(getCertificate());
-
- Audit audit = tx.auditFrom(AccessType.UPDATE, StrolchPrivilegeConstants.PRIVILEGE,
- StrolchPrivilegeConstants.USER, user.getUsername());
- tx.getAuditTrail().add(tx, audit);
- }
-
- return new PrivilegeUserResult(user);
- }
-}
diff --git a/service/src/main/java/li/strolch/service/privilege/users/PrivilegeRemoveUserCommand.java b/service/src/main/java/li/strolch/service/privilege/users/PrivilegeRemoveUserCommand.java
index 4435fbd8a..6064c3ddc 100644
--- a/service/src/main/java/li/strolch/service/privilege/users/PrivilegeRemoveUserCommand.java
+++ b/service/src/main/java/li/strolch/service/privilege/users/PrivilegeRemoveUserCommand.java
@@ -7,6 +7,7 @@ import li.strolch.model.audit.AccessType;
import li.strolch.model.audit.Audit;
import li.strolch.persistence.api.StrolchTransaction;
import li.strolch.privilege.handler.PrivilegeHandler;
+import li.strolch.runtime.sessions.StrolchSessionHandler;
import li.strolch.service.api.Command;
import li.strolch.utils.dbc.DBC;
@@ -37,6 +38,8 @@ public class PrivilegeRemoveUserCommand extends Command {
if (privilegeHandler.isPersistOnUserDataChanged())
privilegeHandler.persist(tx().getCertificate());
+ getComponent(StrolchSessionHandler.class).refreshSessions();
+
Audit audit = tx().auditFrom(AccessType.DELETE, PRIVILEGE, USER, this.username);
tx().getAuditTrail().add(tx(), audit);
}
diff --git a/service/src/main/java/li/strolch/service/privilege/users/PrivilegeUpdateUserRolesService.java b/service/src/main/java/li/strolch/service/privilege/users/PrivilegeUpdateUserRolesService.java
deleted file mode 100644
index cd63191e6..000000000
--- a/service/src/main/java/li/strolch/service/privilege/users/PrivilegeUpdateUserRolesService.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright 2015 Robert von Burg
- *
- * 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.service.privilege.users;
-
-import java.util.HashSet;
-import java.util.Set;
-
-import com.google.gson.JsonArray;
-import li.strolch.model.audit.AccessType;
-import li.strolch.model.audit.Audit;
-import li.strolch.persistence.api.StrolchTransaction;
-import li.strolch.privilege.handler.PrivilegeHandler;
-import li.strolch.privilege.model.UserRep;
-import li.strolch.runtime.StrolchConstants.StrolchPrivilegeConstants;
-import li.strolch.service.JsonServiceArgument;
-import li.strolch.service.api.AbstractService;
-import li.strolch.service.api.ServiceResultState;
-
-/**
- * @author Robert von Burg
- */
-public class PrivilegeUpdateUserRolesService extends AbstractService {
-
- @Override
- protected PrivilegeUserResult getResultInstance() {
- return new PrivilegeUserResult(ServiceResultState.FAILED);
- }
-
- @Override
- public JsonServiceArgument getArgumentInstance() {
- return new JsonServiceArgument();
- }
-
- @Override
- protected PrivilegeUserResult internalDoService(JsonServiceArgument arg) {
-
- li.strolch.runtime.privilege.PrivilegeHandler strolchPrivilegeHandler = getContainer().getPrivilegeHandler();
- PrivilegeHandler privilegeHandler = strolchPrivilegeHandler.getPrivilegeHandler();
-
- JsonArray rolesE = arg.jsonElement.getAsJsonArray();
- Set roles = new HashSet<>();
- rolesE.forEach(e -> roles.add(e.getAsString()));
-
- String username = arg.objectId;
-
- UserRep user;
- try (StrolchTransaction tx = openArgOrUserTx(arg, PrivilegeHandler.PRIVILEGE_ADD_ROLE_TO_USER)) {
- tx.setSuppressAudits(true);
-
- user = privilegeHandler.getUser(getCertificate(), username);
-
- // first add new roles
- boolean changed = false;
- for (String role : roles) {
- if (!user.hasRole(role)) {
- user = privilegeHandler.addRoleToUser(getCertificate(), username, role);
- changed = true;
- }
- }
-
- // handle removed roles
- for (String role : user.getRoles()) {
- if (!roles.contains(role)) {
- user = privilegeHandler.removeRoleFromUser(getCertificate(), username, role);
- changed = true;
- }
- }
-
- if (changed) {
-
- if (privilegeHandler.isPersistOnUserDataChanged())
- privilegeHandler.persist(getCertificate());
-
- Audit audit = tx.auditFrom(AccessType.UPDATE, StrolchPrivilegeConstants.PRIVILEGE,
- StrolchPrivilegeConstants.USER, user.getUsername());
- tx.getAuditTrail().add(tx, audit);
- }
- }
-
- return new PrivilegeUserResult(user);
- }
-}
diff --git a/service/src/main/java/li/strolch/service/privilege/users/PrivilegeUpdateUserService.java b/service/src/main/java/li/strolch/service/privilege/users/PrivilegeUpdateUserService.java
index 634714e54..d2cff7a1a 100644
--- a/service/src/main/java/li/strolch/service/privilege/users/PrivilegeUpdateUserService.java
+++ b/service/src/main/java/li/strolch/service/privilege/users/PrivilegeUpdateUserService.java
@@ -49,7 +49,7 @@ public class PrivilegeUpdateUserService extends AbstractService
*/
@@ -40,12 +40,14 @@ public class PrivilegeAddUserCommandTest extends AbstractRealmCommandTest {
@Override
protected Command getCommandInstance(StrolchTransaction tx) {
+ Set groups = new HashSet<>();
+ groups.add("AppGroups");
Set roles = new HashSet<>();
roles.add("AppUser");
Map propertyMap = new HashMap<>();
- UserRep user = new UserRep(null, "dude", "Jeff", "Lebowski", UserState.ENABLED, roles, Locale.getDefault(),
- propertyMap, null);
+ UserRep user = new UserRep(null, "dude", "Jeff", "Lebowski", UserState.ENABLED, groups, roles,
+ Locale.getDefault(), propertyMap, null);
PrivilegeAddUserCommand command = new PrivilegeAddUserCommand(tx);
command.setUserIn(user);
diff --git a/service/src/test/java/li/strolch/service/privilege/users/PrivilegeAddUserServiceTest.java b/service/src/test/java/li/strolch/service/privilege/users/PrivilegeAddUserServiceTest.java
index 1d4a701bf..97d0ce8b9 100644
--- a/service/src/test/java/li/strolch/service/privilege/users/PrivilegeAddUserServiceTest.java
+++ b/service/src/test/java/li/strolch/service/privilege/users/PrivilegeAddUserServiceTest.java
@@ -43,12 +43,14 @@ public class PrivilegeAddUserServiceTest extends AbstractRealmServiceTest groups = new HashSet<>();
+ groups.add("AppGroups");
Set roles = new HashSet<>();
roles.add("AppUser");
Map propertyMap = new HashMap<>();
PrivilegeUserArgument arg = new PrivilegeUserArgument();
- arg.user = new UserRep(null, "dude", "Jeff", "Lebowski", UserState.ENABLED, roles, Locale.getDefault(),
+ arg.user = new UserRep(null, "dude", "Jeff", "Lebowski", UserState.ENABLED, groups, roles, Locale.getDefault(),
propertyMap, null);
return arg;
diff --git a/service/src/test/java/li/strolch/service/test/ServiceTest.java b/service/src/test/java/li/strolch/service/test/ServiceTest.java
index e6fde9997..6d06ed5f5 100644
--- a/service/src/test/java/li/strolch/service/test/ServiceTest.java
+++ b/service/src/test/java/li/strolch/service/test/ServiceTest.java
@@ -33,6 +33,7 @@ import li.strolch.service.test.model.GreetingResult;
import li.strolch.service.test.model.GreetingService;
import li.strolch.service.test.model.GreetingService.GreetingArgument;
import li.strolch.service.test.model.TestService;
+import li.strolch.utils.dbc.DBC;
import org.junit.Test;
/**
@@ -42,11 +43,11 @@ public class ServiceTest extends AbstractServiceTest {
@Test
public void shouldFailInvalidCertificate1() {
- assertThrows(PrivilegeException.class, () -> {
+ assertThrows(DBC.DbcException.class, () -> {
TestService testService = new TestService();
getServiceHandler().doService(
new Certificate(null, null, null, null, null, null, null, null, ZonedDateTime.now(), false, null,
- new HashSet<>(), null), testService);
+ new HashSet<>(), new HashSet<>(), null), testService);
});
}
@@ -54,7 +55,7 @@ public class ServiceTest extends AbstractServiceTest {
public void shouldFailInvalidCertificate2() {
TestService testService = new TestService();
Certificate badCert = new Certificate(Usage.ANY, "1", "bob", "Bob", "Brown", UserState.ENABLED, "dsdf", "asd",
- ZonedDateTime.now(), false, null, new HashSet<>(), null);
+ ZonedDateTime.now(), false, null, new HashSet<>(), new HashSet<>(), null);
ServiceResult svcResult = getServiceHandler().doService(badCert, testService);
assertThat(svcResult.getThrowable(), instanceOf(NotAuthenticatedException.class));
}
@@ -67,8 +68,7 @@ public class ServiceTest extends AbstractServiceTest {
try {
TestService testService = new TestService();
ServiceResult svcResult = getServiceHandler().doService(certificate, testService);
- assertThat(svcResult.getMessage(),
- containsString("User jill may not perform service TestService"));
+ assertThat(svcResult.getMessage(), containsString("User jill may not perform service TestService"));
assertThat(svcResult.getThrowable(), instanceOf(AccessDeniedException.class));
} finally {
runtimeMock.getPrivilegeHandler().invalidate(certificate);
diff --git a/service/src/test/resources/executiontest/config/PrivilegeConfig.xml b/service/src/test/resources/executiontest/config/PrivilegeConfig.xml
index d04da193e..b2a9b4bf6 100644
--- a/service/src/test/resources/executiontest/config/PrivilegeConfig.xml
+++ b/service/src/test/resources/executiontest/config/PrivilegeConfig.xml
@@ -1,40 +1,21 @@
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
@@ -42,5 +23,4 @@
-
\ No newline at end of file
diff --git a/service/src/test/resources/migrationstest/config/PrivilegeConfig.xml b/service/src/test/resources/migrationstest/config/PrivilegeConfig.xml
index d04da193e..b2a9b4bf6 100644
--- a/service/src/test/resources/migrationstest/config/PrivilegeConfig.xml
+++ b/service/src/test/resources/migrationstest/config/PrivilegeConfig.xml
@@ -1,40 +1,21 @@
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
@@ -42,5 +23,4 @@
-
\ No newline at end of file
diff --git a/service/src/test/resources/reporttest/config/PrivilegeConfig.xml b/service/src/test/resources/reporttest/config/PrivilegeConfig.xml
index d04da193e..b2a9b4bf6 100644
--- a/service/src/test/resources/reporttest/config/PrivilegeConfig.xml
+++ b/service/src/test/resources/reporttest/config/PrivilegeConfig.xml
@@ -1,40 +1,21 @@
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
@@ -42,5 +23,4 @@
-
\ No newline at end of file
diff --git a/service/src/test/resources/svctest/config/PrivilegeConfig.xml b/service/src/test/resources/svctest/config/PrivilegeConfig.xml
index d04da193e..b2a9b4bf6 100644
--- a/service/src/test/resources/svctest/config/PrivilegeConfig.xml
+++ b/service/src/test/resources/svctest/config/PrivilegeConfig.xml
@@ -1,40 +1,21 @@
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
@@ -42,5 +23,4 @@
-
\ No newline at end of file
diff --git a/service/src/test/resources/svctest/config/PrivilegeGroups.xml b/service/src/test/resources/svctest/config/PrivilegeGroups.xml
new file mode 100644
index 000000000..735d8c42e
--- /dev/null
+++ b/service/src/test/resources/svctest/config/PrivilegeGroups.xml
@@ -0,0 +1,8 @@
+
+
+
+
+ AppGroup
+
+
+
\ No newline at end of file
diff --git a/service/src/test/resources/svctest/config/PrivilegeRoles.xml b/service/src/test/resources/svctest/config/PrivilegeRoles.xml
index 754344715..b23138789 100644
--- a/service/src/test/resources/svctest/config/PrivilegeRoles.xml
+++ b/service/src/test/resources/svctest/config/PrivilegeRoles.xml
@@ -1,174 +1,174 @@
-
-
- li.strolch.runtime.privilege.StrolchSystemAction
- li.strolch.runtime.privilege.StrolchSystemActionWithResult
- li.strolch.persistence.postgresql.PostgreSqlSchemaInitializer
-
-
- true
-
-
- true
-
+
+
+ li.strolch.runtime.privilege.StrolchSystemAction
+ li.strolch.runtime.privilege.StrolchSystemActionWithResult
+ li.strolch.persistence.postgresql.PostgreSqlSchemaInitializer
+
+
+ true
+
+
+ true
+
-
- true
-
-
- true
-
-
- true
-
-
- true
-
-
- true
-
-
- true
-
-
- true
-
-
- true
-
-
- true
-
-
- true
-
-
- true
-
-
- true
-
-
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
-
-
- true
-
-
- true
-
+
+
+ true
+
+
+ true
+
+
-
- Bike
-
-
- Bike
-
-
- Bike
-
-
- Bike
-
-
- Bike
-
-
- Bike
-
-
- Bike
-
-
- Bike
-
-
- Bike
-
-
- Bike
-
-
- Bike
-
-
- Bike
-
-
+
+
+ true
+
+
+ true
+
-
-
- li.strolch.service.privilege.users.PrivilegeUpdateUserService
- li.strolch.service.privilege.users.PrivilegeUpdateUserRolesService
- li.strolch.service.privilege.users.PrivilegeSetUserPasswordService
- li.strolch.service.privilege.users.PrivilegeSetUserLocaleService
- li.strolch.service.privilege.users.PrivilegeRemoveUserService
- li.strolch.service.privilege.users.PrivilegeRemoveRoleFromUserService
- li.strolch.service.privilege.users.PrivilegeAddUserService
- li.strolch.service.privilege.users.PrivilegeAddRoleToUserService
- li.strolch.service.privilege.roles.PrivilegeUpdateRoleService
- li.strolch.service.privilege.roles.PrivilegeRemoveRoleService
- li.strolch.service.privilege.roles.PrivilegeRemovePrivilegeFromRoleService
- li.strolch.service.privilege.roles.PrivilegeAddRoleService
- li.strolch.service.privilege.roles.PrivilegeAddOrReplacePrivilegeOnRoleService
-
-
- true
-
-
- true
-
-
- true
-
-
- true
-
-
- true
-
-
- true
-
-
- Reload
- GetPolicies
- Persist
- GetCertificates
- PersistSessions
-
-
- true
-
-
- SYSTEM
- DISABLED
- ENABLED
-
-
- true
-
-
- true
-
-
- true
-
-
- true
-
-
- true
-
-
- true
-
-
- true
-
-
- true
-
-
+
+ Bike
+
+
+ Bike
+
+
+ Bike
+
+
+ Bike
+
+
+ Bike
+
+
+ Bike
+
+
+ Bike
+
+
+ Bike
+
+
+ Bike
+
+
+ Bike
+
+
+ Bike
+
+
+ Bike
+
+
+
+
+
+ true
+
+
+ true
+
+
+ GetCertificates
+ GetPolicies
+ Persist
+ PersistSessions
+ Reload
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+ SYSTEM
+ DISABLED
+ ENABLED
+
+
+ true
+
+
+ li.strolch.service.privilege.roles.PrivilegeAddRoleService
+ li.strolch.service.privilege.roles.PrivilegeRemoveRoleService
+ li.strolch.service.privilege.roles.PrivilegeUpdateRoleService
+ li.strolch.service.privilege.users.PrivilegeAddUserService
+ li.strolch.service.privilege.users.PrivilegeRemoveUserService
+ li.strolch.service.privilege.users.PrivilegeSetUserLocaleService
+ li.strolch.service.privilege.users.PrivilegeSetUserPasswordService
+ li.strolch.service.privilege.users.PrivilegeSetUserStateService
+ li.strolch.service.privilege.users.PrivilegeUpdateUserRolesService
+ li.strolch.service.privilege.users.PrivilegeUpdateUserService
+
+
diff --git a/service/src/test/resources/svctest/config/PrivilegeUsers.xml b/service/src/test/resources/svctest/config/PrivilegeUsers.xml
index df7c74820..371fe63ce 100644
--- a/service/src/test/resources/svctest/config/PrivilegeUsers.xml
+++ b/service/src/test/resources/svctest/config/PrivilegeUsers.xml
@@ -1,28 +1,28 @@
-
- SYSTEM
-
- agent
-
-
-
- Application
- Administrator
- ENABLED
- en-GB
-
- AppUser
-
-
-
- Application
- Administrator
- ENABLED
- en-GB
-
- AppUser
- PrivilegeAdmin
-
-
+
+ SYSTEM
+
+ agent
+
+
+
+ Application
+ Administrator
+ ENABLED
+ en-GB
+
+ AppUser
+
+
+
+ Application
+ Administrator
+ ENABLED
+ en-GB
+
+ AppUser
+ PrivilegeAdmin
+
+
diff --git a/service/src/test/resources/transienttest/config/PrivilegeConfig.xml b/service/src/test/resources/transienttest/config/PrivilegeConfig.xml
index d04da193e..b2a9b4bf6 100644
--- a/service/src/test/resources/transienttest/config/PrivilegeConfig.xml
+++ b/service/src/test/resources/transienttest/config/PrivilegeConfig.xml
@@ -1,40 +1,21 @@
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
@@ -42,5 +23,4 @@
-
\ No newline at end of file
diff --git a/service/src/test/resources/withPrivilegeRuntime/config/PrivilegeConfig.xml b/service/src/test/resources/withPrivilegeRuntime/config/PrivilegeConfig.xml
index d04da193e..b2a9b4bf6 100644
--- a/service/src/test/resources/withPrivilegeRuntime/config/PrivilegeConfig.xml
+++ b/service/src/test/resources/withPrivilegeRuntime/config/PrivilegeConfig.xml
@@ -1,40 +1,21 @@
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
@@ -42,5 +23,4 @@
-
\ No newline at end of file
diff --git a/test-performance/src/runtime_postgresql/config/PrivilegeConfig.xml b/test-performance/src/runtime_postgresql/config/PrivilegeConfig.xml
index 9cdb99fa5..31f6561d6 100644
--- a/test-performance/src/runtime_postgresql/config/PrivilegeConfig.xml
+++ b/test-performance/src/runtime_postgresql/config/PrivilegeConfig.xml
@@ -8,7 +8,6 @@
-
diff --git a/test-performance/src/runtime_postgresql_json/config/PrivilegeConfig.xml b/test-performance/src/runtime_postgresql_json/config/PrivilegeConfig.xml
index 9cdb99fa5..31f6561d6 100644
--- a/test-performance/src/runtime_postgresql_json/config/PrivilegeConfig.xml
+++ b/test-performance/src/runtime_postgresql_json/config/PrivilegeConfig.xml
@@ -8,7 +8,6 @@
-
diff --git a/test-performance/src/runtime_postgresql_versioning/config/PrivilegeConfig.xml b/test-performance/src/runtime_postgresql_versioning/config/PrivilegeConfig.xml
index afa9daf94..b2a9b4bf6 100644
--- a/test-performance/src/runtime_postgresql_versioning/config/PrivilegeConfig.xml
+++ b/test-performance/src/runtime_postgresql_versioning/config/PrivilegeConfig.xml
@@ -1,46 +1,26 @@
-
-
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
+
+
+
+
-
\ No newline at end of file
diff --git a/test-performance/src/runtime_transient/config/PrivilegeConfig.xml b/test-performance/src/runtime_transient/config/PrivilegeConfig.xml
index 9cdb99fa5..31f6561d6 100644
--- a/test-performance/src/runtime_transient/config/PrivilegeConfig.xml
+++ b/test-performance/src/runtime_transient/config/PrivilegeConfig.xml
@@ -8,7 +8,6 @@
-
diff --git a/test-performance/src/runtime_xml/config/PrivilegeConfig.xml b/test-performance/src/runtime_xml/config/PrivilegeConfig.xml
index 9cdb99fa5..31f6561d6 100644
--- a/test-performance/src/runtime_xml/config/PrivilegeConfig.xml
+++ b/test-performance/src/runtime_xml/config/PrivilegeConfig.xml
@@ -8,7 +8,6 @@
-
diff --git a/utils/src/main/java/li/strolch/utils/helper/NetworkHelper.java b/utils/src/main/java/li/strolch/utils/helper/NetworkHelper.java
index 54eb033c2..0cec120ae 100644
--- a/utils/src/main/java/li/strolch/utils/helper/NetworkHelper.java
+++ b/utils/src/main/java/li/strolch/utils/helper/NetworkHelper.java
@@ -1,12 +1,19 @@
package li.strolch.utils.helper;
-import java.net.Inet4Address;
-import java.net.InetAddress;
-import java.net.NetworkInterface;
-import java.net.SocketException;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.List;
+import java.io.File;
+import java.io.IOException;
+import java.net.*;
+import java.nio.file.Path;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+
+import static java.nio.file.Files.readAllLines;
+import static java.nio.file.Files.readString;
+import static java.util.Spliterator.ORDERED;
+import static java.util.Spliterators.spliteratorUnknownSize;
public class NetworkHelper {
@@ -33,13 +40,101 @@ public class NetworkHelper {
return inet4Addresses;
}
+ public static String formatMacAddress(NetworkInterface networkInterface) {
+ try {
+ return formatMacAddress(networkInterface.getHardwareAddress());
+ } catch (SocketException e) {
+ throw new IllegalStateException(
+ "Failed to get hardware address for network interface " + networkInterface.getDisplayName(), e);
+ }
+ }
+
public static String formatMacAddress(byte[] bytes) {
StringBuilder sb = new StringBuilder(17);
for (byte b : bytes) {
- if (sb.length() > 0)
+ if (!sb.isEmpty())
sb.append(':');
sb.append(String.format("%02x", b));
}
return sb.toString();
}
+
+ public static void main(String[] args) throws IOException {
+
+ Stream interfaceStream = streamStrolchNetworkInterface();
+
+ interfaceStream.forEach(t -> System.out.printf("%20s: %s%n", t.name(), t.hwAddress()));
+ }
+
+ public static Stream streamStrolchNetworkInterface() {
+
+ if (!System.getProperty("os.name").equals("Linux")) {
+ Enumeration interfaces = null;
+ try {
+ interfaces = NetworkInterface.getNetworkInterfaces();
+ } catch (SocketException e) {
+ throw new IllegalStateException("Failed to read network interfaces ", e);
+ }
+ return StreamSupport.stream(spliteratorUnknownSize(interfaces.asIterator(), ORDERED), false).map(ni -> {
+ try {
+ List addresses = Collections.list(ni.getInetAddresses());
+ if (addresses.isEmpty())
+ addresses = List.of(Inet4Address.getByName("0.0.0.0"));
+ return new StrolchNetworkInterface(ni.getName(), formatMacAddress(ni), addresses);
+ } catch (UnknownHostException e) {
+ throw new IllegalStateException("Failed to read information for device " + ni.getName(), e);
+ }
+ });
+ }
+
+ // Read all available device names
+ Pattern pattern = Pattern.compile("^ *(.*):");
+ List kernelInterfaceLines;
+ try {
+ kernelInterfaceLines = readAllLines(Path.of("/proc/net/dev"));
+ } catch (IOException e) {
+ throw new IllegalStateException("Failed to read /proc/net/dev", e);
+ }
+
+ return kernelInterfaceLines.stream().map(line -> {
+ Matcher m = pattern.matcher(line);
+ if (m.find())
+ return m.group(1).trim();
+ return null;
+ }).filter(Objects::nonNull).filter(device -> {
+ if (device.startsWith("br-"))
+ return false;
+ if (device.startsWith("veth"))
+ return false;
+ if (device.startsWith("docker"))
+ return false;
+ return true;
+ }).map(device -> {
+ try {
+ String hwAddress = readString(Path.of("/sys/class/net/" + device + "/address")).trim();
+ File operStateFile = new File("/sys/class/net/" + device + "/operstate");
+ File carrierFile = new File("/sys/class/net/" + device + "/carrier");
+ boolean hasNoCarrier;
+ if (operStateFile.exists()) {
+ hasNoCarrier = operStateFile.exists() && readString(operStateFile.toPath()).trim().equals("down");
+ } else {
+ hasNoCarrier = readString(carrierFile.toPath()).trim().equals("0");
+ }
+ if (hasNoCarrier)
+ return new StrolchNetworkInterface(device, hwAddress, List.of(Inet4Address.getByName("0.0.0.0")));
+
+ NetworkInterface ni = NetworkInterface.getByName(device);
+ if (ni.isLoopback() || ni.isPointToPoint() || ni.isVirtual())
+ return null;
+
+ List addresses = Collections.list(ni.getInetAddresses());
+ if (addresses.isEmpty())
+ addresses = List.of(Inet4Address.getByName("0.0.0.0"));
+ return new StrolchNetworkInterface(ni.getName(), hwAddress, addresses);
+
+ } catch (IOException e) {
+ throw new IllegalStateException("Failed to read information for device " + device, e);
+ }
+ }).filter(Objects::nonNull);
+ }
}
diff --git a/utils/src/main/java/li/strolch/utils/helper/StringHelper.java b/utils/src/main/java/li/strolch/utils/helper/StringHelper.java
index 21fa617f5..d2029c32d 100644
--- a/utils/src/main/java/li/strolch/utils/helper/StringHelper.java
+++ b/utils/src/main/java/li/strolch/utils/helper/StringHelper.java
@@ -85,23 +85,16 @@ public class StringHelper {
}
public static String toPrettyHexString(byte[] raw, int srcPos, int length) {
- byte[] hex = new byte[3 * length + (length / 8)];
- int index = srcPos;
-
- for (int i = srcPos; i < length; i++) {
- byte b = raw[i];
- int v = b & 0xFF;
- hex[index++] = HEX_CHAR_TABLE[v >>> 4];
- hex[index++] = HEX_CHAR_TABLE[v & 0xF];
- hex[index++] = ' ';
-
- if ((i + 1) % 8 == 0) {
- hex[index++] = ' ';
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < length; i++) {
+ sb.append(String.format("%02x", raw[i + srcPos]));
+ sb.append(' ');
+ if ((i + srcPos) % 8 == 0) {
+ sb.append(' ');
}
}
- return new String(hex, StandardCharsets.US_ASCII);
-
+ return sb.toString();
}
public static byte[] fromPrettyHexString(String prettyHex) {
diff --git a/utils/src/main/java/li/strolch/utils/helper/StrolchNetworkInterface.java b/utils/src/main/java/li/strolch/utils/helper/StrolchNetworkInterface.java
new file mode 100644
index 000000000..4262691d0
--- /dev/null
+++ b/utils/src/main/java/li/strolch/utils/helper/StrolchNetworkInterface.java
@@ -0,0 +1,12 @@
+package li.strolch.utils.helper;
+
+import java.net.InetAddress;
+import java.util.List;
+
+public record StrolchNetworkInterface(String name, String hwAddress, List inetAddresses) {
+ public StrolchNetworkInterface(String name, String hwAddress, List inetAddresses) {
+ this.name = name;
+ this.hwAddress = hwAddress;
+ this.inetAddresses = List.copyOf(inetAddresses);
+ }
+}
diff --git a/utils/src/main/java/li/strolch/utils/helper/XmlHelper.java b/utils/src/main/java/li/strolch/utils/helper/XmlHelper.java
index 76d9fbb93..06a6f48ba 100644
--- a/utils/src/main/java/li/strolch/utils/helper/XmlHelper.java
+++ b/utils/src/main/java/li/strolch/utils/helper/XmlHelper.java
@@ -15,12 +15,21 @@
*/
package li.strolch.utils.helper;
-import static li.strolch.utils.helper.FileHelper.getTempFile;
-
import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.Marshaller;
import jakarta.xml.bind.Unmarshaller;
import jakarta.xml.bind.annotation.XmlRootElement;
+import li.strolch.utils.RemoveCRFilterWriter;
+import li.strolch.utils.exceptions.XmlException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
import javax.xml.parsers.*;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Source;
@@ -33,16 +42,7 @@ import java.nio.file.Files;
import java.text.MessageFormat;
import java.util.Set;
-import li.strolch.utils.RemoveCRFilterWriter;
-import li.strolch.utils.exceptions.XmlException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.w3c.dom.DOMException;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-import org.xml.sax.helpers.DefaultHandler;
+import static li.strolch.utils.helper.FileHelper.getTempFile;
/**
* Helper class for performing XML based tasks
@@ -71,8 +71,7 @@ public class XmlHelper {
/**
* Parses an XML file on the file system and returns the resulting {@link Document} object
*
- * @param xmlFile
- * the {@link File} which has the path to the XML file to read
+ * @param xmlFile the {@link File} which has the path to the XML file to read
*/
public static void parseDocument(File xmlFile, DefaultHandler xmlHandler) {
@@ -92,8 +91,7 @@ public class XmlHelper {
/**
* Parses an XML file on the file system and returns the resulting {@link Document} object
*
- * @param xmlFileInputStream
- * the XML {@link InputStream} which is to be parsed
+ * @param xmlFileInputStream the XML {@link InputStream} which is to be parsed
*/
public static void parseDocument(InputStream xmlFileInputStream, DefaultHandler xmlHandler) {
@@ -116,8 +114,7 @@ public class XmlHelper {
/**
* Parses an XML file on the file system and returns the resulting {@link Document} object
*
- * @param xmlInputSource
- * the XML {@link InputSource} which is to be parsed
+ * @param xmlInputSource the XML {@link InputSource} which is to be parsed
*/
public static void parseDocument(InputSource xmlInputSource, DefaultHandler xmlHandler) {
parseDocument(xmlInputSource, xmlHandler, false);
@@ -126,10 +123,8 @@ public class XmlHelper {
/**
* Parses an XML file on the file system and returns the resulting {@link Document} object
*
- * @param xmlInputSource
- * the XML {@link InputSource} which is to be parsed
- * @param nsAware
- * if true, then calls {@link SAXParserFactory#setNamespaceAware(boolean)}
+ * @param xmlInputSource the XML {@link InputSource} which is to be parsed
+ * @param nsAware if true, then calls {@link SAXParserFactory#setNamespaceAware(boolean)}
*/
public static void parseDocument(InputSource xmlInputSource, DefaultHandler xmlHandler, boolean nsAware) {
@@ -156,12 +151,9 @@ public class XmlHelper {
*
* Note: The passed class must have the {@link XmlRootElement} annotation!
*
- * @param file
- * the file to parse
- * @param clazz
- * the class for the returning object type
- * @param
- * the type of object to return
+ * @param file the file to parse
+ * @param clazz the class for the returning object type
+ * @param the type of object to return
*
* @return the parsed object
*/
@@ -171,8 +163,7 @@ public class XmlHelper {
JAXBContext jaxbContext = JAXBContext.newInstance(clazz);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
- @SuppressWarnings("unchecked")
- T o = (T) unmarshaller.unmarshal(fin);
+ @SuppressWarnings("unchecked") T o = (T) unmarshaller.unmarshal(fin);
return o;
@@ -185,13 +176,11 @@ public class XmlHelper {
/**
* Writes an {@link Element} to an XML file on the file system
*
- * @param rootElement
- * the {@link Element} to write to the file system
- * @param file
- * the {@link File} describing the path on the file system where the XML file should be written to
+ * @param rootElement the {@link Element} to write to the file system
+ * @param file the {@link File} describing the path on the file system where the XML file should be written
+ * to
*
- * @throws RuntimeException
- * if something went wrong while creating the XML configuration, or writing the element
+ * @throws RuntimeException if something went wrong while creating the XML configuration, or writing the element
*/
public static void writeElement(Element rootElement, File file) throws RuntimeException {
Document document = createDocument();
@@ -202,13 +191,10 @@ public class XmlHelper {
/**
* Writes a {@link Document} to an XML file on the file system
*
- * @param document
- * the {@link Document} to write to the file system
- * @param file
- * the {@link File} describing the path on the file system where the XML file should be written to
+ * @param document the {@link Document} to write to the file system
+ * @param file the {@link File} describing the path on the file system where the XML file should be written to
*
- * @throws RuntimeException
- * if something went wrong while creating the XML configuration, or writing the element
+ * @throws RuntimeException if something went wrong while creating the XML configuration, or writing the element
*/
public static void writeDocument(Document document, File file) throws RuntimeException {
writeDocument(document, file, DEFAULT_ENCODING);
@@ -217,15 +203,11 @@ public class XmlHelper {
/**
* Writes a {@link Document} to an XML file on the file system
*
- * @param document
- * the {@link Document} to write to the file system
- * @param file
- * the {@link File} describing the path on the file system where the XML file should be written to
- * @param encoding
- * encoding to use to write the file
+ * @param document the {@link Document} to write to the file system
+ * @param file the {@link File} describing the path on the file system where the XML file should be written to
+ * @param encoding encoding to use to write the file
*
- * @throws RuntimeException
- * if something went wrong while creating the XML configuration, or writing the element
+ * @throws RuntimeException if something went wrong while creating the XML configuration, or writing the element
*/
public static void writeDocument(Document document, File file, String encoding) throws RuntimeException {
try (FileOutputStream out = new FileOutputStream(file)) {
@@ -239,13 +221,10 @@ public class XmlHelper {
/**
* Writes a {@link Document} to an XML file on the file system
*
- * @param document
- * the {@link Document} to write to the file system
- * @param out
- * stream to write document to
+ * @param document the {@link Document} to write to the file system
+ * @param out stream to write document to
*
- * @throws RuntimeException
- * if something went wrong while creating the XML configuration, or writing the element
+ * @throws RuntimeException if something went wrong while creating the XML configuration, or writing the element
*/
public static void writeDocument(Document document, OutputStream out) throws RuntimeException {
writeDocument(document, new StreamResult(new RemoveCRFilterWriter(new OutputStreamWriter(out))),
@@ -255,11 +234,9 @@ public class XmlHelper {
/**
* Writes a {@link Document} to an XML file on the file system
*
- * @param document
- * the {@link Document} to write to the file system
+ * @param document the {@link Document} to write to the file system
*
- * @throws RuntimeException
- * if something went wrong while creating the XML configuration, or writing the element
+ * @throws RuntimeException if something went wrong while creating the XML configuration, or writing the element
*/
public static String writeToString(Document document) throws RuntimeException {
try {
@@ -275,15 +252,11 @@ public class XmlHelper {
/**
* Writes a {@link Document} to an XML file on the file system
*
- * @param document
- * the {@link Document} to write to the file system
- * @param streamResult
- * the destination
- * @param encoding
- * encoding to use to write the file
+ * @param document the {@link Document} to write to the file system
+ * @param streamResult the destination
+ * @param encoding encoding to use to write the file
*
- * @throws RuntimeException
- * if something went wrong while creating the XML configuration, or writing the element
+ * @throws RuntimeException if something went wrong while creating the XML configuration, or writing the element
*/
public static void writeDocument(Document document, StreamResult streamResult, String encoding)
throws RuntimeException {
@@ -307,8 +280,7 @@ public class XmlHelper {
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.ENCODING, docEncoding);
- transformer.setOutputProperty("{http://xml.apache.org/xalan}indent-amount",
- "2"); //$NON-NLS-2$
+ transformer.setOutputProperty("{http://xml.apache.org/xalan}indent-amount", "2"); //$NON-NLS-2$
// transformer.setOutputProperty("{http://xml.apache.org/xalan}line-separator", "\t");
// Transform to file
@@ -330,8 +302,7 @@ public class XmlHelper {
*
* @return a new document instance
*
- * @throws RuntimeException
- * if something went wrong while creating the XML configuration
+ * @throws RuntimeException if something went wrong while creating the XML configuration
*/
public static Document createDocument() throws RuntimeException {
try {
@@ -354,13 +325,10 @@ public class XmlHelper {
/**
* Marshalls the given element annotated with xml annotations to the given destination file
*
- * @param dstFile
- * the destination to marshall the object
- * @param object
- * the object to marshall
+ * @param dstFile the destination to marshall the object
+ * @param object the object to marshall
*
- * @throws Exception
- * if the marshalling fails for any reason
+ * @throws Exception if the marshalling fails for any reason
*/
public static void marshall(File dstFile, Object object) throws Exception {
diff --git a/web-rest/src/main/java/li/strolch/rest/RestfulStrolchComponent.java b/web-rest/src/main/java/li/strolch/rest/RestfulStrolchComponent.java
index 51283268b..d25d616ab 100644
--- a/web-rest/src/main/java/li/strolch/rest/RestfulStrolchComponent.java
+++ b/web-rest/src/main/java/li/strolch/rest/RestfulStrolchComponent.java
@@ -25,6 +25,7 @@ import li.strolch.rest.filters.AccessControlResponseFilter;
import li.strolch.rest.filters.HttpCacheResponseFilter;
import li.strolch.runtime.configuration.ComponentConfiguration;
import li.strolch.runtime.privilege.PrivilegeHandler;
+import li.strolch.runtime.sessions.StrolchSessionHandler;
import li.strolch.service.api.ServiceHandler;
import li.strolch.utils.dbc.DBC;
diff --git a/web-rest/src/main/java/li/strolch/rest/StrolchRestfulExceptionMapper.java b/web-rest/src/main/java/li/strolch/rest/StrolchRestfulExceptionMapper.java
index a28d3a790..df0985f75 100644
--- a/web-rest/src/main/java/li/strolch/rest/StrolchRestfulExceptionMapper.java
+++ b/web-rest/src/main/java/li/strolch/rest/StrolchRestfulExceptionMapper.java
@@ -43,14 +43,14 @@ public class StrolchRestfulExceptionMapper implements ExceptionMapper
if (ex instanceof NotFoundException)
return ResponseUtil.toResponse(Status.NOT_FOUND, ex);
- if (ex instanceof StrolchAccessDeniedException e)
- return ResponseUtil.toResponse(Status.FORBIDDEN, e.getI18n());
-
if (ex instanceof StrolchNotAuthenticatedException e) {
logger.error("User tried to access resource, but was not authenticated: " + ex.getMessage());
return Response.status(Status.UNAUTHORIZED).entity(e.getMessage()).type(MediaType.TEXT_PLAIN).build();
}
+ if (ex instanceof StrolchAccessDeniedException e)
+ return ResponseUtil.toResponse(Status.FORBIDDEN, e.getI18n());
+
return ResponseUtil.toResponse(ex);
}
}
\ No newline at end of file
diff --git a/web-rest/src/main/java/li/strolch/rest/endpoint/AuthenticationService.java b/web-rest/src/main/java/li/strolch/rest/endpoint/AuthenticationService.java
index cfbdc9faa..d288b94b3 100644
--- a/web-rest/src/main/java/li/strolch/rest/endpoint/AuthenticationService.java
+++ b/web-rest/src/main/java/li/strolch/rest/endpoint/AuthenticationService.java
@@ -37,11 +37,11 @@ import li.strolch.privilege.base.AccessDeniedException;
import li.strolch.privilege.base.InvalidCredentialsException;
import li.strolch.privilege.base.PrivilegeException;
import li.strolch.privilege.model.Certificate;
-import li.strolch.privilege.model.IPrivilege;
+import li.strolch.privilege.model.Privilege;
import li.strolch.privilege.model.PrivilegeContext;
import li.strolch.privilege.model.Usage;
import li.strolch.rest.RestfulStrolchComponent;
-import li.strolch.rest.StrolchSessionHandler;
+import li.strolch.runtime.sessions.StrolchSessionHandler;
import li.strolch.rest.helper.ResponseUtil;
import li.strolch.runtime.privilege.PrivilegeHandler;
import li.strolch.utils.helper.ExceptionHelper;
@@ -401,7 +401,7 @@ public class AuthenticationService {
loginResult.add("privileges", privArr);
for (String name : privilegeContext.getPrivilegeNames()) {
- IPrivilege privilege = privilegeContext.getPrivilege(name);
+ Privilege privilege = privilegeContext.getPrivilege(name);
JsonObject privObj = new JsonObject();
privArr.add(privObj);
diff --git a/web-rest/src/main/java/li/strolch/rest/endpoint/PrivilegeRolesService.java b/web-rest/src/main/java/li/strolch/rest/endpoint/PrivilegeRolesService.java
index adcde1fa9..2f203d1e6 100644
--- a/web-rest/src/main/java/li/strolch/rest/endpoint/PrivilegeRolesService.java
+++ b/web-rest/src/main/java/li/strolch/rest/endpoint/PrivilegeRolesService.java
@@ -15,23 +15,18 @@
*/
package li.strolch.rest.endpoint;
-import static java.util.Comparator.comparing;
-import static li.strolch.privilege.handler.PrivilegeHandler.PRIVILEGE_GET_ROLE;
-
+import com.google.gson.JsonArray;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
-
-import com.google.gson.JsonArray;
import li.strolch.agent.api.ComponentContainer;
import li.strolch.model.json.PrivilegeElementFromJsonVisitor;
import li.strolch.model.json.PrivilegeElementToJsonVisitor;
import li.strolch.persistence.api.StrolchTransaction;
import li.strolch.privilege.handler.PrivilegeHandler;
import li.strolch.privilege.model.Certificate;
-import li.strolch.privilege.model.PrivilegeRep;
import li.strolch.privilege.model.RoleRep;
import li.strolch.rest.RestfulStrolchComponent;
import li.strolch.rest.StrolchRestfulConstants;
@@ -39,6 +34,9 @@ import li.strolch.rest.helper.ResponseUtil;
import li.strolch.service.api.ServiceHandler;
import li.strolch.service.privilege.roles.*;
+import static java.util.Comparator.comparing;
+import static li.strolch.privilege.handler.PrivilegeHandler.PRIVILEGE_GET_ROLE;
+
/**
* @author Robert von Burg
*/
@@ -147,50 +145,11 @@ public class PrivilegeRolesService {
return handleServiceResult(svcResult);
}
- @PUT
- @Consumes(MediaType.APPLICATION_JSON)
- @Produces(MediaType.APPLICATION_JSON)
- @Path("{roleName}/privileges")
- public Response addOrReplacePrivilegeOnRole(@Context HttpServletRequest request,
- @PathParam("roleName") String roleName, String data) {
- Certificate cert = (Certificate) request.getAttribute(StrolchRestfulConstants.STROLCH_CERTIFICATE);
-
- PrivilegeRep privilegeRep = new PrivilegeElementFromJsonVisitor().privilegeRepFromJson(data);
-
- ServiceHandler svcHandler = RestfulStrolchComponent.getInstance().getComponent(ServiceHandler.class);
- PrivilegeAddOrReplacePrivilegeOnRoleService svc = new PrivilegeAddOrReplacePrivilegeOnRoleService();
- PrivilegeAddOrReplacePrivilegeOnRoleArgument arg = new PrivilegeAddOrReplacePrivilegeOnRoleArgument();
- arg.roleName = roleName;
- arg.privilegeRep = privilegeRep;
-
- PrivilegeRoleResult svcResult = svcHandler.doService(cert, svc, arg);
- return handleServiceResult(svcResult);
- }
-
- @DELETE
- @Consumes(MediaType.APPLICATION_JSON)
- @Produces(MediaType.APPLICATION_JSON)
- @Path("{roleName}/privileges/{privilege}")
- public Response removePrivilegeFromRole(@Context HttpServletRequest request, @PathParam("roleName") String roleName,
- @PathParam("privilege") String privilege) {
- Certificate cert = (Certificate) request.getAttribute(StrolchRestfulConstants.STROLCH_CERTIFICATE);
-
- ServiceHandler svcHandler = RestfulStrolchComponent.getInstance().getComponent(ServiceHandler.class);
- PrivilegeRemovePrivilegeFromRoleService svc = new PrivilegeRemovePrivilegeFromRoleService();
- PrivilegeRemovePrivilegeFromRoleArgument arg = new PrivilegeRemovePrivilegeFromRoleArgument();
- arg.roleName = roleName;
- arg.privilegeName = privilege;
-
- PrivilegeRoleResult svcResult = svcHandler.doService(cert, svc, arg);
- return handleServiceResult(svcResult);
- }
-
private Response handleServiceResult(PrivilegeRoleResult svcResult) {
if (svcResult.isOk()) {
RoleRep roleRep = svcResult.getRole();
- return Response
- .ok(roleRep.accept(new PrivilegeElementToJsonVisitor()).toString(), MediaType.APPLICATION_JSON)
- .build();
+ return Response.ok(roleRep.accept(new PrivilegeElementToJsonVisitor()).toString(),
+ MediaType.APPLICATION_JSON).build();
}
return ResponseUtil.toResponse(svcResult);
}
diff --git a/web-rest/src/main/java/li/strolch/rest/endpoint/PrivilegeUsersService.java b/web-rest/src/main/java/li/strolch/rest/endpoint/PrivilegeUsersService.java
index 3823819c7..087e78511 100644
--- a/web-rest/src/main/java/li/strolch/rest/endpoint/PrivilegeUsersService.java
+++ b/web-rest/src/main/java/li/strolch/rest/endpoint/PrivilegeUsersService.java
@@ -15,19 +15,6 @@
*/
package li.strolch.rest.endpoint;
-import static jakarta.ws.rs.core.Response.Status.NOT_ACCEPTABLE;
-import static java.util.Comparator.comparing;
-import static li.strolch.privilege.handler.PrivilegeHandler.PRIVILEGE_GET_USER;
-import static li.strolch.rest.helper.ResponseUtil.toResponse;
-import static li.strolch.rest.helper.RestfulHelper.toJson;
-import static li.strolch.search.SearchBuilder.buildSimpleValueSearch;
-
-import java.text.MessageFormat;
-import java.util.Arrays;
-import java.util.Base64;
-import java.util.List;
-import java.util.Locale;
-
import com.google.gson.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.ws.rs.*;
@@ -46,11 +33,10 @@ import li.strolch.privilege.model.UserRep;
import li.strolch.privilege.model.UserState;
import li.strolch.rest.RestfulStrolchComponent;
import li.strolch.rest.StrolchRestfulConstants;
-import li.strolch.rest.StrolchSessionHandler;
+import li.strolch.runtime.sessions.StrolchSessionHandler;
import li.strolch.rest.model.QueryData;
import li.strolch.search.SearchResult;
import li.strolch.search.ValueSearch;
-import li.strolch.service.JsonServiceArgument;
import li.strolch.service.StringMapArgument;
import li.strolch.service.api.ServiceHandler;
import li.strolch.service.api.ServiceResult;
@@ -58,6 +44,19 @@ import li.strolch.service.privilege.users.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.text.MessageFormat;
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.List;
+import java.util.Locale;
+
+import static jakarta.ws.rs.core.Response.Status.NOT_ACCEPTABLE;
+import static java.util.Comparator.comparing;
+import static li.strolch.privilege.handler.PrivilegeHandler.PRIVILEGE_GET_USER;
+import static li.strolch.rest.helper.ResponseUtil.toResponse;
+import static li.strolch.rest.helper.RestfulHelper.toJson;
+import static li.strolch.search.SearchBuilder.buildSimpleValueSearch;
+
/**
* @author Robert von Burg
*/
@@ -191,60 +190,6 @@ public class PrivilegeUsersService {
return handleServiceResult(svcResult);
}
- @PUT
- @Consumes(MediaType.APPLICATION_JSON)
- @Produces(MediaType.APPLICATION_JSON)
- @Path("{username}/roles")
- public Response updateRolesOnUser(@PathParam("username") String username, String data,
- @Context HttpServletRequest request) {
- Certificate cert = (Certificate) request.getAttribute(StrolchRestfulConstants.STROLCH_CERTIFICATE);
-
- ServiceHandler svcHandler = RestfulStrolchComponent.getInstance().getComponent(ServiceHandler.class);
- PrivilegeUpdateUserRolesService svc = new PrivilegeUpdateUserRolesService();
- JsonServiceArgument arg = svc.getArgumentInstance();
- arg.objectId = username;
- arg.jsonElement = JsonParser.parseString(data);
-
- PrivilegeUserResult svcResult = svcHandler.doService(cert, svc, arg);
- return handleServiceResult(svcResult);
- }
-
- @PUT
- @Consumes(MediaType.APPLICATION_JSON)
- @Produces(MediaType.APPLICATION_JSON)
- @Path("{username}/roles/{rolename}")
- public Response addRoleToUser(@PathParam("username") String username, @PathParam("rolename") String rolename,
- @Context HttpServletRequest request) {
- Certificate cert = (Certificate) request.getAttribute(StrolchRestfulConstants.STROLCH_CERTIFICATE);
-
- ServiceHandler svcHandler = RestfulStrolchComponent.getInstance().getComponent(ServiceHandler.class);
- PrivilegeAddRoleToUserService svc = new PrivilegeAddRoleToUserService();
- PrivilegeRoleUserNamesArgument arg = new PrivilegeRoleUserNamesArgument();
- arg.username = username;
- arg.rolename = rolename;
-
- PrivilegeUserResult svcResult = svcHandler.doService(cert, svc, arg);
- return handleServiceResult(svcResult);
- }
-
- @DELETE
- @Consumes(MediaType.APPLICATION_JSON)
- @Produces(MediaType.APPLICATION_JSON)
- @Path("{username}/roles/{rolename}")
- public Response removeRoleFromUser(@PathParam("username") String username, @PathParam("rolename") String rolename,
- @Context HttpServletRequest request) {
- Certificate cert = (Certificate) request.getAttribute(StrolchRestfulConstants.STROLCH_CERTIFICATE);
-
- ServiceHandler svcHandler = RestfulStrolchComponent.getInstance().getComponent(ServiceHandler.class);
- PrivilegeRemoveRoleFromUserService svc = new PrivilegeRemoveRoleFromUserService();
- PrivilegeRoleUserNamesArgument arg = new PrivilegeRoleUserNamesArgument();
- arg.username = username;
- arg.rolename = rolename;
-
- PrivilegeUserResult svcResult = svcHandler.doService(cert, svc, arg);
- return handleServiceResult(svcResult);
- }
-
@PUT
@Produces(MediaType.APPLICATION_JSON)
@Path("{username}/state/{state}")
@@ -279,7 +224,7 @@ public class PrivilegeUsersService {
Locale locale;
try {
- locale = new Locale(localeS);
+ locale = Locale.forLanguageTag(localeS);
} catch (Exception e) {
String msg = MessageFormat.format("Locale {0} is not valid!", localeS);
return toResponse(msg);
diff --git a/web-rest/src/main/java/li/strolch/rest/endpoint/StrolchJobsResource.java b/web-rest/src/main/java/li/strolch/rest/endpoint/StrolchJobsResource.java
index 49d4b4a77..336975edd 100644
--- a/web-rest/src/main/java/li/strolch/rest/endpoint/StrolchJobsResource.java
+++ b/web-rest/src/main/java/li/strolch/rest/endpoint/StrolchJobsResource.java
@@ -33,7 +33,7 @@ import li.strolch.job.StrolchJob;
import li.strolch.job.StrolchJobsHandler;
import li.strolch.persistence.api.StrolchTransaction;
import li.strolch.privilege.model.Certificate;
-import li.strolch.privilege.model.IPrivilege;
+import li.strolch.privilege.model.Privilege;
import li.strolch.privilege.model.PrivilegeContext;
import li.strolch.rest.RestfulStrolchComponent;
import li.strolch.rest.StrolchRestfulConstants;
@@ -76,7 +76,7 @@ public class StrolchJobsResource {
if (ctx.hasRole(ROLE_STROLCH_ADMIN))
return true;
- IPrivilege privilege = ctx.getPrivilege(StrolchJob.class.getName());
+ Privilege privilege = ctx.getPrivilege(StrolchJob.class.getName());
return privilege.isAllAllowed() || privilege.getAllowList().contains(job.getClass().getName());
}) //
.sorted(comparing(StrolchJob::getName)) //
diff --git a/web-rest/src/main/java/li/strolch/rest/endpoint/UserSessionsService.java b/web-rest/src/main/java/li/strolch/rest/endpoint/UserSessionsService.java
index 16d5e2264..d1497a9db 100644
--- a/web-rest/src/main/java/li/strolch/rest/endpoint/UserSessionsService.java
+++ b/web-rest/src/main/java/li/strolch/rest/endpoint/UserSessionsService.java
@@ -37,10 +37,10 @@ import li.strolch.persistence.api.StrolchTransaction;
import li.strolch.privilege.model.Certificate;
import li.strolch.rest.RestfulStrolchComponent;
import li.strolch.rest.StrolchRestfulConstants;
-import li.strolch.rest.StrolchSessionHandler;
+import li.strolch.runtime.sessions.StrolchSessionHandler;
import li.strolch.rest.helper.ResponseUtil;
import li.strolch.rest.model.QueryData;
-import li.strolch.rest.model.UserSession;
+import li.strolch.runtime.sessions.UserSession;
import li.strolch.search.SearchResult;
import li.strolch.search.ValueSearch;
import org.slf4j.Logger;
diff --git a/web-rest/src/main/java/li/strolch/rest/filters/AuthenticationRequestFilter.java b/web-rest/src/main/java/li/strolch/rest/filters/AuthenticationRequestFilter.java
index bd1d0cc2a..770937818 100644
--- a/web-rest/src/main/java/li/strolch/rest/filters/AuthenticationRequestFilter.java
+++ b/web-rest/src/main/java/li/strolch/rest/filters/AuthenticationRequestFilter.java
@@ -15,17 +15,22 @@
*/
package li.strolch.rest.filters;
-import static li.strolch.rest.StrolchRestfulConstants.*;
-import static li.strolch.utils.helper.StringHelper.*;
-
import jakarta.annotation.Priority;
import jakarta.servlet.http.HttpServletRequest;
-
import jakarta.ws.rs.Priorities;
import jakarta.ws.rs.container.ContainerRequestContext;
import jakarta.ws.rs.container.ContainerRequestFilter;
import jakarta.ws.rs.core.*;
import jakarta.ws.rs.ext.Provider;
+import li.strolch.exception.StrolchAccessDeniedException;
+import li.strolch.exception.StrolchNotAuthenticatedException;
+import li.strolch.privilege.model.Certificate;
+import li.strolch.privilege.model.Usage;
+import li.strolch.rest.RestfulStrolchComponent;
+import li.strolch.rest.StrolchRestfulConstants;
+import li.strolch.runtime.sessions.StrolchSessionHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
@@ -33,15 +38,8 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
-import li.strolch.exception.StrolchAccessDeniedException;
-import li.strolch.exception.StrolchNotAuthenticatedException;
-import li.strolch.privilege.model.Certificate;
-import li.strolch.privilege.model.Usage;
-import li.strolch.rest.RestfulStrolchComponent;
-import li.strolch.rest.StrolchRestfulConstants;
-import li.strolch.rest.StrolchSessionHandler;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import static li.strolch.rest.StrolchRestfulConstants.*;
+import static li.strolch.utils.helper.StringHelper.*;
/**
* This authentication request filter secures any requests to a Strolch server, by verifying that the request contains
@@ -212,7 +210,7 @@ public class AuthenticationRequestFilter implements ContainerRequestFilter {
logger.error(
"No Authorization header or cookie on request to URL " + requestContext.getUriInfo().getPath());
requestContext.abortWith(
- Response.status(Response.Status.FORBIDDEN).header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN)
+ Response.status(Response.Status.UNAUTHORIZED).header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN)
.entity("Missing Authorization!").build());
return null;
}
diff --git a/web-rest/src/main/java/li/strolch/rest/helper/ResponseUtil.java b/web-rest/src/main/java/li/strolch/rest/helper/ResponseUtil.java
index e3a6a5072..6b4c85771 100644
--- a/web-rest/src/main/java/li/strolch/rest/helper/ResponseUtil.java
+++ b/web-rest/src/main/java/li/strolch/rest/helper/ResponseUtil.java
@@ -1,21 +1,14 @@
package li.strolch.rest.helper;
-import static li.strolch.rest.StrolchRestfulConstants.*;
-import static li.strolch.utils.helper.ExceptionHelper.getExceptionMessageWithCauses;
-import static li.strolch.utils.helper.ExceptionHelper.getRootCause;
-
-import jakarta.ws.rs.core.MediaType;
-import jakarta.ws.rs.core.Response;
-import jakarta.ws.rs.core.Response.Status;
-import java.util.List;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
import li.strolch.exception.StrolchElementNotFoundException;
+import li.strolch.exception.StrolchNotAuthenticatedException;
import li.strolch.exception.StrolchUserMessageException;
import li.strolch.model.i18n.I18nMessageToJsonVisitor;
import li.strolch.privilege.base.AccessDeniedException;
@@ -27,6 +20,14 @@ import li.strolch.utils.I18nMessage;
import li.strolch.utils.collections.Paging;
import li.strolch.utils.helper.StringHelper;
+import java.util.List;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import static li.strolch.rest.StrolchRestfulConstants.*;
+import static li.strolch.utils.helper.ExceptionHelper.getExceptionMessageWithCauses;
+import static li.strolch.utils.helper.ExceptionHelper.getRootCause;
+
/**
* Created by eitch on 29.08.16.
*/
@@ -155,17 +156,17 @@ public class ResponseUtil {
}
public static Response toResponse(Throwable t) {
- if (t instanceof AccessDeniedException) {
- return ResponseUtil.toResponse(Status.FORBIDDEN, t);
- } else if (t instanceof StrolchElementNotFoundException) {
- return ResponseUtil.toResponse(Status.NOT_FOUND, t);
- } else if (t instanceof PrivilegeModelException) {
- return ResponseUtil.toResponse(Status.INTERNAL_SERVER_ERROR, t);
- } else if (t instanceof PrivilegeException) {
+ if (t instanceof StrolchNotAuthenticatedException)
return ResponseUtil.toResponse(Status.UNAUTHORIZED, t);
- } else {
- return toResponse(Status.INTERNAL_SERVER_ERROR, t);
- }
+ if (t instanceof AccessDeniedException)
+ return ResponseUtil.toResponse(Status.FORBIDDEN, t);
+ if (t instanceof StrolchElementNotFoundException)
+ return ResponseUtil.toResponse(Status.NOT_FOUND, t);
+ if (t instanceof PrivilegeModelException)
+ return ResponseUtil.toResponse(Status.INTERNAL_SERVER_ERROR, t);
+ if (t instanceof PrivilegeException)
+ return ResponseUtil.toResponse(Status.FORBIDDEN, t);
+ return toResponse(Status.INTERNAL_SERVER_ERROR, t);
}
public static Response toResponse(Status status, String msg) {
@@ -183,8 +184,8 @@ public class ResponseUtil {
response.add("i18n", ex.getI18n().accept(new I18nMessageToJsonVisitor()));
} else {
Throwable rootCause = getRootCause(t);
- if (rootCause instanceof StrolchUserMessageException ex
- && ((StrolchUserMessageException) rootCause).hasI18n()) {
+ if (rootCause instanceof StrolchUserMessageException ex &&
+ ((StrolchUserMessageException) rootCause).hasI18n()) {
response.add("i18n", ex.getI18n().accept(new I18nMessageToJsonVisitor()));
}
}
diff --git a/web-rest/src/test/resources/withPrivilegeRuntime/config/PrivilegeConfig.xml b/web-rest/src/test/resources/withPrivilegeRuntime/config/PrivilegeConfig.xml
index d04da193e..b2a9b4bf6 100644
--- a/web-rest/src/test/resources/withPrivilegeRuntime/config/PrivilegeConfig.xml
+++ b/web-rest/src/test/resources/withPrivilegeRuntime/config/PrivilegeConfig.xml
@@ -1,40 +1,21 @@
-
-
-
-
-
+
+
-
-
-
-