[Major] allow user to change their own locale incl. auto persist
This commit is contained in:
parent
86895c7aa5
commit
5602f56c15
|
@ -1 +1 @@
|
||||||
Subproject commit 5ef43eaebe670b0cf3f8ea1ccbc251b2c48f3dca
|
Subproject commit a3d76d4cd88ffd1fbeb6e9c646db0e55211f6d09
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
<Parameters>
|
<Parameters>
|
||||||
<!-- parameters for the container itself -->
|
<!-- parameters for the container itself -->
|
||||||
<Parameter name="autoPersistOnPasswordChange" value="true" />
|
<Parameter name="autoPersistOnUserChangesData" value="true" />
|
||||||
</Parameters>
|
</Parameters>
|
||||||
|
|
||||||
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
|
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
<Parameters>
|
<Parameters>
|
||||||
<!-- parameters for the container itself -->
|
<!-- parameters for the container itself -->
|
||||||
<Parameter name="autoPersistOnPasswordChange" value="true" />
|
<Parameter name="autoPersistOnUserChangesData" value="true" />
|
||||||
</Parameters>
|
</Parameters>
|
||||||
|
|
||||||
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
|
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
<Parameters>
|
<Parameters>
|
||||||
<!-- parameters for the container itself -->
|
<!-- parameters for the container itself -->
|
||||||
<Parameter name="autoPersistOnPasswordChange" value="true" />
|
<Parameter name="autoPersistOnUserChangesData" value="true" />
|
||||||
</Parameters>
|
</Parameters>
|
||||||
|
|
||||||
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
|
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
<Parameters>
|
<Parameters>
|
||||||
<!-- parameters for the container itself -->
|
<!-- parameters for the container itself -->
|
||||||
<Parameter name="autoPersistOnPasswordChange" value="true" />
|
<Parameter name="autoPersistOnUserChangesData" value="true" />
|
||||||
</Parameters>
|
</Parameters>
|
||||||
|
|
||||||
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
|
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
<Parameters>
|
<Parameters>
|
||||||
<!-- parameters for the container itself -->
|
<!-- parameters for the container itself -->
|
||||||
<Parameter name="autoPersistOnPasswordChange" value="true" />
|
<Parameter name="autoPersistOnUserChangesData" value="true" />
|
||||||
</Parameters>
|
</Parameters>
|
||||||
|
|
||||||
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
|
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
<Parameters>
|
<Parameters>
|
||||||
<!-- parameters for the container itself -->
|
<!-- parameters for the container itself -->
|
||||||
<Parameter name="autoPersistOnPasswordChange" value="true" />
|
<Parameter name="autoPersistOnUserChangesData" value="true" />
|
||||||
</Parameters>
|
</Parameters>
|
||||||
|
|
||||||
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
|
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
<Parameters>
|
<Parameters>
|
||||||
<!-- parameters for the container itself -->
|
<!-- parameters for the container itself -->
|
||||||
<Parameter name="autoPersistOnPasswordChange" value="true" />
|
<Parameter name="autoPersistOnUserChangesData" value="true" />
|
||||||
</Parameters>
|
</Parameters>
|
||||||
|
|
||||||
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
|
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
<Parameters>
|
<Parameters>
|
||||||
<!-- parameters for the container itself -->
|
<!-- parameters for the container itself -->
|
||||||
<Parameter name="autoPersistOnPasswordChange" value="true" />
|
<Parameter name="autoPersistOnUserChangesData" value="true" />
|
||||||
</Parameters>
|
</Parameters>
|
||||||
|
|
||||||
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
|
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
<Parameters>
|
<Parameters>
|
||||||
<!-- parameters for the container itself -->
|
<!-- parameters for the container itself -->
|
||||||
<Parameter name="autoPersistOnPasswordChange" value="true" />
|
<Parameter name="autoPersistOnUserChangesData" value="true" />
|
||||||
</Parameters>
|
</Parameters>
|
||||||
|
|
||||||
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
|
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
<Parameters>
|
<Parameters>
|
||||||
<!-- parameters for the container itself -->
|
<!-- parameters for the container itself -->
|
||||||
<Parameter name="autoPersistOnPasswordChange" value="true" />
|
<Parameter name="autoPersistOnUserChangesData" value="true" />
|
||||||
</Parameters>
|
</Parameters>
|
||||||
|
|
||||||
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
|
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
<Parameters>
|
<Parameters>
|
||||||
<!-- parameters for the container itself -->
|
<!-- parameters for the container itself -->
|
||||||
<Parameter name="autoPersistOnPasswordChange" value="true" />
|
<Parameter name="autoPersistOnUserChangesData" value="true" />
|
||||||
</Parameters>
|
</Parameters>
|
||||||
|
|
||||||
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
|
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
<Parameters>
|
<Parameters>
|
||||||
<!-- parameters for the container itself -->
|
<!-- parameters for the container itself -->
|
||||||
<Parameter name="autoPersistOnPasswordChange" value="true" />
|
<Parameter name="autoPersistOnUserChangesData" value="true" />
|
||||||
</Parameters>
|
</Parameters>
|
||||||
|
|
||||||
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
|
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
|
||||||
|
|
|
@ -15,7 +15,11 @@
|
||||||
*/
|
*/
|
||||||
package li.strolch.rest.endpoint;
|
package li.strolch.rest.endpoint;
|
||||||
|
|
||||||
|
import static li.strolch.rest.StrolchRestfulConstants.ROLE_STROLCH_PRIVILEGE_ADMIN;
|
||||||
|
|
||||||
|
import java.text.MessageFormat;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.ws.rs.Consumes;
|
import javax.ws.rs.Consumes;
|
||||||
|
@ -35,6 +39,7 @@ import javax.ws.rs.core.Response.Status;
|
||||||
import li.strolch.agent.api.ComponentContainer;
|
import li.strolch.agent.api.ComponentContainer;
|
||||||
import li.strolch.rest.RestfulStrolchComponent;
|
import li.strolch.rest.RestfulStrolchComponent;
|
||||||
import li.strolch.rest.StrolchRestfulConstants;
|
import li.strolch.rest.StrolchRestfulConstants;
|
||||||
|
import li.strolch.rest.model.PasswordField;
|
||||||
import li.strolch.rest.model.Result;
|
import li.strolch.rest.model.Result;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -45,6 +50,7 @@ import ch.eitchnet.privilege.base.PrivilegeException;
|
||||||
import ch.eitchnet.privilege.handler.PrivilegeHandler;
|
import ch.eitchnet.privilege.handler.PrivilegeHandler;
|
||||||
import ch.eitchnet.privilege.model.Certificate;
|
import ch.eitchnet.privilege.model.Certificate;
|
||||||
import ch.eitchnet.privilege.model.UserRep;
|
import ch.eitchnet.privilege.model.UserRep;
|
||||||
|
import ch.eitchnet.privilege.model.UserState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Robert von Burg <eitch@eitchnet.ch>
|
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||||
|
@ -55,9 +61,9 @@ public class PrivilegeUsersService {
|
||||||
private static final Logger logger = LoggerFactory.getLogger(PrivilegeUsersService.class);
|
private static final Logger logger = LoggerFactory.getLogger(PrivilegeUsersService.class);
|
||||||
|
|
||||||
private PrivilegeHandler getPrivilegeHandler(Certificate cert, boolean requiresStrolchPrivilegeAdminRole) {
|
private PrivilegeHandler getPrivilegeHandler(Certificate cert, boolean requiresStrolchPrivilegeAdminRole) {
|
||||||
if (requiresStrolchPrivilegeAdminRole && !cert.hasRole(StrolchRestfulConstants.ROLE_STROLCH_PRIVILEGE_ADMIN)) {
|
if (requiresStrolchPrivilegeAdminRole && !cert.hasRole(ROLE_STROLCH_PRIVILEGE_ADMIN)) {
|
||||||
throw new AccessDeniedException("You may not perform the request as you are missing role "
|
String msg = "You may not perform the request as you are missing role {0}";
|
||||||
+ StrolchRestfulConstants.ROLE_STROLCH_PRIVILEGE_ADMIN);
|
throw new AccessDeniedException(MessageFormat.format(msg, ROLE_STROLCH_PRIVILEGE_ADMIN));
|
||||||
}
|
}
|
||||||
|
|
||||||
ComponentContainer container = RestfulStrolchComponent.getInstance().getContainer();
|
ComponentContainer container = RestfulStrolchComponent.getInstance().getContainer();
|
||||||
|
@ -222,9 +228,92 @@ public class PrivilegeUsersService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO set password on user
|
@PUT
|
||||||
// TODO set state on user
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
// TODO set locale on user
|
@Path("{username}/state/{state}")
|
||||||
// TODO change username of user
|
public Response setUserState(@PathParam("username") String username, @PathParam("state") String state,
|
||||||
|
@Context HttpServletRequest request) {
|
||||||
|
Certificate cert = (Certificate) request.getAttribute(StrolchRestfulConstants.STROLCH_CERTIFICATE);
|
||||||
|
try {
|
||||||
|
|
||||||
|
UserState userState;
|
||||||
|
try {
|
||||||
|
userState = UserState.valueOf(state);
|
||||||
|
} catch (Exception e) {
|
||||||
|
String msg = MessageFormat.format("UserState {0} is not valid!", state);
|
||||||
|
return Response.serverError().entity(new Result(msg)).type(MediaType.APPLICATION_JSON).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
PrivilegeHandler privilegeHandler = getPrivilegeHandler(cert, true);
|
||||||
|
UserRep updatedUser = privilegeHandler.setUserState(cert, username, userState);
|
||||||
|
return Response.ok(updatedUser, MediaType.APPLICATION_JSON).build();
|
||||||
|
|
||||||
|
} catch (AccessDeniedException e) {
|
||||||
|
logger.error(e.getMessage(), e);
|
||||||
|
return Response.status(Status.UNAUTHORIZED).entity(new Result(e.getMessage()))
|
||||||
|
.type(MediaType.APPLICATION_JSON).build();
|
||||||
|
} catch (PrivilegeException e) {
|
||||||
|
logger.error(e.getMessage(), e);
|
||||||
|
return Response.status(Status.FORBIDDEN).entity(new Result(e.getMessage()))
|
||||||
|
.type(MediaType.APPLICATION_JSON).build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PUT
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Path("{username}/password")
|
||||||
|
public Response setUserPassword(@PathParam("username") String username, PasswordField passwordField,
|
||||||
|
@Context HttpServletRequest request) {
|
||||||
|
Certificate cert = (Certificate) request.getAttribute(StrolchRestfulConstants.STROLCH_CERTIFICATE);
|
||||||
|
try {
|
||||||
|
|
||||||
|
// if user changing own password, then no need for StrolchPrivilegeAdmin
|
||||||
|
PrivilegeHandler privilegeHandler = getPrivilegeHandler(cert, !cert.getUsername().equals(username));
|
||||||
|
|
||||||
|
privilegeHandler.setUserPassword(cert, username, passwordField.getPassword().getBytes());
|
||||||
|
return Response.ok(new Result(), MediaType.APPLICATION_JSON).build();
|
||||||
|
|
||||||
|
} catch (AccessDeniedException e) {
|
||||||
|
logger.error(e.getMessage(), e);
|
||||||
|
return Response.status(Status.UNAUTHORIZED).entity(new Result(e.getMessage()))
|
||||||
|
.type(MediaType.APPLICATION_JSON).build();
|
||||||
|
} catch (PrivilegeException e) {
|
||||||
|
logger.error(e.getMessage(), e);
|
||||||
|
return Response.status(Status.FORBIDDEN).entity(new Result(e.getMessage()))
|
||||||
|
.type(MediaType.APPLICATION_JSON).build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PUT
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@Path("{username}/locale/{locale}")
|
||||||
|
public Response setUserLocale(@PathParam("username") String username, @PathParam("locale") String localeS,
|
||||||
|
@Context HttpServletRequest request) {
|
||||||
|
Certificate cert = (Certificate) request.getAttribute(StrolchRestfulConstants.STROLCH_CERTIFICATE);
|
||||||
|
try {
|
||||||
|
|
||||||
|
Locale locale;
|
||||||
|
try {
|
||||||
|
locale = new Locale(localeS);
|
||||||
|
} catch (Exception e) {
|
||||||
|
String msg = MessageFormat.format("Locale {0} is not valid!", localeS);
|
||||||
|
return Response.serverError().entity(new Result(msg)).type(MediaType.APPLICATION_JSON).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
// if user changing own locale, then no need for StrolchPrivilegeAdmin
|
||||||
|
PrivilegeHandler privilegeHandler = getPrivilegeHandler(cert, !cert.getUsername().equals(username));
|
||||||
|
|
||||||
|
UserRep updatedUser = privilegeHandler.setUserLocale(cert, username, locale);
|
||||||
|
return Response.ok(updatedUser, MediaType.APPLICATION_JSON).build();
|
||||||
|
|
||||||
|
} catch (AccessDeniedException e) {
|
||||||
|
logger.error(e.getMessage(), e);
|
||||||
|
return Response.status(Status.UNAUTHORIZED).entity(new Result(e.getMessage()))
|
||||||
|
.type(MediaType.APPLICATION_JSON).build();
|
||||||
|
} catch (PrivilegeException e) {
|
||||||
|
logger.error(e.getMessage(), e);
|
||||||
|
return Response.status(Status.FORBIDDEN).entity(new Result(e.getMessage()))
|
||||||
|
.type(MediaType.APPLICATION_JSON).build();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package li.strolch.rest.model;
|
package li.strolch.rest.model;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -133,6 +134,8 @@ public class LoginResult {
|
||||||
*/
|
*/
|
||||||
@XmlElement(name = "properties")
|
@XmlElement(name = "properties")
|
||||||
public List<XmlKeyValue> getPropertiesAsKeyValue() {
|
public List<XmlKeyValue> getPropertiesAsKeyValue() {
|
||||||
|
if (this.parameters == null)
|
||||||
|
return new ArrayList<>(0);
|
||||||
return XmlKeyValue.valueOf(this.parameters);
|
return XmlKeyValue.valueOf(this.parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
package li.strolch.rest.model;
|
||||||
|
|
||||||
|
import javax.xml.bind.annotation.XmlAccessType;
|
||||||
|
import javax.xml.bind.annotation.XmlAccessorType;
|
||||||
|
import javax.xml.bind.annotation.XmlAttribute;
|
||||||
|
import javax.xml.bind.annotation.XmlRootElement;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Robert von Burg <eitch@eitchnet.ch>
|
||||||
|
*/
|
||||||
|
@XmlRootElement(name = "PasswordField")
|
||||||
|
@XmlAccessorType(XmlAccessType.NONE)
|
||||||
|
public class PasswordField {
|
||||||
|
|
||||||
|
@XmlAttribute(name = "password")
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
public String getPassword() {
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPassword(String password) {
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
<Parameters>
|
<Parameters>
|
||||||
<!-- parameters for the container itself -->
|
<!-- parameters for the container itself -->
|
||||||
<Parameter name="autoPersistOnPasswordChange" value="true" />
|
<Parameter name="autoPersistOnUserChangesData" value="true" />
|
||||||
</Parameters>
|
</Parameters>
|
||||||
|
|
||||||
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
|
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
<Parameters>
|
<Parameters>
|
||||||
<!-- parameters for the container itself -->
|
<!-- parameters for the container itself -->
|
||||||
<Parameter name="autoPersistOnPasswordChange" value="true" />
|
<Parameter name="autoPersistOnUserChangesData" value="true" />
|
||||||
</Parameters>
|
</Parameters>
|
||||||
|
|
||||||
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
|
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
<Parameters>
|
<Parameters>
|
||||||
<!-- parameters for the container itself -->
|
<!-- parameters for the container itself -->
|
||||||
<Parameter name="autoPersistOnPasswordChange" value="true" />
|
<Parameter name="autoPersistOnUserChangesData" value="true" />
|
||||||
</Parameters>
|
</Parameters>
|
||||||
|
|
||||||
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
|
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
<Parameters>
|
<Parameters>
|
||||||
<!-- parameters for the container itself -->
|
<!-- parameters for the container itself -->
|
||||||
<Parameter name="autoPersistOnPasswordChange" value="true" />
|
<Parameter name="autoPersistOnUserChangesData" value="true" />
|
||||||
</Parameters>
|
</Parameters>
|
||||||
|
|
||||||
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
|
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
<Parameters>
|
<Parameters>
|
||||||
<!-- parameters for the container itself -->
|
<!-- parameters for the container itself -->
|
||||||
<Parameter name="autoPersistOnPasswordChange" value="true" />
|
<Parameter name="autoPersistOnUserChangesData" value="true" />
|
||||||
</Parameters>
|
</Parameters>
|
||||||
|
|
||||||
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
|
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
<Parameters>
|
<Parameters>
|
||||||
<!-- parameters for the container itself -->
|
<!-- parameters for the container itself -->
|
||||||
<Parameter name="autoPersistOnPasswordChange" value="true" />
|
<Parameter name="autoPersistOnUserChangesData" value="true" />
|
||||||
</Parameters>
|
</Parameters>
|
||||||
|
|
||||||
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
|
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
<Parameters>
|
<Parameters>
|
||||||
<!-- parameters for the container itself -->
|
<!-- parameters for the container itself -->
|
||||||
<Parameter name="autoPersistOnPasswordChange" value="true" />
|
<Parameter name="autoPersistOnUserChangesData" value="true" />
|
||||||
</Parameters>
|
</Parameters>
|
||||||
|
|
||||||
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
|
<EncryptionHandler class="ch.eitchnet.privilege.handler.DefaultEncryptionHandler">
|
||||||
|
|
Loading…
Reference in New Issue