feat(auth): add @RequiresHouseholdRole annotation with interceptor
Reusable annotation for planner-only endpoints. Uses a HandlerInterceptor that resolves the household role from the authenticated user and throws 403 if the role doesn't match. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
package com.recipeapp.common;
|
||||
|
||||
import com.recipeapp.recipe.HouseholdResolver;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
|
||||
@Component
|
||||
public class HouseholdRoleInterceptor implements HandlerInterceptor {
|
||||
|
||||
private final HouseholdResolver householdResolver;
|
||||
|
||||
public HouseholdRoleInterceptor(HouseholdResolver householdResolver) {
|
||||
this.householdResolver = householdResolver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
|
||||
if (!(handler instanceof HandlerMethod handlerMethod)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
RequiresHouseholdRole annotation = handlerMethod.getMethodAnnotation(RequiresHouseholdRole.class);
|
||||
if (annotation == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
if (auth == null) {
|
||||
throw new ForbiddenException("Not authenticated");
|
||||
}
|
||||
|
||||
String actualRole = householdResolver.resolveRole(auth.getName());
|
||||
if (!annotation.value().equals(actualRole)) {
|
||||
throw new ForbiddenException("Requires household role: " + annotation.value());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user