[New] Added UserSession querying and modifying

This commit is contained in:
Robert von Burg 2015-03-14 21:23:10 +01:00
parent 85e34cabe1
commit 2ee0d2fb4e
7 changed files with 252 additions and 11 deletions

@ -1 +1 @@
Subproject commit 9870513beb0a656a7d9153ea30aa7a0000e17417
Subproject commit c2f4d7468b124f2579ac21d080d47c179f007afd

View File

@ -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);
}
}
}
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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();
}
}

View File

@ -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;
}
}

View File

@ -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));
}