[New] Added UserSession querying and modifying
This commit is contained in:
parent
85e34cabe1
commit
2ee0d2fb4e
|
@ -1 +1 @@
|
|||
Subproject commit 9870513beb0a656a7d9153ea30aa7a0000e17417
|
||||
Subproject commit c2f4d7468b124f2579ac21d080d47c179f007afd
|
|
@ -16,7 +16,15 @@
|
|||
package li.strolch.rest;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
@ -25,13 +33,17 @@ import java.util.concurrent.TimeUnit;
|
|||
import li.strolch.agent.api.ComponentContainer;
|
||||
import li.strolch.agent.api.StrolchComponent;
|
||||
import li.strolch.exception.StrolchException;
|
||||
import li.strolch.rest.model.UserSession;
|
||||
import li.strolch.runtime.configuration.ComponentConfiguration;
|
||||
import li.strolch.runtime.privilege.PrivilegeHandler;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ch.eitchnet.privilege.base.AccessDeniedException;
|
||||
import ch.eitchnet.privilege.model.Certificate;
|
||||
import ch.eitchnet.privilege.model.PrivilegeContext;
|
||||
import ch.eitchnet.privilege.model.SimpleRestrictable;
|
||||
import ch.eitchnet.utils.dbc.DBC;
|
||||
|
||||
/**
|
||||
|
@ -106,7 +118,7 @@ public class DefaultStrolchSessionHandler extends StrolchComponent implements St
|
|||
|
||||
synchronized (this.certificateMap) {
|
||||
Certificate certificate = this.privilegeHandler.authenticate(username, password);
|
||||
certificate.setLastAccess(System.currentTimeMillis());
|
||||
certificate.setLastAccess(new Date());
|
||||
this.certificateMap.put(certificate.getAuthToken(), certificate);
|
||||
|
||||
logger.info(MessageFormat.format("{0} sessions currently active.", this.certificateMap.size())); //$NON-NLS-1$
|
||||
|
@ -132,12 +144,12 @@ public class DefaultStrolchSessionHandler extends StrolchComponent implements St
|
|||
@Override
|
||||
public Certificate validate(Certificate certificate) {
|
||||
this.privilegeHandler.isCertificateValid(certificate);
|
||||
certificate.setLastAccess(System.currentTimeMillis());
|
||||
certificate.setLastAccess(new Date());
|
||||
return certificate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateSession(Certificate certificate) {
|
||||
public void invalidate(Certificate certificate) {
|
||||
DBC.PRE.assertNotNull("Certificate must bet given!", certificate); //$NON-NLS-1$
|
||||
|
||||
Certificate removedCert;
|
||||
|
@ -174,15 +186,74 @@ public class DefaultStrolchSessionHandler extends StrolchComponent implements St
|
|||
certificateMap = new HashMap<>(map);
|
||||
}
|
||||
|
||||
long reqLastAccessTime = System.currentTimeMillis() - DefaultStrolchSessionHandler.this.sessionTtl;
|
||||
LocalDateTime timeOutTime = LocalDateTime.now().minus(sessionTtl, ChronoUnit.MILLIS);
|
||||
ZoneId systemDefault = ZoneId.systemDefault();
|
||||
|
||||
for (Certificate certificate : certificateMap.values()) {
|
||||
if (certificate.getLastAccess() < reqLastAccessTime) {
|
||||
Instant lastAccess = certificate.getLastAccess().toInstant();
|
||||
if (timeOutTime.isAfter(LocalDateTime.ofInstant(lastAccess, systemDefault))) {
|
||||
String msg = "Session {0} for user {1} has expired, invalidating session..."; //$NON-NLS-1$
|
||||
logger.info(MessageFormat.format(msg, certificate.getAuthToken(), certificate.getUsername()));
|
||||
invalidateSession(certificate);
|
||||
invalidate(certificate);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserSession getSession(Certificate certificate, String sessionId) {
|
||||
PrivilegeContext ctx = this.privilegeHandler.getPrivilegeContext(certificate);
|
||||
ctx.assertHasPrivilege("GetSession");
|
||||
for (Certificate cert : certificateMap.values()) {
|
||||
if (cert.getSessionId().equals(sessionId)) {
|
||||
ctx.validateAction(new SimpleRestrictable("GetSession", cert));
|
||||
return new UserSession(cert);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserSession> getSessions(Certificate certificate) {
|
||||
PrivilegeContext ctx = this.privilegeHandler.getPrivilegeContext(certificate);
|
||||
ctx.assertHasPrivilege("GetSession");
|
||||
List<UserSession> sessions = new ArrayList<>(this.certificateMap.size());
|
||||
for (Certificate cert : certificateMap.values()) {
|
||||
try {
|
||||
ctx.validateAction(new SimpleRestrictable("GetSession", cert));
|
||||
sessions.add(new UserSession(cert));
|
||||
} catch (AccessDeniedException e) {
|
||||
// so no, user may not get this session
|
||||
}
|
||||
}
|
||||
|
||||
return sessions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateSession(Certificate certificate, String sessionId) {
|
||||
PrivilegeContext ctx = this.privilegeHandler.getPrivilegeContext(certificate);
|
||||
ctx.assertHasPrivilege("InvalidateSession");
|
||||
for (Certificate cert : certificateMap.values()) {
|
||||
if (cert.getSessionId().equals(sessionId)) {
|
||||
ctx.validateAction(new SimpleRestrictable("InvalidateSession", cert));
|
||||
invalidate(cert);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSessionLocale(Certificate certificate, String sessionId, Locale locale) {
|
||||
if (!certificate.getSessionId().equals(sessionId)) {
|
||||
String msg = "User''s can only change their own session locale: {0} may not change locale of session {1}";
|
||||
throw new AccessDeniedException(MessageFormat.format(msg, certificate.getUsername(), sessionId));
|
||||
}
|
||||
|
||||
for (Certificate cert : certificateMap.values()) {
|
||||
if (cert.getSessionId().equals(sessionId)) {
|
||||
cert.setLocale(locale);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,10 @@
|
|||
*/
|
||||
package li.strolch.rest;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import li.strolch.rest.model.UserSession;
|
||||
import ch.eitchnet.privilege.model.Certificate;
|
||||
|
||||
/**
|
||||
|
@ -28,5 +32,13 @@ public interface StrolchSessionHandler {
|
|||
|
||||
public Certificate validate(Certificate certificate);
|
||||
|
||||
public void invalidateSession(Certificate certificate);
|
||||
public void invalidate(Certificate certificate);
|
||||
|
||||
public List<UserSession> getSessions(Certificate certificate);
|
||||
|
||||
public UserSession getSession(Certificate certificate, String sessionId);
|
||||
|
||||
public void invalidateSession(Certificate certificate, String sessionId);
|
||||
|
||||
public void setSessionLocale(Certificate certificate, String sessionId, Locale locale);
|
||||
}
|
||||
|
|
|
@ -133,7 +133,7 @@ public class AuthenticationService {
|
|||
StrolchSessionHandler sessionHandlerHandler = RestfulStrolchComponent.getInstance().getComponent(
|
||||
StrolchSessionHandler.class);
|
||||
Certificate certificate = sessionHandlerHandler.validate(sessionId);
|
||||
sessionHandlerHandler.invalidateSession(certificate);
|
||||
sessionHandlerHandler.invalidate(certificate);
|
||||
|
||||
logoutResult.setUsername(certificate.getUsername());
|
||||
logoutResult.setSessionId(sessionId);
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
package li.strolch.rest.endpoint;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.GenericEntity;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import li.strolch.rest.RestfulStrolchComponent;
|
||||
import li.strolch.rest.StrolchRestfulConstants;
|
||||
import li.strolch.rest.StrolchSessionHandler;
|
||||
import li.strolch.rest.model.Result;
|
||||
import li.strolch.rest.model.UserSession;
|
||||
import ch.eitchnet.privilege.model.Certificate;
|
||||
|
||||
@Path("strolch/sessions")
|
||||
public class UserSessionsService {
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response getSessions(@Context HttpServletRequest request) {
|
||||
Certificate cert = (Certificate) request.getAttribute(StrolchRestfulConstants.STROLCH_CERTIFICATE);
|
||||
StrolchSessionHandler sessionHandler = RestfulStrolchComponent.getInstance().getSessionHandler();
|
||||
List<UserSession> sessions = sessionHandler.getSessions(cert);
|
||||
GenericEntity<List<UserSession>> entity = new GenericEntity<List<UserSession>>(sessions) {
|
||||
};
|
||||
return Response.ok(entity, MediaType.APPLICATION_JSON).build();
|
||||
}
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("{sessionId}")
|
||||
public Response getSession(@Context HttpServletRequest request, @PathParam("sessionId") String sessionId) {
|
||||
Certificate cert = (Certificate) request.getAttribute(StrolchRestfulConstants.STROLCH_CERTIFICATE);
|
||||
StrolchSessionHandler sessionHandler = RestfulStrolchComponent.getInstance().getSessionHandler();
|
||||
UserSession session = sessionHandler.getSession(cert, sessionId);
|
||||
return Response.ok(session, MediaType.APPLICATION_JSON).build();
|
||||
}
|
||||
|
||||
@DELETE
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("{sessionId}")
|
||||
public Response invalidateSession(@Context HttpServletRequest request, @PathParam("sessionId") String sessionId) {
|
||||
Certificate cert = (Certificate) request.getAttribute(StrolchRestfulConstants.STROLCH_CERTIFICATE);
|
||||
StrolchSessionHandler sessionHandler = RestfulStrolchComponent.getInstance().getSessionHandler();
|
||||
sessionHandler.invalidateSession(cert, sessionId);
|
||||
return Response.ok(new Result(), MediaType.APPLICATION_JSON).build();
|
||||
}
|
||||
|
||||
@PUT
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Path("{sessionId}/locale/{locale}")
|
||||
public Response setSessionLocale(@Context HttpServletRequest request, @PathParam("sessionId") String sessionId,
|
||||
@PathParam("locale") String localeS) {
|
||||
Certificate cert = (Certificate) request.getAttribute(StrolchRestfulConstants.STROLCH_CERTIFICATE);
|
||||
StrolchSessionHandler sessionHandler = RestfulStrolchComponent.getInstance().getSessionHandler();
|
||||
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();
|
||||
}
|
||||
|
||||
sessionHandler.setSessionLocale(cert, sessionId, locale);
|
||||
return Response.ok(new Result(), MediaType.APPLICATION_JSON).build();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
package li.strolch.rest.model;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
import ch.eitchnet.privilege.model.Certificate;
|
||||
|
||||
@XmlRootElement(name = "UserSession")
|
||||
@XmlAccessorType(XmlAccessType.NONE)
|
||||
public class UserSession {
|
||||
|
||||
@XmlAttribute(name = "sessionId")
|
||||
private String sessionId;
|
||||
@XmlAttribute(name = "loginTime")
|
||||
private Date loginTime;
|
||||
@XmlAttribute(name = "username")
|
||||
private String username;
|
||||
@XmlAttribute(name = "firstname")
|
||||
private String firstname;
|
||||
@XmlAttribute(name = "lastname")
|
||||
private String lastname;
|
||||
@XmlElement(name = "roles")
|
||||
private Set<String> userRoles;
|
||||
@XmlAttribute(name = "locale")
|
||||
private Locale locale;
|
||||
@XmlAttribute(name = "lastAccess")
|
||||
private Date lastAccess;
|
||||
|
||||
public UserSession(Certificate certificate) {
|
||||
this.sessionId = certificate.getSessionId();
|
||||
this.loginTime = certificate.getLoginTime();
|
||||
this.username = certificate.getUsername();
|
||||
this.firstname = certificate.getFirstname();
|
||||
this.lastname = certificate.getLastname();
|
||||
this.userRoles = certificate.getUserRoles();
|
||||
this.locale = certificate.getLocale();
|
||||
this.lastAccess = certificate.getLastAccess();
|
||||
}
|
||||
|
||||
public Locale getLocale() {
|
||||
return locale;
|
||||
}
|
||||
|
||||
public Date getLastAccess() {
|
||||
return lastAccess;
|
||||
}
|
||||
|
||||
public String getSessionId() {
|
||||
return sessionId;
|
||||
}
|
||||
|
||||
public Date getLoginTime() {
|
||||
return loginTime;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public String getFirstname() {
|
||||
return firstname;
|
||||
}
|
||||
|
||||
public String getLastname() {
|
||||
return lastname;
|
||||
}
|
||||
|
||||
public Set<String> getUserRoles() {
|
||||
return userRoles;
|
||||
}
|
||||
}
|
|
@ -20,6 +20,7 @@ import static org.hamcrest.Matchers.equalTo;
|
|||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
|
||||
import li.strolch.service.api.ServiceResult;
|
||||
|
@ -56,14 +57,15 @@ public class ServiceTest extends AbstractServiceTest {
|
|||
this.thrown.expect(PrivilegeException.class);
|
||||
TestService testService = new TestService();
|
||||
getServiceHandler().doService(
|
||||
new Certificate(null, 0, null, null, null, null, null, new HashSet<String>(), null), testService);
|
||||
new Certificate(null, new Date(), null, null, null, null, null, new HashSet<String>(), null),
|
||||
testService);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldFailInvalidCertificate2() {
|
||||
TestService testService = new TestService();
|
||||
Certificate badCert = new Certificate(
|
||||
"1", System.currentTimeMillis(), "bob", "Bob", "Brown", "dsdf", null, new HashSet<String>(), null); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||
"1", new Date(), "bob", "Bob", "Brown", "dsdf", null, new HashSet<String>(), null); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||
ServiceResult svcResult = getServiceHandler().doService(badCert, testService);
|
||||
assertThat(svcResult.getThrowable(), instanceOf(AccessDeniedException.class));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue