Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Boot @RestController enable/disable methods using properties [duplicate]

I can enable/disable the whole @RestController using @ConditionalOnProperty, for example:

@RestController
@ConditionalOnProperty(name = "com.example.api.controller.decision.DecisionController.enabled", havingValue = "true")
@RequestMapping("/v1.0/decisions")
public class DecisionController {
}

The following configuration works fine. But I need to have more fine-grained control over this controller and enable/disable access to the certain methods inside, for example:

@RestController
@ConditionalOnProperty(name = "com.example.api.controller.decision.DecisionController.enabled", havingValue = "true")
@RequestMapping("/v1.0/decisions")
public class DecisionController {

    @ConditionalOnProperty(name = "com.example.api.controller.decision.DecisionController.create.enabled", havingValue = "true")
    @PreAuthorize("isAuthenticated()")
    @RequestMapping(method = RequestMethod.POST)
    public DecisionResponse create(@Valid @RequestBody CreateDecisionRequest request, Authentication authentication) {
        ...
    }

}

As you may see, I have added @ConditionalOnProperty to create method but this approach doesn't work and in case of enabled DecisionController the create method is also enabled even if com.example.api.controller.decision.DecisionController.create.enabled property is absent in my application.properties.

How to properly enable/disable create method in this case ?

like image 276
alexanoid Avatar asked Apr 08 '18 07:04

alexanoid


1 Answers

You could also use aop to not proceed with method execution and return some status to the user. I'm using annotation here to mark/ identify disabled methods. You could add attributes to that annotation if you want to disable based on certain values in the attributes. Like you can add same property name and havingvalue and look for those and so on...

@Retention(RUNTIME)
@Target(METHOD)
public @interface DisableMe {}

Aspect:

@Aspect
@Component
public class DisableCertainAPI {

  @Autowired private HttpServletResponse httpServletResponse;

  @Pointcut(" @annotation(disableMe)")
  protected void disabledMethods(DisableMe disableMe) {
    // disabled methods pointcut
  }

  @Around("disabledMethods(disableMe)")
  public void dontRun(JoinPoint jp, DisableMe disableMe) throws IOException {
    httpServletResponse.sendError(HttpStatus.NOT_FOUND.value(), "Not found");
  }
}

and on target methods :

 @DisableMe
 @GetMapping(...)
 public ResponseEntity<String> doSomething(...){
  logger.info("recieved a request");
 }

you would see a response like :

{
  "timestamp": "2019-11-11T16:29:31.454+0000",
  "status": 404,
  "error": "Not Found",
  "message": "Not found",
  "path": "/xyz/...."
}
like image 166
user3487063 Avatar answered Sep 20 '22 17:09

user3487063