You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2015/07/09 18:29:35 UTC
[6/9] isis git commit: ISIS-1169: change to (try to) avoid "session
already open" error (http://isis.markmail.org/thread/2dn7tja3r466yd2m)
ISIS-1169: change to (try to) avoid "session already open" error (http://isis.markmail.org/thread/2dn7tja3r466yd2m)
- IsisContextThreadLocal now uses AUTO_CLOSE session policy instead of EXPLICIT_CLOSE session policy
- simplified IsisSessionFilter:
- always call closeSession() in a finally block
- get rid of SessionState enum, since never used
- enhanced IsisTransactionFilterForRestfulObjects to be resilient of the fact that the session/transaction may no longer exist (if the authSession is closed by a resource)
- added user/logout resource to UserResourceServerSide, enhanced UserReprRenderer to display new link (plus new proprietary Rel for this)
- extended IsisSessionFilter, also AuthenticationSessionStrategy interface
- special query string to set on redirect to request that the session be closed
- new AuthenticationSessionStrategy#invalidate(), called on this
- default impl returns 401, UNAUTHORIZED... this is enough to effect a server-side "logout" for BASIC auth
- updated IsisSession#close() so that if takeSnapshot() throws exception, then this doesn't prevent the persistence session from being closed
- updated PersistenceSession#close(), better debugging if the objectStore#close() or the adapterManager#close() were to throw an exception.
- removed unused DeploymentType#UTILITY instance.
Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/edc4fa76
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/edc4fa76
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/edc4fa76
Branch: refs/heads/master
Commit: edc4fa7648f73dea2c3be41de24b29ca76af9fe4
Parents: 7db0239
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Thu Jul 9 11:25:50 2015 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Thu Jul 9 11:29:57 2015 +0100
----------------------------------------------------------------------
.../core/runtime/system/DeploymentType.java | 1 -
.../runtime/system/context/IsisContext.java | 14 +-
.../system/context/IsisContextThreadLocal.java | 6 +-
.../system/persistence/PersistenceSession.java | 29 +--
.../runtime/system/session/IsisSession.java | 5 -
.../system/session/IsisSessionDefault.java | 12 +-
.../isis/core/webapp/IsisSessionFilter.java | 205 +++++++------------
.../auth/AuthenticationSessionStrategy.java | 10 +-
.../AuthenticationSessionStrategyAbstract.java | 12 +-
.../AuthenticationSessionStrategyDefault.java | 28 ++-
.../isis/viewer/restfulobjects/applib/Rel.java | 3 +-
.../applib/user/UserResource.java | 19 +-
.../rendering/RendererContext.java | 2 +-
.../AuthenticationSessionStrategyBasicAuth.java | 39 ++--
.../AuthenticationSessionStrategyHeader.java | 10 +-
.../AuthenticationSessionStrategyTrusted.java | 8 +-
.../server/resources/ResourceAbstract.java | 12 +-
.../server/resources/UserReprRenderer.java | 7 +
.../resources/UserResourceServerside.java | 28 +++
.../IsisTransactionFilterForRestfulObjects.java | 10 +-
20 files changed, 257 insertions(+), 203 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/isis/blob/edc4fa76/core/runtime/src/main/java/org/apache/isis/core/runtime/system/DeploymentType.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/DeploymentType.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/DeploymentType.java
index e92b5ff..3cde2b1 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/DeploymentType.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/DeploymentType.java
@@ -62,7 +62,6 @@ public class DeploymentType implements DeploymentCategoryProvider {
public static DeploymentType SERVER_EXPLORATION = new DeploymentType("SERVER_EXPLORATION", DeploymentCategory.EXPLORING, ContextCategory.THREADLOCAL);
public static DeploymentType SERVER_PROTOTYPE = new DeploymentType("SERVER_PROTOTYPE", DeploymentCategory.PROTOTYPING, ContextCategory.THREADLOCAL);
public static DeploymentType UNIT_TESTING = new DeploymentType("UNIT_TESTING", DeploymentCategory.PRODUCTION, ContextCategory.STATIC_RELAXED);
- public static DeploymentType UTILITY = new DeploymentType("UTILITY", DeploymentCategory.EXPLORING, ContextCategory.STATIC);
/**
* Look up {@link DeploymentType} by their {@link #name()}.
http://git-wip-us.apache.org/repos/asf/isis/blob/edc4fa76/core/runtime/src/main/java/org/apache/isis/core/runtime/system/context/IsisContext.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/context/IsisContext.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/context/IsisContext.java
index e078665..287c282 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/context/IsisContext.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/context/IsisContext.java
@@ -95,7 +95,10 @@ public abstract class IsisContext implements DebuggableWithTitle {
protected static enum SessionClosePolicy {
/**
* Sessions must be explicitly closed.
+ *
+ * @deprecated - in 1.9.0-SNAPSHOT it has been reported that on occasion the session is not explicitly closed. This must mean that there's a leakage somewhere. Using auto close instead will make the system overall more able to "repair itself" when this type of error (presumably a bug in our session management code) occurs
*/
+ @Deprecated
EXPLICIT_CLOSE,
/**
* Sessions will be automatically closed.
@@ -211,8 +214,9 @@ public abstract class IsisContext implements DebuggableWithTitle {
* threads have finished with a session can it really be closed.
*/
public void closeSessionInstance() {
- if (getSessionInstance() != null) {
- getSessionInstance().close();
+ final IsisSession isisSession = getSessionInstance();
+ if (isisSession != null) {
+ isisSession.close();
doClose();
}
}
@@ -445,7 +449,11 @@ public abstract class IsisContext implements DebuggableWithTitle {
// ///////////////////////////////////////////////////////////
public static boolean inTransaction() {
- return inSession() && getCurrentTransaction() != null && !getCurrentTransaction().getState().isComplete();
+ if (inSession())
+ if (getCurrentTransaction() != null)
+ if (!getCurrentTransaction().getState().isComplete())
+ return true;
+ return false;
}
/**
http://git-wip-us.apache.org/repos/asf/isis/blob/edc4fa76/core/runtime/src/main/java/org/apache/isis/core/runtime/system/context/IsisContextThreadLocal.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/context/IsisContextThreadLocal.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/context/IsisContextThreadLocal.java
index 5c34916..e99e485 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/context/IsisContextThreadLocal.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/context/IsisContextThreadLocal.java
@@ -42,6 +42,7 @@ public class IsisContextThreadLocal extends IsisContext {
return new IsisContextThreadLocal(sessionFactory);
}
+ // TODO: could convert this to a regular ThreadLocal, I think; except for the closeAllSessionsInstance() method...; is that method really needed?
private final Map<Thread, IsisSession> sessionsByThread = new IdentityHashMap<>();
@@ -50,7 +51,7 @@ public class IsisContextThreadLocal extends IsisContext {
// //////////////////////////////////////////////
protected IsisContextThreadLocal(final IsisSessionFactory sessionFactory) {
- this(ContextReplacePolicy.NOT_REPLACEABLE, SessionClosePolicy.EXPLICIT_CLOSE, sessionFactory);
+ this(ContextReplacePolicy.NOT_REPLACEABLE, SessionClosePolicy.AUTO_CLOSE, sessionFactory);
}
protected IsisContextThreadLocal(final ContextReplacePolicy contextReplacePolicy, final SessionClosePolicy sessionClosePolicy, final IsisSessionFactory sessionFactory) {
@@ -184,8 +185,7 @@ public class IsisContextThreadLocal extends IsisContext {
@Override
public IsisSession getSessionInstance() {
final Thread thread = Thread.currentThread();
- final IsisSession session = sessionsByThread.get(thread);
- return session;
+ return sessionsByThread.get(thread);
}
}
http://git-wip-us.apache.org/repos/asf/isis/blob/edc4fa76/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession.java
index 5c64197..d5e01ec 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSession.java
@@ -238,28 +238,31 @@ public class PersistenceSession implements SessionScopedComponent, DebuggableWit
*/
@Override
public void close() {
+
if (getState() == State.CLOSED) {
// nothing to do
return;
}
- if (LOG.isDebugEnabled()) {
- LOG.debug("closing " + this);
- }
-
try {
- objectStore.close();
- } catch(final RuntimeException ex) {
- // ignore
- }
+ try {
+ objectStore.close();
+ } catch(final Throwable ex) {
+ // ignore
+ LOG.error("objectStore#close() failed while closing the session; continuing to avoid memory leakage");
+ }
- try {
- adapterManager.close();
- } catch(final RuntimeException ex) {
- // ignore
+ try {
+ adapterManager.close();
+ } catch(final Throwable ex) {
+ // ignore
+ LOG.error("adapterManager#close() failed while closing the session; continuing to avoid memory leakage");
+ }
+
+ } finally {
+ setState(State.CLOSED);
}
- setState(State.CLOSED);
}
http://git-wip-us.apache.org/repos/asf/isis/blob/edc4fa76/core/runtime/src/main/java/org/apache/isis/core/runtime/system/session/IsisSession.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/session/IsisSession.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/session/IsisSession.java
index 3c95e12..0f42039 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/session/IsisSession.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/session/IsisSession.java
@@ -74,11 +74,6 @@ public interface IsisSession extends SessionScopedComponent {
/**
* The {@link PersistenceSession} within this {@link IsisSession}.
- *
- * <p>
- * Would have been created by the {@link #getSessionFactory() owning
- * factory}'s
- *
*/
PersistenceSession getPersistenceSession();
http://git-wip-us.apache.org/repos/asf/isis/blob/edc4fa76/core/runtime/src/main/java/org/apache/isis/core/runtime/system/session/IsisSessionDefault.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/session/IsisSessionDefault.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/session/IsisSessionDefault.java
index c74a4b8..4dcb7b3 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/session/IsisSessionDefault.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/session/IsisSessionDefault.java
@@ -102,8 +102,16 @@ public class IsisSessionDefault implements IsisSession {
*/
@Override
public void close() {
- takeSnapshot();
- getPersistenceSession().close();
+ try {
+ takeSnapshot();
+ } catch(Throwable ex) {
+ LOG.error("Failed to takeSnapshot while closing the session; continuing to avoid memory leakage");
+ }
+
+ final PersistenceSession persistenceSession = getPersistenceSession();
+ if(persistenceSession != null) {
+ persistenceSession.close();
+ }
}
// //////////////////////////////////////////////////////
http://git-wip-us.apache.org/repos/asf/isis/blob/edc4fa76/core/runtime/src/main/java/org/apache/isis/core/webapp/IsisSessionFilter.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/webapp/IsisSessionFilter.java b/core/runtime/src/main/java/org/apache/isis/core/webapp/IsisSessionFilter.java
index 21680e6..b1d50d0 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/webapp/IsisSessionFilter.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/webapp/IsisSessionFilter.java
@@ -59,9 +59,7 @@ public class IsisSessionFilter implements Filter {
public static final String AUTHENTICATION_SESSION_STRATEGY_KEY = "authenticationSessionStrategy";
/**
- * Default value for
- * {@link AuthenticationSessionLookupStrategyConstants#AUTHENTICATION_SESSION_STRATEGY_KEY}
- * if not specified.
+ * Default value for {@link #AUTHENTICATION_SESSION_STRATEGY_KEY} if not specified.
*/
public static final String AUTHENTICATION_SESSION_STRATEGY_DEFAULT = AuthenticationSessionStrategyDefault.class.getName();
@@ -115,11 +113,7 @@ public class IsisSessionFilter implements Filter {
* accomplishes the same thing).
*
* <p>
- * The value is expected as a comma separated list, for example:
- *
- * <pre>
- * htmlviewer
- * </pre>
+ * The value is expected as a comma separated list.
*/
public static final String IGNORE_EXTENSIONS_KEY = "ignoreExtensions";
@@ -131,6 +125,11 @@ public class IsisSessionFilter implements Filter {
};
+ /**
+ * Somewhat hacky, add this to the query
+ */
+ public static final String QUERY_STRING_FORCE_LOGOUT = "__isis_force_logout";
+
static void redirect(final HttpServletRequest httpRequest, final HttpServletResponse httpResponse, final String redirectTo) throws IOException {
httpResponse.sendRedirect(StringExtensions.combinePath(httpRequest.getContextPath(), redirectTo));
}
@@ -193,17 +192,10 @@ public class IsisSessionFilter implements Filter {
public abstract void handle(IsisSessionFilter filter, HttpServletRequest httpRequest, HttpServletResponse httpResponse, FilterChain chain) throws IOException, ServletException;
}
- /**
- * Used as a flag on {@link HttpServletRequest} so that if there are two
- * {@link IsisSessionFilter}s in a request pipeline, then the second can
- * determine what processing has already been done (and is usually then just
- * a no-op).
- */
- private static final String SESSION_STATE_KEY = IsisSessionFilter.SessionState.class.getName();
private AuthenticationSessionStrategy authSessionStrategy;
private List<String> restrictedPaths;
- private WhenNoSession whenNoSession;
+ private WhenNoSession whenNotAuthenticated;
private String redirectToOnException;
private Collection<Pattern> ignoreExtensions;
@@ -237,18 +229,22 @@ public class IsisSessionFilter implements Filter {
final String logonPage = config.getInitParameter(LOGON_PAGE_KEY);
if (logonPage != null) {
if (whenNoSessionStr != null) {
- throw new IllegalStateException("The init-param '" + LOGON_PAGE_KEY + "' is only provided for backwards compatibility; remove if the init-param '" + WHEN_NO_SESSION_KEY + "' has been specified");
+ throw new IllegalStateException(String.format(
+ "The init-param '%s' is only provided for backwards compatibility; "
+ + "remove if the init-param '%s' has been specified", LOGON_PAGE_KEY, WHEN_NO_SESSION_KEY));
+ } else {
+ // default whenNotAuthenticated and allow access through to the logonPage
+ whenNotAuthenticated = WhenNoSession.RESTRICTED;
+ this.restrictedPaths = Lists.newArrayList(logonPage);
+ return;
}
- whenNoSession = WhenNoSession.RESTRICTED;
- this.restrictedPaths = Lists.newArrayList(logonPage);
- return;
}
- whenNoSession = WhenNoSession.lookup(whenNoSessionStr);
- if (whenNoSession == WhenNoSession.RESTRICTED) {
+ whenNotAuthenticated = WhenNoSession.lookup(whenNoSessionStr);
+ if (whenNotAuthenticated == WhenNoSession.RESTRICTED) {
final String restrictedPathsStr = config.getInitParameter(RESTRICTED_KEY);
if (restrictedPathsStr == null) {
- throw new IllegalStateException("Require an init-param of '" + RESTRICTED_KEY + "' key to be set.");
+ throw new IllegalStateException(String.format("Require an init-param of '%s' key to be set.", RESTRICTED_KEY));
}
this.restrictedPaths = Lists.newArrayList(Splitter.on(",").split(restrictedPathsStr));
}
@@ -281,137 +277,80 @@ public class IsisSessionFilter implements Filter {
// doFilter
// /////////////////////////////////////////////////////////////////
- public enum SessionState {
-
- UNDEFINED {
- @Override
- public void handle(final IsisSessionFilter filter, final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException {
-
- final HttpServletRequest httpRequest = (HttpServletRequest) request;
- final HttpServletResponse httpResponse = (HttpServletResponse) response;
-
- if (requestIsIgnoreExtension(filter, httpRequest)) {
- try {
- chain.doFilter(request, response);
- return;
- } finally {
- closeSession();
- }
- }
+ @Override
+ public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException {
- if (ResourceCachingFilter.isCachedResource(httpRequest)) {
- try {
- chain.doFilter(request, response);
- return;
- } finally {
- closeSession();
- }
- }
+ final HttpServletRequest httpServletRequest = (HttpServletRequest) request;
+ final HttpServletResponse httpServletResponse = (HttpServletResponse) response;
- // authenticate
- final AuthenticationSession validSession = filter.authSessionStrategy.lookupValid(request, response);
- if (validSession != null) {
- filter.authSessionStrategy.bind(request, response, validSession);
+ try {
+ final String queryString = httpServletRequest.getQueryString();
+ if (queryString != null && queryString.contains(QUERY_STRING_FORCE_LOGOUT)) {
- openSession(validSession);
- SESSION_IN_PROGRESS.setOn(request);
+ authSessionStrategy.invalidate(httpServletRequest, httpServletResponse);
+ return;
+ }
- try {
- chain.doFilter(request, response);
- } finally {
- UNDEFINED.setOn(request);
- closeSession();
- }
- return;
- }
+ if (requestIsIgnoreExtension(this, httpServletRequest) ||
+ ResourceCachingFilter.isCachedResource(httpServletRequest)) {
+ chain.doFilter(request, response);
+ return;
+ }
- try {
- NO_SESSION_SINCE_NOT_AUTHENTICATED.setOn(request);
- filter.whenNoSession.handle(filter, httpRequest, httpResponse, chain);
- } catch (final RuntimeException ex) {
- // in case the destination servlet cannot cope, but we've
- // been told
- // to redirect elsewhere
- if (filter.redirectToOnException != null) {
- redirect(httpRequest, httpResponse, filter.redirectToOnException);
- return;
- }
- throw ex;
- } catch (final IOException ex) {
- if (filter.redirectToOnException != null) {
- redirect(httpRequest, httpResponse, filter.redirectToOnException);
- return;
- }
- throw ex;
- } catch (final ServletException ex) {
- // in case the destination servlet cannot cope, but we've
- // been told
- // to redirect elsewhere
- if (filter.redirectToOnException != null) {
- redirect(httpRequest, httpResponse, filter.redirectToOnException);
- return;
- }
- throw ex;
- } finally {
- UNDEFINED.setOn(request);
- // nothing to do
- }
+ // authenticate
+ final AuthenticationSession authSession =
+ authSessionStrategy.lookupValid(httpServletRequest, httpServletResponse);
+ if (authSession != null) {
+ authSessionStrategy.bind(httpServletRequest, httpServletResponse, authSession);
+ openSession(authSession); // is closed in the finally block
+ chain.doFilter(request, response);
+ return;
}
- private boolean requestIsIgnoreExtension(final IsisSessionFilter filter, final HttpServletRequest httpRequest) {
- final String servletPath = httpRequest.getServletPath();
- for (final Pattern extension : filter.ignoreExtensions) {
- if (extension.matcher(servletPath).matches()) {
- return true;
- }
+ try {
+ whenNotAuthenticated.handle(this, httpServletRequest, httpServletResponse, chain);
+ } catch (final RuntimeException | IOException | ServletException ex) {
+ // in case the destination servlet cannot cope, but we've
+ // been told to redirect elsewhere
+ if (redirectToOnException != null) {
+ redirect(httpServletRequest, httpServletResponse, redirectToOnException);
+ return;
}
- return false;
+ throw ex;
}
- },
- NO_SESSION_SINCE_REDIRECTING_TO_LOGON_PAGE, NO_SESSION_SINCE_NOT_AUTHENTICATED, SESSION_IN_PROGRESS;
-
- static SessionState lookup(final ServletRequest request) {
- final Object state = request.getAttribute(SESSION_STATE_KEY);
- return state != null ? (SessionState) state : SessionState.UNDEFINED;
- }
-
- boolean isValid(final AuthenticationSession authSession) {
- return authSession != null && getAuthenticationManager().isSessionValid(authSession);
- }
-
- void setOn(final ServletRequest request) {
- request.setAttribute(SESSION_STATE_KEY, this);
- }
- public void handle(final IsisSessionFilter filter, final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException {
- chain.doFilter(request, response);
+ } finally {
+ closeSession();
}
- AuthenticationManager getAuthenticationManager() {
- return IsisContext.getAuthenticationManager();
- }
-
- IsisSession openSession(final AuthenticationSession authSession) {
- return IsisContext.openSession(authSession);
- }
+ }
- void closeSession() {
- IsisContext.closeSession();
+ private boolean requestIsIgnoreExtension(final IsisSessionFilter filter, final HttpServletRequest httpRequest) {
+ final String servletPath = httpRequest.getServletPath();
+ for (final Pattern extension : filter.ignoreExtensions) {
+ if (extension.matcher(servletPath).matches()) {
+ return true;
+ }
}
+ return false;
+ }
+ protected IsisTransactionManager getTransactionManager() {
+ return IsisContext.getTransactionManager();
}
- @Override
- public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException {
+ private AuthenticationManager getAuthenticationManager() {
+ return IsisContext.getAuthenticationManager();
+ }
- final SessionState sessionState = SessionState.lookup(request);
- sessionState.handle(this, request, response, chain);
+ private IsisSession openSession(final AuthenticationSession authSession) {
+ return IsisContext.openSession(authSession);
}
-
- protected IsisTransactionManager getTransactionManager() {
- return IsisContext.getTransactionManager();
+ private void closeSession() {
+ IsisContext.closeSession();
}
+
}
http://git-wip-us.apache.org/repos/asf/isis/blob/edc4fa76/core/runtime/src/main/java/org/apache/isis/core/webapp/auth/AuthenticationSessionStrategy.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/webapp/auth/AuthenticationSessionStrategy.java b/core/runtime/src/main/java/org/apache/isis/core/webapp/auth/AuthenticationSessionStrategy.java
index b0f5bd4..b95bec8 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/webapp/auth/AuthenticationSessionStrategy.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/webapp/auth/AuthenticationSessionStrategy.java
@@ -19,8 +19,8 @@
package org.apache.isis.core.webapp.auth;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
import org.apache.isis.core.commons.authentication.AuthenticationSession;
import org.apache.isis.core.runtime.authentication.AuthenticationManager;
@@ -37,7 +37,9 @@ public interface AuthenticationSessionStrategy {
* {@link AuthenticationManager#isSessionValid(AuthenticationSession)
* still-valid} {@link AuthenticationSession}.
*/
- AuthenticationSession lookupValid(ServletRequest servletRequest, ServletResponse servletResponse);
+ AuthenticationSession lookupValid(final HttpServletRequest httpServletRequest, final HttpServletResponse httpServletResponse);
- void bind(ServletRequest servletRequest, ServletResponse servletResponse, AuthenticationSession authSession);
+ void bind(final HttpServletRequest httpServletRequest, final HttpServletResponse httpServletResponse, final AuthenticationSession authSession);
+
+ void invalidate(final HttpServletRequest httpServletRequest, final HttpServletResponse httpServletResponse);
}
http://git-wip-us.apache.org/repos/asf/isis/blob/edc4fa76/core/runtime/src/main/java/org/apache/isis/core/webapp/auth/AuthenticationSessionStrategyAbstract.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/webapp/auth/AuthenticationSessionStrategyAbstract.java b/core/runtime/src/main/java/org/apache/isis/core/webapp/auth/AuthenticationSessionStrategyAbstract.java
index 142340f..6f01b75 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/webapp/auth/AuthenticationSessionStrategyAbstract.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/webapp/auth/AuthenticationSessionStrategyAbstract.java
@@ -20,14 +20,16 @@ package org.apache.isis.core.webapp.auth;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.isis.core.commons.authentication.AuthenticationSession;
public abstract class AuthenticationSessionStrategyAbstract implements AuthenticationSessionStrategy {
+ public static final int STATUS_UNAUTHORIZED = 401;
+
protected HttpSession getHttpSession(final ServletRequest servletRequest) {
final HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
return httpServletRequest.getSession();
@@ -39,8 +41,14 @@ public abstract class AuthenticationSessionStrategyAbstract implements Authentic
}
@Override
- public void bind(final ServletRequest servletRequest, final ServletResponse servletResponse, final AuthenticationSession authSession) {
+ public void bind(final HttpServletRequest httpServletRequest, final HttpServletResponse httpServletResponse, final AuthenticationSession authSession) {
// no-op
}
+ @Override
+ public void invalidate(final HttpServletRequest httpServletRequest, final HttpServletResponse httpServletResponse) {
+ bind(httpServletRequest, httpServletResponse, null);
+ httpServletResponse.setStatus(STATUS_UNAUTHORIZED);
+ }
+
}
http://git-wip-us.apache.org/repos/asf/isis/blob/edc4fa76/core/runtime/src/main/java/org/apache/isis/core/webapp/auth/AuthenticationSessionStrategyDefault.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/isis/core/webapp/auth/AuthenticationSessionStrategyDefault.java b/core/runtime/src/main/java/org/apache/isis/core/webapp/auth/AuthenticationSessionStrategyDefault.java
index cf884ee..5d8350a 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/webapp/auth/AuthenticationSessionStrategyDefault.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/webapp/auth/AuthenticationSessionStrategyDefault.java
@@ -20,8 +20,8 @@
package org.apache.isis.core.webapp.auth;
import javax.servlet.ServletContext;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.isis.applib.fixtures.LogonFixture;
@@ -42,13 +42,13 @@ import org.apache.isis.core.webapp.WebAppConstants;
* The session is looked-up as follows:
* <ul>
* <li>it looks up from the {@link HttpSession} using the value
- * {@value WebAppConstants#HTTP_SESSION_AUTHENTICATION_SESSION_KEY}</li>
+ * {@link WebAppConstants#HTTP_SESSION_AUTHENTICATION_SESSION_KEY}</li>
* <li>failing that, if in exploration mode, then returns an exploration session
* </li>
* <li>failing that, if a {@link LogonFixture} has been provided and not already
* used, will provide an session for that fixture. The {@link HttpSession} also
* stores the value
- * {@value WebAppConstants#HTTP_SESSION_LOGGED_ON_PREVIOUSLY_USING_LOGON_FIXTURE_KEY}
+ * {@link WebAppConstants#HTTP_SESSION_LOGGED_ON_PREVIOUSLY_USING_LOGON_FIXTURE_KEY}
* in the session to track whether this has been done</li>
* </ul>
* <p>
@@ -56,10 +56,10 @@ import org.apache.isis.core.webapp.WebAppConstants;
public class AuthenticationSessionStrategyDefault extends AuthenticationSessionStrategyAbstract {
@Override
- public AuthenticationSession lookupValid(final ServletRequest servletRequest, final ServletResponse servletResponse) {
+ public AuthenticationSession lookupValid(final HttpServletRequest httpServletRequest, final HttpServletResponse httpServletResponse) {
final AuthenticationManager authenticationManager = getAuthenticationManager();
- final HttpSession httpSession = getHttpSession(servletRequest);
+ final HttpSession httpSession = getHttpSession(httpServletRequest);
// use previously authenticated session if available
AuthenticationSession authSession = (AuthenticationSession) httpSession.getAttribute(WebAppConstants.HTTP_SESSION_AUTHENTICATION_SESSION_KEY);
@@ -71,7 +71,7 @@ public class AuthenticationSessionStrategyDefault extends AuthenticationSessionS
}
// otherwise, look for LogonFixture and try to authenticate
- final ServletContext servletContext = getServletContext(servletRequest);
+ final ServletContext servletContext = getServletContext(httpServletRequest);
final IsisSystem system = (IsisSystem) servletContext.getAttribute(WebAppConstants.ISIS_SYSTEM_KEY);
if (system == null) {
// not expected to happen...
@@ -97,11 +97,19 @@ public class AuthenticationSessionStrategyDefault extends AuthenticationSessionS
}
@Override
- public void bind(final ServletRequest servletRequest, final ServletResponse servletResponse, final AuthenticationSession authSession) {
- final HttpSession httpSession = getHttpSession(servletRequest);
- httpSession.setAttribute(WebAppConstants.HTTP_SESSION_AUTHENTICATION_SESSION_KEY, authSession);
+ public void bind(
+ final HttpServletRequest httpServletRequest,
+ final HttpServletResponse httpServletResponse,
+ final AuthenticationSession authSession) {
+ final HttpSession httpSession = getHttpSession(httpServletRequest);
+ if(authSession != null) {
+ httpSession.setAttribute(WebAppConstants.HTTP_SESSION_AUTHENTICATION_SESSION_KEY, authSession);
+ } else {
+ httpSession.removeAttribute(WebAppConstants.HTTP_SESSION_AUTHENTICATION_SESSION_KEY);
+ }
}
+
// //////////////////////////////////////////////////////////
// Dependencies (from context)
// //////////////////////////////////////////////////////////
http://git-wip-us.apache.org/repos/asf/isis/blob/edc4fa76/core/viewer-restfulobjects-applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/Rel.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/Rel.java b/core/viewer-restfulobjects-applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/Rel.java
index 5381e1b..70d7699 100644
--- a/core/viewer-restfulobjects-applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/Rel.java
+++ b/core/viewer-restfulobjects-applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/Rel.java
@@ -58,7 +58,8 @@ public enum Rel {
// implementation specific
- CONTRIBUTED_BY(RelDefinition.IMPL, "contributed-by");
+ CONTRIBUTED_BY(RelDefinition.IMPL, "contributed-by"),
+ LOGOUT(RelDefinition.IMPL, "logout");
private final RelDefinition relDef;
private final String relSuffix;
http://git-wip-us.apache.org/repos/asf/isis/blob/edc4fa76/core/viewer-restfulobjects-applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/user/UserResource.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/user/UserResource.java b/core/viewer-restfulobjects-applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/user/UserResource.java
index ff53c07..afcc179 100644
--- a/core/viewer-restfulobjects-applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/user/UserResource.java
+++ b/core/viewer-restfulobjects-applib/src/main/java/org/apache/isis/viewer/restfulobjects/applib/user/UserResource.java
@@ -18,13 +18,19 @@
*/
package org.apache.isis.viewer.restfulobjects.applib.user;
-import javax.ws.rs.*;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
-import org.apache.isis.viewer.restfulobjects.applib.RestfulMediaType;
import org.jboss.resteasy.annotations.ClientResponseType;
+import org.apache.isis.viewer.restfulobjects.applib.RestfulMediaType;
+
@Path("/user")
public interface UserResource {
@@ -42,4 +48,13 @@ public interface UserResource {
@POST
public Response postUserNotAllowed();
+ /**
+ * Not part of the Restful Objects spec.
+ */
+ @GET
+ @Path("/logout")
+ @Produces({ MediaType.APPLICATION_JSON, RestfulMediaType.APPLICATION_JSON_HOME_PAGE })
+ @ClientResponseType(entityType = String.class)
+ public Response logout();
+
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/isis/blob/edc4fa76/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/RendererContext.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/RendererContext.java b/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/RendererContext.java
index 03ab027..a1b0821 100644
--- a/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/RendererContext.java
+++ b/core/viewer-restfulobjects-rendering/src/main/java/org/apache/isis/viewer/restfulobjects/rendering/RendererContext.java
@@ -35,7 +35,7 @@ public interface RendererContext {
public String urlFor(final String url);
public AuthenticationSession getAuthenticationSession();
-
+
public IsisConfiguration getConfiguration();
public PersistenceSession getPersistenceSession();
http://git-wip-us.apache.org/repos/asf/isis/blob/edc4fa76/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/authentication/AuthenticationSessionStrategyBasicAuth.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/authentication/AuthenticationSessionStrategyBasicAuth.java b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/authentication/AuthenticationSessionStrategyBasicAuth.java
index 54bd2b6..f8f69e5 100644
--- a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/authentication/AuthenticationSessionStrategyBasicAuth.java
+++ b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/authentication/AuthenticationSessionStrategyBasicAuth.java
@@ -21,9 +21,8 @@ package org.apache.isis.viewer.restfulobjects.server.authentication;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.codec.binary.Base64;
@@ -40,22 +39,20 @@ import org.apache.isis.core.webapp.auth.AuthenticationSessionStrategyAbstract;
*/
public class AuthenticationSessionStrategyBasicAuth extends AuthenticationSessionStrategyAbstract {
+ public static final String HEADER_AUTHORIZATION = "Authorization";
+ public static final String BASIC_AUTH_PREFIX = "Basic ";
+
private static Pattern USER_AND_PASSWORD_REGEX = Pattern.compile("^(.+):(.+)$");
@Override
- public AuthenticationSession lookupValid(final ServletRequest servletRequest, final ServletResponse servletResponse) {
-
- final HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
- final String authStr = httpServletRequest.getHeader("Authorization");
+ public AuthenticationSession lookupValid(final HttpServletRequest httpServletRequest, final HttpServletResponse httpServletResponse) {
- // value should be in the form:
- // Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
- if (authStr == null || !authStr.startsWith("Basic ")) {
+ final String digest = getBasicAuthDigest(httpServletRequest);
+ if (digest == null) {
return null;
}
- final String digest = authStr.substring(6);
- final String userAndPassword = new String(new Base64().decode(digest.getBytes()));
+ final String userAndPassword = unencoded(digest);
final Matcher matcher = USER_AND_PASSWORD_REGEX.matcher(userAndPassword);
if (!matcher.matches()) {
return null;
@@ -64,10 +61,28 @@ public class AuthenticationSessionStrategyBasicAuth extends AuthenticationSessio
final String user = matcher.group(1);
final String password = matcher.group(2);
- final AuthenticationSession authSession = getAuthenticationManager().authenticate(new AuthenticationRequestPassword(user, password));
+ final AuthenticationRequestPassword request = new AuthenticationRequestPassword(user, password);
+ final AuthenticationSession authSession =
+ getAuthenticationManager().authenticate(request);
return authSession;
}
+ // value should be in the form:
+ // Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
+ String getBasicAuthDigest(final HttpServletRequest httpServletRequest) {
+ final String authStr = httpServletRequest.getHeader(HEADER_AUTHORIZATION);
+ return authStr != null &&
+ authStr.startsWith(BASIC_AUTH_PREFIX)
+ ? authStr.substring(BASIC_AUTH_PREFIX.length())
+ : null;
+ }
+
+
+ protected String unencoded(final String encodedDigest) {
+ return new String(new Base64().decode(encodedDigest.getBytes()));
+ }
+
+
// //////////////////////////////////////////////////////////
// Dependencies (from context)
// //////////////////////////////////////////////////////////
http://git-wip-us.apache.org/repos/asf/isis/blob/edc4fa76/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/authentication/AuthenticationSessionStrategyHeader.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/authentication/AuthenticationSessionStrategyHeader.java b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/authentication/AuthenticationSessionStrategyHeader.java
index 84bfb73..cece9a6 100644
--- a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/authentication/AuthenticationSessionStrategyHeader.java
+++ b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/authentication/AuthenticationSessionStrategyHeader.java
@@ -21,9 +21,8 @@ package org.apache.isis.viewer.restfulobjects.server.authentication;
import java.util.Collections;
import java.util.List;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.google.common.base.Splitter;
@@ -43,11 +42,12 @@ import org.apache.isis.core.webapp.auth.AuthenticationSessionStrategyAbstract;
*/
public class AuthenticationSessionStrategyHeader extends AuthenticationSessionStrategyAbstract {
+ public static final String HEADER_ISIS_USER = "isis.user";
+
@Override
- public AuthenticationSession lookupValid(final ServletRequest servletRequest, final ServletResponse servletResponse) {
+ public AuthenticationSession lookupValid(final HttpServletRequest httpServletRequest, final HttpServletResponse httpServletResponse) {
- final HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
- final String user = httpServletRequest.getHeader("isis.user");
+ final String user = httpServletRequest.getHeader(HEADER_ISIS_USER);
final List<String> roles = rolesFrom(httpServletRequest);
if (Strings.isNullOrEmpty(user)) {
http://git-wip-us.apache.org/repos/asf/isis/blob/edc4fa76/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/authentication/AuthenticationSessionStrategyTrusted.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/authentication/AuthenticationSessionStrategyTrusted.java b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/authentication/AuthenticationSessionStrategyTrusted.java
index 666ccc3..16fbfc7 100644
--- a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/authentication/AuthenticationSessionStrategyTrusted.java
+++ b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/authentication/AuthenticationSessionStrategyTrusted.java
@@ -18,8 +18,8 @@
*/
package org.apache.isis.viewer.restfulobjects.server.authentication;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
import org.apache.isis.core.commons.authentication.AuthenticationSession;
import org.apache.isis.core.runtime.authentication.exploration.AuthenticationRequestExploration;
@@ -29,8 +29,8 @@ import org.apache.isis.core.webapp.auth.AuthenticationSessionStrategyDefault;
public class AuthenticationSessionStrategyTrusted extends AuthenticationSessionStrategyDefault {
@Override
- public AuthenticationSession lookupValid(final ServletRequest servletRequest, final ServletResponse servletResponse) {
- final AuthenticationSession session = super.lookupValid(servletRequest, servletResponse);
+ public AuthenticationSession lookupValid(final HttpServletRequest httpServletRequest, final HttpServletResponse httpServletResponse) {
+ final AuthenticationSession session = super.lookupValid(httpServletRequest, httpServletResponse);
if (session != null) {
return session;
}
http://git-wip-us.apache.org/repos/asf/isis/blob/edc4fa76/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/ResourceAbstract.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/ResourceAbstract.java b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/ResourceAbstract.java
index c014111..a570487 100644
--- a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/ResourceAbstract.java
+++ b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/ResourceAbstract.java
@@ -20,9 +20,14 @@ package org.apache.isis.viewer.restfulobjects.server.resources;
import java.io.InputStream;
import java.util.List;
+
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import javax.ws.rs.core.*;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.SecurityContext;
+import javax.ws.rs.core.UriInfo;
import javax.ws.rs.ext.Providers;
import org.apache.isis.applib.annotation.Where;
@@ -35,6 +40,7 @@ import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
import org.apache.isis.core.metamodel.adapter.oid.OidMarshaller;
import org.apache.isis.core.metamodel.services.ServiceUtil;
import org.apache.isis.core.metamodel.spec.SpecificationLoaderSpi;
+import org.apache.isis.core.runtime.authentication.AuthenticationManager;
import org.apache.isis.core.runtime.system.context.IsisContext;
import org.apache.isis.core.runtime.system.persistence.PersistenceSession;
import org.apache.isis.viewer.restfulobjects.applib.RepresentationType;
@@ -155,6 +161,10 @@ public abstract class ResourceAbstract {
return IsisContext.getAuthenticationSession();
}
+ protected AuthenticationManager getAuthenticationManager() {
+ return IsisContext.getAuthenticationManager();
+ }
+
protected SpecificationLoaderSpi getSpecificationLoader() {
return IsisContext.getSpecificationLoader();
}
http://git-wip-us.apache.org/repos/asf/isis/blob/edc4fa76/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/UserReprRenderer.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/UserReprRenderer.java b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/UserReprRenderer.java
index 6cd15bd..e37d4be 100644
--- a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/UserReprRenderer.java
+++ b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/UserReprRenderer.java
@@ -47,6 +47,7 @@ public class UserReprRenderer extends ReprRendererAbstract<UserReprRenderer, Aut
if (includesSelf) {
addLinkToSelf();
addLinkToUp();
+ addLinkToLogout();
}
getExtensions();
return representation;
@@ -76,5 +77,11 @@ public class UserReprRenderer extends ReprRendererAbstract<UserReprRenderer, Aut
getLinks().arrayAdd(link);
}
+ private void addLinkToLogout() {
+ final JsonRepresentation link = LinkBuilder.newBuilder(rendererContext, Rel.LOGOUT.getName(), RepresentationType.HOME_PAGE, "user/logout").build();
+
+ getLinks().arrayAdd(link);
+ }
+
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/isis/blob/edc4fa76/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/UserResourceServerside.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/UserResourceServerside.java b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/UserResourceServerside.java
index 9d1b0c6..0910aeb 100644
--- a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/UserResourceServerside.java
+++ b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/resources/UserResourceServerside.java
@@ -18,11 +18,15 @@
*/
package org.apache.isis.viewer.restfulobjects.server.resources;
+import java.net.URI;
+import java.net.URISyntaxException;
+
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.apache.isis.applib.annotation.Where;
+import org.apache.isis.core.webapp.IsisSessionFilter;
import org.apache.isis.viewer.restfulobjects.applib.JsonRepresentation;
import org.apache.isis.viewer.restfulobjects.applib.RepresentationType;
import org.apache.isis.viewer.restfulobjects.applib.RestfulMediaType;
@@ -62,4 +66,28 @@ public class UserResourceServerside extends ResourceAbstract implements UserReso
throw RestfulObjectsApplicationException.createWithMessage(RestfulResponse.HttpStatusCode.METHOD_NOT_ALLOWED, "Posting to the user resource is not allowed.");
}
+ /**
+ * Not part of the Restful Objects spec.
+ */
+ @Override
+ @Produces({ MediaType.APPLICATION_JSON, RestfulMediaType.APPLICATION_JSON_HOME_PAGE })
+ public Response logout() {
+ init(RepresentationType.HOME_PAGE, Where.NOWHERE);
+
+ final HomePageReprRenderer renderer = new HomePageReprRenderer(getResourceContext(), null, JsonRepresentation.newMap());
+ renderer.includesSelf();
+
+ // we do the logout (removes this session from those valid)
+ getAuthenticationManager().closeSession(getResourceContext().getAuthenticationSession());
+
+ // we also redirect to home page with special query string; this allows the session filter
+ // to clear out any cookies/headers (eg if BASIC auth in use).
+ try {
+ final URI location = new URI("?" + IsisSessionFilter.QUERY_STRING_FORCE_LOGOUT);
+ return Response.temporaryRedirect(location).build();
+ } catch (URISyntaxException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
}
http://git-wip-us.apache.org/repos/asf/isis/blob/edc4fa76/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/webapp/IsisTransactionFilterForRestfulObjects.java
----------------------------------------------------------------------
diff --git a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/webapp/IsisTransactionFilterForRestfulObjects.java b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/webapp/IsisTransactionFilterForRestfulObjects.java
index acc107b..af943ab 100644
--- a/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/webapp/IsisTransactionFilterForRestfulObjects.java
+++ b/core/viewer-restfulobjects-server/src/main/java/org/apache/isis/viewer/restfulobjects/server/webapp/IsisTransactionFilterForRestfulObjects.java
@@ -40,10 +40,18 @@ public class IsisTransactionFilterForRestfulObjects implements Filter {
try {
chain.doFilter(request, response);
} finally {
- getTransactionManager().endTransaction();
+ final boolean inTransaction = inTransaction();
+ if(inTransaction) {
+ // user/logout will have invalidated the current transaction and also persistence session.
+ getTransactionManager().endTransaction();
+ }
}
}
+ protected boolean inTransaction() {
+ return IsisContext.inTransaction();
+ }
+
protected IsisTransactionManager getTransactionManager() {
return IsisContext.getTransactionManager();
}