package com.restfully.shop.features;
import javax.annotation.Priority;
import javax.ws.rs.ForbiddenException;
import javax.ws.rs.Priorities;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ResourceInfo;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.SecurityContext;
import java.io.IOException;
import java.lang.reflect.Method;
import java.security.Principal;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@AllowedPerDay(0)
@Priority(Priorities.AUTHORIZATION)
public class PerDayAuthorizer implements ContainerRequestFilter
{
@Context
ResourceInfo info;
public void filter(ContainerRequestContext requestContext) throws IOException
{
SecurityContext sc = requestContext.getSecurityContext();
if (sc == null) throw new ForbiddenException();
Principal principal = sc.getUserPrincipal();
if (principal == null) throw new ForbiddenException();
String user = principal.getName();
if (!authorized(user))
{
throw new ForbiddenException();
}
}
protected static class UserMethodKey
{
String username;
Method method;
public UserMethodKey(String username, Method method)
{
this.username = username;
this.method = method;
}
@Override
public boolean equals(Object o)
{
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
UserMethodKey that = (UserMethodKey) o;
if (!method.equals(that.method)) return false;
if (!username.equals(that.username)) return false;
return true;
}
@Override
public int hashCode()
{
int result = username.hashCode();
result = 31 * result + method.hashCode();
return result;
}
}
protected Map<UserMethodKey, Integer> count = new HashMap<UserMethodKey, Integer>();
protected long today = System.currentTimeMillis();
protected synchronized boolean authorized(String user)
{
if (System.currentTimeMillis() > today + (24 * 60 * 60 * 1000))
{
today = System.currentTimeMillis();
count.clear();
}
UserMethodKey key = new UserMethodKey(user, info.getResourceMethod());
Integer counter = count.get(key);
if (counter == null)
{
counter = 0;
}
AllowedPerDay allowed = info.getResourceMethod().getAnnotation(AllowedPerDay.class);
if (allowed.value() > counter)
{
count.put(key, counter + 1);
return true;
}
return false;
}
}