package com.peterphi.std.guice.web.rest.service.jwt;

import com.auth0.jwt.JWTSigner;
import com.google.inject.Inject;
import com.google.inject.name.Named;
import com.peterphi.std.guice.apploader.GuiceConstants;
import com.peterphi.std.guice.apploader.GuiceProperties;
import com.peterphi.std.guice.common.auth.annotations.AuthConstraint;
import com.peterphi.std.guice.web.HttpCallContext;
import com.peterphi.std.guice.web.rest.service.GuiceCoreTemplater;
import com.peterphi.std.guice.web.rest.templating.TemplateCall;
import org.apache.commons.lang.StringUtils;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpSession;
import java.util.Map;

/**
 *
 */
@AuthConstraint(id = "framework-jwtgenerate", skip = true)
public class JwtCreationRestServiceImpl implements JwtCreationRestService
{
	/**
	 * The resource prefix
	 */
	private static final String PREFIX = "/com/peterphi/std/guice/web/rest/service/restcore/";

	@Inject
	GuiceCoreTemplater templater;

	@Inject(optional = true)
	@Named(GuiceProperties.AUTH_JWT_HTTP_COOKIE)
	public String cookieName = GuiceConstants.JAXRS_SERVER_WEBAUTH_JWT_COOKIE_NAME;


	@Override
	public String getIndex(String message)
	{
		final TemplateCall template = templater.template(PREFIX + "jwt_index.html");

		template.set("message", message);

		return template.process();
	}


	@Override
	public String getResult(String token, final String secret, final String payload, final String op)
	{
		final TemplateCall template = templater.template(PREFIX + "jwt_generated.html");

		final Long expireTime;
		if (token == null)
		{
			// Decode JSON from payload object
			Map<String, Object> claims = JSONUtil.parse(payload);

			expireTime = (Long) claims.get("exp");


			JWTSigner signer = new JWTSigner(secret);

			token = signer.sign(claims);
		}
		else
		{
			Map<String, Object> claims = JWTInspector.getClaims(token);
			expireTime = (Long) claims.get("exp");
		}

		final boolean save = StringUtils.equalsIgnoreCase("save", op);

		// Optionally save as a cookie
		if (save)
		{

			Cookie cookie = new Cookie(cookieName, token);

			// Expire the cookie 1 minute before the token expires
			if (expireTime != null)
				cookie.setMaxAge(expireTime.intValue() - 60);

			// Kill the current session (just in case it's associated with a job manager login)
			final HttpSession session = HttpCallContext.get().getRequest().getSession(false);

			if (session != null)
				session.invalidate();

			// Now add the JWT cookie
			HttpCallContext.get().getResponse().addCookie(cookie);
		}

		template.set("saved", save);
		template.set("token", token);

		return template.process();
	}
}

@@ -632,16 +632,37 @@
 ession;%0A
+import java.net.URI;%0A
 import j
@@ -1144,16 +1144,162 @@
 _NAME;%0A%0A
+%09/**%0A%09 * The URI for the webapp (for setting the JWT cookie path)%0A%09 */%0A%09@Named(GuiceProperties.STATIC_ENDPOINT_CONFIG_NAME)%0A%09URI webappEndpoint;%0A%0A
 %0A%09@Overr
@@ -1882,17 +1882,16 @@
 exp%22);%0A%0A
-%0A
 %09%09%09JWTSi
@@ -2200,17 +2200,16 @@
 ve)%0A%09%09%7B%0A
-%0A
 %09%09%09Cooki
@@ -2247,24 +2247,403 @@
 e, token);%0A%0A
+%09%09%09// Set the cookie path based on the webapp endpoint path%0A%09%09%09cookie.setPath(webappEndpoint.getPath());%0A%0A%09%09%09// If the webapp has an https endpoint (or if we were accessed by HTTPS) then set the cookie as a secure cookie%0A%09%09%09cookie.setSecure(HttpCallContext.get().getRequest().isSecure() %7C%7C%0A%09%09%09                 StringUtils.equalsIgnoreCase(%22https%22, webappEndpoint.getScheme()));%0A%0A
 %09%09%09// Expire

Use the webapp path when setting JWT cookie