From 5acfcd74a14d0feac4f885c9bf8a9584b3cfc6e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mandresy=20Ga=C3=ABtan=20RANDRIANANTOANINA?= Date: Thu, 9 Jul 2026 23:09:37 +0300 Subject: [PATCH 1/4] feat: add FeesOnly annotation for fee-only mode --- src/main/java/school/hei/haapi/endpoint/FeesOnly.java | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/main/java/school/hei/haapi/endpoint/FeesOnly.java diff --git a/src/main/java/school/hei/haapi/endpoint/FeesOnly.java b/src/main/java/school/hei/haapi/endpoint/FeesOnly.java new file mode 100644 index 000000000..837dddb44 --- /dev/null +++ b/src/main/java/school/hei/haapi/endpoint/FeesOnly.java @@ -0,0 +1,8 @@ +package school.hei.haapi.endpoint; + +import java.lang.annotation.*; + +@Target({ElementType.TYPE, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface FeesOnly { +} \ No newline at end of file From e5fb6551dfb11cd5efa437ca6b11ba6a1f8e5d35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mandresy=20Ga=C3=ABtan=20RANDRIANANTOANINA?= Date: Thu, 9 Jul 2026 23:12:08 +0300 Subject: [PATCH 2/4] feat: add FeesOnly interceptor for fee-only mode --- .../haapi/endpoint/FeesOnlyInterceptor.java | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 src/main/java/school/hei/haapi/endpoint/FeesOnlyInterceptor.java diff --git a/src/main/java/school/hei/haapi/endpoint/FeesOnlyInterceptor.java b/src/main/java/school/hei/haapi/endpoint/FeesOnlyInterceptor.java new file mode 100644 index 000000000..d92bc6259 --- /dev/null +++ b/src/main/java/school/hei/haapi/endpoint/FeesOnlyInterceptor.java @@ -0,0 +1,57 @@ +package school.hei.haapi.endpoint; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.HandlerInterceptor; + +@Slf4j +@Component +public class FeesOnlyInterceptor implements HandlerInterceptor { + private final boolean feesOnly; + public FeesOnlyInterceptor(@Value("${FEES_ONLY:false}") boolean feesOnly) { + this.feesOnly = feesOnly; + } + @Override + public boolean preHandle( + HttpServletRequest request, + HttpServletResponse response, + Object handler) throws Exception { + + String uri = request.getRequestURI(); + + if (!feesOnly || isAlwaysAllowed(uri)) {return true;} + if (!(handler instanceof HandlerMethod handlerMethod)) {return true;} + boolean allowed = + handlerMethod.getBeanType().isAnnotationPresent(FeesOnly.class) + || handlerMethod.getMethod().isAnnotationPresent(FeesOnly.class); + if (!allowed) { + log.warn("Blocked by FEES_ONLY: {} {}", request.getMethod(), uri); + response.sendError( + HttpServletResponse.SC_FORBIDDEN, + "FEES_ONLY mode active"); + return false; + } + return true; + } + private boolean isAlwaysAllowed(String uri) { + return uri.equals("/whoami") + || uri.equals("/ping") + || uri.equals("/health/db") + || uri.startsWith("/authentication/") + || uri.startsWith("/oauth2/") + || uri.startsWith("/oauth2/authorization/") + || uri.startsWith("/login") + || uri.startsWith("/login/oauth2/") + || uri.startsWith("/logout") + || uri.startsWith("/error") + || uri.startsWith("/actuator") + || uri.startsWith("/auth/") + || uri.startsWith("/api/auth/") + || uri.startsWith("/callback") + || uri.startsWith("/casdoor/"); + } +} \ No newline at end of file From 6a9acda59ea7ae3ac052969cbfc17a091abb9061 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mandresy=20Ga=C3=ABtan=20RANDRIANANTOANINA?= Date: Thu, 9 Jul 2026 23:14:51 +0300 Subject: [PATCH 3/4] feat: register FeesOnly interceptor in Spring MVC --- .../FeesOnlyInterceptorConfigurer.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/main/java/school/hei/haapi/endpoint/FeesOnlyInterceptorConfigurer.java diff --git a/src/main/java/school/hei/haapi/endpoint/FeesOnlyInterceptorConfigurer.java b/src/main/java/school/hei/haapi/endpoint/FeesOnlyInterceptorConfigurer.java new file mode 100644 index 000000000..4d21528de --- /dev/null +++ b/src/main/java/school/hei/haapi/endpoint/FeesOnlyInterceptorConfigurer.java @@ -0,0 +1,19 @@ +package school.hei.haapi.endpoint; + +import lombok.AllArgsConstructor; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +@AllArgsConstructor +public class FeesOnlyInterceptorConfigurer implements WebMvcConfigurer { + + private final FeesOnlyInterceptor feesOnlyInterceptor; + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(feesOnlyInterceptor) + .addPathPatterns("/**"); + } +} \ No newline at end of file From fd71f2181a27840d58c4be3734f565f9d8eaa977 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mandresy=20Ga=C3=ABtan=20RANDRIANANTOANINA?= Date: Thu, 9 Jul 2026 23:20:06 +0300 Subject: [PATCH 4/4] feat: annotate necessary controllers for fee-only mode --- .../hei/haapi/endpoint/rest/controller/AdminController.java | 2 ++ .../hei/haapi/endpoint/rest/controller/FeeController.java | 2 ++ .../hei/haapi/endpoint/rest/controller/ManagerController.java | 2 ++ .../hei/haapi/endpoint/rest/controller/PaymentController.java | 2 ++ .../hei/haapi/endpoint/rest/controller/StudentController.java | 2 ++ 5 files changed, 10 insertions(+) diff --git a/src/main/java/school/hei/haapi/endpoint/rest/controller/AdminController.java b/src/main/java/school/hei/haapi/endpoint/rest/controller/AdminController.java index f1c0c4949..815a2d1ab 100644 --- a/src/main/java/school/hei/haapi/endpoint/rest/controller/AdminController.java +++ b/src/main/java/school/hei/haapi/endpoint/rest/controller/AdminController.java @@ -5,6 +5,7 @@ import lombok.AllArgsConstructor; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; +import school.hei.haapi.endpoint.FeesOnly; import school.hei.haapi.endpoint.rest.mapper.UserMapper; import school.hei.haapi.endpoint.rest.model.Admin; import school.hei.haapi.endpoint.rest.model.CrupdateManager; @@ -13,6 +14,7 @@ @RestController @AllArgsConstructor +@FeesOnly public class AdminController { private final UserService userService; diff --git a/src/main/java/school/hei/haapi/endpoint/rest/controller/FeeController.java b/src/main/java/school/hei/haapi/endpoint/rest/controller/FeeController.java index ecaa43fcc..c9a211ba4 100644 --- a/src/main/java/school/hei/haapi/endpoint/rest/controller/FeeController.java +++ b/src/main/java/school/hei/haapi/endpoint/rest/controller/FeeController.java @@ -20,6 +20,7 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import school.hei.haapi.endpoint.FeesOnly; import school.hei.haapi.endpoint.rest.mapper.FeeMapper; import school.hei.haapi.endpoint.rest.mapper.FeeTemplateMapper; import school.hei.haapi.endpoint.rest.model.*; @@ -37,6 +38,7 @@ @RestController @AllArgsConstructor +@FeesOnly @Slf4j public class FeeController { private final UserService userService; diff --git a/src/main/java/school/hei/haapi/endpoint/rest/controller/ManagerController.java b/src/main/java/school/hei/haapi/endpoint/rest/controller/ManagerController.java index 10eca5a12..2d6583a3a 100644 --- a/src/main/java/school/hei/haapi/endpoint/rest/controller/ManagerController.java +++ b/src/main/java/school/hei/haapi/endpoint/rest/controller/ManagerController.java @@ -14,6 +14,7 @@ import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; +import school.hei.haapi.endpoint.FeesOnly; import school.hei.haapi.endpoint.rest.mapper.SexEnumMapper; import school.hei.haapi.endpoint.rest.mapper.StatusEnumMapper; import school.hei.haapi.endpoint.rest.mapper.UserMapper; @@ -30,6 +31,7 @@ @RestController @AllArgsConstructor +@FeesOnly public class ManagerController { private final SexEnumMapper sexEnumMapper; private final StatusEnumMapper statusEnumMapper; diff --git a/src/main/java/school/hei/haapi/endpoint/rest/controller/PaymentController.java b/src/main/java/school/hei/haapi/endpoint/rest/controller/PaymentController.java index 7181b72d5..aaea7ed2e 100644 --- a/src/main/java/school/hei/haapi/endpoint/rest/controller/PaymentController.java +++ b/src/main/java/school/hei/haapi/endpoint/rest/controller/PaymentController.java @@ -11,6 +11,7 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import school.hei.haapi.endpoint.FeesOnly; import school.hei.haapi.endpoint.rest.mapper.PaymentMapper; import school.hei.haapi.endpoint.rest.model.CreatePayment; import school.hei.haapi.endpoint.rest.model.Payment; @@ -21,6 +22,7 @@ @RestController @AllArgsConstructor +@FeesOnly public class PaymentController { private final PaymentService paymentService; private final PaymentMapper paymentMapper; diff --git a/src/main/java/school/hei/haapi/endpoint/rest/controller/StudentController.java b/src/main/java/school/hei/haapi/endpoint/rest/controller/StudentController.java index 0ba5cad80..49818eda9 100644 --- a/src/main/java/school/hei/haapi/endpoint/rest/controller/StudentController.java +++ b/src/main/java/school/hei/haapi/endpoint/rest/controller/StudentController.java @@ -17,6 +17,7 @@ import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; +import school.hei.haapi.endpoint.FeesOnly; import school.hei.haapi.endpoint.rest.mapper.GroupFlowMapper; import school.hei.haapi.endpoint.rest.mapper.SexEnumMapper; import school.hei.haapi.endpoint.rest.mapper.StatusCheckMapper; @@ -50,6 +51,7 @@ @RestController @AllArgsConstructor +@FeesOnly public class StudentController { private final UserService userService; private final UserMapper userMapper;