package org.jboss.resteasy.tests.signature;

import org.jboss.resteasy.annotations.security.doseta.After;
import org.jboss.resteasy.annotations.security.doseta.Signed;
import org.jboss.resteasy.annotations.security.doseta.Verify;
import org.jboss.resteasy.security.doseta.DKIMSignature;
import org.junit.Assert;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;

/**
 * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
 * @version $Revision: 1 $
 */
@Path("/signed")
public class SignedResource
{
   /**
    * Sign a returned message using a private key named "test._domainKey.samplezone.org"
    * found in the key store.
    *
    * @return
    */
   @GET
   @Signed(selector = "test", domain = "samplezone.org")
   @Produces("text/plain")
   public String hello()
   {
      return "hello world";
   }

   /**
    * Sign a returned message using a private key named "test._domainKey.samplezone.org"
    * found in the key store.  A header named "custom" is included in the signature calculation.
    * The signature header is created manually here instead of using annotations.
    *
    * @return
    */
   @GET
   @Path("manual-header")
   @Produces("text/plain")
   public Response withHeader()
   {
      Response.ResponseBuilder builder = Response.ok("hello world");
      builder.header("custom", "value");
      DKIMSignature signature = new DKIMSignature();
      signature.setSelector("test");
      signature.setDomain("samplezone.org");
      signature.addHeader("custom");
      builder.header(DKIMSignature.DKIM_SIGNATURE, signature);
      return builder.build();
   }

   /**
    * Verify a posted signature. Inject it and print it out too.
    *
    * @param signature
    * @param input
    */
   @POST
   @Consumes("text/plain")
   @Verify
   public void post(@HeaderParam(DKIMSignature.DKIM_SIGNATURE) DKIMSignature signature, String input)
   {
      Assert.assertNotNull(signature);
      Assert.assertEquals(input, "hello world");
   }

   /**
    * Sign a returned message, but also add a timestamp to the signature calculation.
    *
    * @return
    */
   @GET
   @Signed(selector = "test", domain = "samplezone.org",
           timestamped = true)
   @Produces("text/plain")
   @Path("stamped")
   public String getStamp()
   {
      return "hello world";
   }

   /**
    * Sign a message setting the expiration field of the DKIM-Signature to be 1 second after the current time
    *
    * @return
    */
   @GET
   @Signed(selector = "test", domain = "samplezone.org",
           expires = @After(seconds = 1))
   @Produces("text/plain")
   @Path("expires-short")
   public String getExpiresShort()
   {
      return "hello world";
   }

   /**
    * Sign a message setting the expiration field of the DKIM-Signature to be 1 minute after the current time
    *
    * @return
    */
   @GET
   @Signed(selector = "test", domain = "samplezone.org",
           expires = @After(minutes = 1))
   @Produces("text/plain")
   @Path("expires-minute")
   public String getExpiresMinute()
   {
      return "hello world";
   }

   /**
    * Example of sending a signature signed by a bad or expired key.
    *
    * @return
    * @throws Exception
    */
   @GET
   @Produces("text/plain")
   @Path("bad-signature")
   public Response badSignature() throws Exception
   {
      DKIMSignature signature = new DKIMSignature();
      signature.setDomain("samplezone.org");
      signature.setSelector("test");
      KeyPair keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
      PrivateKey badKey = keyPair.getPrivate();
      signature.setPrivateKey(badKey);

      return Response.ok("hello world").header(DKIMSignature.DKIM_SIGNATURE, signature).build();
   }


}
