package org.pac4j.play;
import java.util.*;
import org.pac4j.core.context.Cookie;
import org.pac4j.core.context.Pac4jConstants;
import org.pac4j.core.context.WebContext;
import org.pac4j.core.context.session.SessionStore;
import org.pac4j.core.util.JavaSerializationHelper;
import play.api.mvc.RequestHeader;
import play.core.j.JavaHelpers$;
import play.mvc.Http;
import play.mvc.Http.Request;
import play.mvc.Http.Response;
import play.mvc.Http.Session;
import play.mvc.Http.Context;
import static org.pac4j.core.util.CommonHelper.assertNotNull;
/**
* <p>This class is the web context for Play (used both for Java and Scala).</p>
* <p>"Session objects" are managed by the defined {@link SessionStore}.</p>
* <p>"Request attributes" are saved/restored to/from the context.</p>
*
* @author Jerome Leleu
* @since 1.1.0
*/
public class PlayWebContext implements WebContext {
public final static String SB64_PREFIX = "{sb64}";
public final static JavaSerializationHelper JAVA_SERIALIZATION_HELPER = new JavaSerializationHelper();
protected final Context context;
protected final Request request;
protected final Response response;
protected final Session session;
protected SessionStore<PlayWebContext> sessionStore;
protected String responseContent = "";
public PlayWebContext(final Context context, final SessionStore<PlayWebContext> sessionStore) {
this.context = context;
this.request = context.request();
this.response = context.response();
this.session = context.session();
setSessionStore(sessionStore);
}
public PlayWebContext(final RequestHeader requestHeader, final SessionStore<PlayWebContext> sessionStore) {
this(JavaHelpers$.MODULE$.createJavaContext(requestHeader), sessionStore);
}
@Override
public SessionStore getSessionStore() {
return this.sessionStore;
}
@Override
public void setSessionStore(final SessionStore sessionStore) {
assertNotNull("sessionStore", sessionStore);
this.sessionStore = sessionStore;
}
/**
* Get the Java session.
*
* @return the Java session
*/
public Session getJavaSession() {
return session;
}
/**
* Get the Java context.
*
* @return the Java context.
*/
public Context getJavaContext() {
return this.context;
}
@Override
public void setResponseStatus(final int code) {}
@Override
public void writeResponseContent(final String content) {
if (content != null) {
this.responseContent += content;
}
}
/**
* Get the response content.
*
* @return the response content
*/
public String getResponseContent() {
return this.responseContent;
}
@Override
public String getRequestHeader(final String name) {
return request.getHeader(name);
}
@Override
public String getRequestMethod() {
return request.method();
}
@Override
public String getRequestParameter(final String name) {
final Map<String, String[]> parameters = getRequestParameters();
final String[] values = parameters.get(name);
if (values != null && values.length > 0) {
return values[0];
}
return null;
}
@Override
public Map<String, String[]> getRequestParameters() {
final Http.RequestBody body = request.body();
final Map<String, String[]> formParameters;
if (body != null) {
formParameters = body.asFormUrlEncoded();
} else {
formParameters = new HashMap<>();
}
final Map<String, String[]> urlParameters = request.queryString();
final Map<String, String[]> parameters = new HashMap<>();
if (formParameters != null) {
parameters.putAll(formParameters);
}
if (urlParameters != null) {
parameters.putAll(urlParameters);
}
return parameters;
}
@Override
public void setResponseHeader(final String name, final String value) {
response.setHeader(name, value);
}
@Override
public String getServerName() {
String[] split = request.host().split(":");
return split[0];
}
@Override
public int getServerPort() {
String[] split = request.host().split(":");
String portStr = split.length > 1 ? split[1] : "80";
return Integer.parseInt(portStr);
}
@Override
public String getScheme() {
if (request.secure()) {
return "https";
} else {
return "http";
}
}
@Override
public boolean isSecure() { return request.secure(); }
@Override
public String getFullRequestURL() {
return getScheme() + "://" + request.host() + request.uri();
}
@Override
public String getRemoteAddr() {
return request.remoteAddress();
}
@Override
public Object getRequestAttribute(final String name) {
Object value = context.args.get(name);
// this is a hack: we try to get the profiles as a serialized value because of the SecurityFilter
if (Pac4jConstants.USER_PROFILES.equals(name) && value != null && value instanceof String) {
final String sValue = (String) value;
if (sValue.startsWith(SB64_PREFIX)) {
value = JAVA_SERIALIZATION_HELPER.unserializeFromBase64(sValue.substring(SB64_PREFIX.length()));
}
}
return value;
}
@Override
public void setRequestAttribute(final String name, final Object value) {
context.args.put(name, value);
}
@Override
public Collection<Cookie> getRequestCookies() {
final List<Cookie> cookies = new ArrayList<>();
final Http.Cookies httpCookies = request.cookies();
httpCookies.forEach(httpCookie -> {
final Cookie cookie = new Cookie(httpCookie.name(), httpCookie.value());
if(httpCookie.domain() != null) {
cookie.setDomain(httpCookie.domain());
}
cookie.setHttpOnly(httpCookie.httpOnly());
if(httpCookie.maxAge() != null) {
cookie.setMaxAge(httpCookie.maxAge());
}
cookie.setPath(httpCookie.path());
cookie.setSecure(httpCookie.secure());
cookies.add(cookie);
});
return cookies;
}
@Override
public String getPath() {
return request.path();
}
@Override
public void addResponseCookie(final Cookie cookie) {
response.setCookie(new Http.Cookie(
cookie.getName(),
cookie.getValue(),
cookie.getMaxAge() == -1 ? null : cookie.getMaxAge(),
cookie.getPath(),
cookie.getDomain(),
cookie.isSecure(),
cookie.isHttpOnly()));
}
@Override
public void setResponseContentType(final String content) {
response.setContentType(content);
}
}