==============================================================================
Demo 8 -- meta-annotations, templates, class-level rules, ambiguity
==============================================================================

A plain meta-annotation needs no extra configuration
----------------------------------------------------
SLF4J(W): No SLF4J providers were found.
SLF4J(W): Defaulting to no-operation (NOP) logger implementation
SLF4J(W): See https://www.slf4j.org/codes.html#noProviders for further details.
  @IsAdmin  (alice, ROLE_USER)                   DENIED   -> AuthorizationDeniedException: Access Denied
  @IsAdmin  (root, ROLE_ADMIN)                   ALLOWED  -> ok

A TEMPLATED meta-annotation, with NO AnnotationTemplateExpressionDefaults bean
------------------------------------------------------------------------------
  @HasRole("ADMIN") as root (ROLE_ADMIN)         ALLOWED  -> ok
  @HasRole("ADMIN") as alice (ROLE_USER)         DENIED   -> AuthorizationDeniedException: Access Denied

  '{value}' was substituted anyway. The reference documentation says you
  must publish an AnnotationTemplateExpressionDefaults bean for templated
  meta-annotations to work; in 7.1.1 you do not.
  PreAuthorizeExpressionAttributeRegistry initialises its scanner with
  SecurityAnnotationScanners.requireUnique(PreAuthorize.class), and that
  overload constructs a default AnnotationTemplateExpressionDefaults for
  you. Publishing the bean only changes ignoreUnknown.

The same annotation WITH the AnnotationTemplateExpressionDefaults bean
----------------------------------------------------------------------
  @HasRole("ADMIN") as root (ROLE_ADMIN)         ALLOWED  -> ok
  @HasRole("ADMIN") as alice (ROLE_USER)         DENIED   -> AuthorizationDeniedException: Access Denied
  @HasRole("USER")  as alice (ROLE_USER)         ALLOWED  -> ok

Class-level rules, and what a method-level one does to them
-----------------------------------------------------------
  inherited from the class  (needs ADMIN)        DENIED   -> AuthorizationDeniedException: Access Denied
  method-level overrides it (needs USER)         ALLOWED  -> ok
  class @PreAuthorize AND method @PostAuthorize  DENIED   -> AuthorizationDeniedException: Access Denied

Two interfaces, two different @PreAuthorize on the same method
--------------------------------------------------------------
  context started fine.
  bean type -> jdk.proxy2.$Proxy21
  read()  -- inherits two conflicting rules      DENIED   -> AnnotationConfigurationException: Please ensure there is one unique annotation of type [interface org.springframework.security.access.prepost.PreAuthorize] attributed to public abstract java.lang.String com.ankurm.methodsec.Demo8MetaAnnotations$ReadsAsUser.read(). Found 2 competing annotations: [@org.springframework.security.access.prepost.PreAuthorize("hasRole('USER')"), @org.springframework.security.access.prepost.PreAuthorize("hasRole('ADMIN')")]

  It is not a startup failure: the context refreshes, the bean is
  proxied, and the conflict only surfaces when the method is called.
  The fix is to put @PreAuthorize on the implementation method, which
  is the nearest declaration and therefore wins outright.
