==============================================================================
Demo 4 -- what you can actually write inside @PreAuthorize / @PostAuthorize
==============================================================================
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.

alice: ROLE_USER, ROLE_AUDITOR, plus the authority 'report:read'
----------------------------------------------------------------
  permitAll                                      ALLOWED  -> ok
  denyAll                                        DENIED   -> AuthorizationDeniedException: Access Denied
  isAuthenticated()                              ALLOWED  -> ok
  isAnonymous()                                  DENIED   -> AuthorizationDeniedException: Access Denied
  isFullyAuthenticated()                         ALLOWED  -> ok
  isRememberMe()                                 DENIED   -> AuthorizationDeniedException: Access Denied
  hasRole('ADMIN')                               DENIED   -> AuthorizationDeniedException: Access Denied
  hasAnyRole('ADMIN','AUDITOR')                  ALLOWED  -> ok
  hasAllRoles('USER','AUDITOR')                  ALLOWED  -> ok
  hasAuthority('report:read')                    ALLOWED  -> ok
  hasAnyAuthority('report:read','x')             ALLOWED  -> ok
  hasAllAuthorities('report:read','x')           DENIED   -> AuthorizationDeniedException: Access Denied
  authentication.name == 'alice'                 ALLOWED  -> ok
  principal == 'alice'                           ALLOWED  -> ok

root: ROLE_ADMIN only (RoleHierarchy says ADMIN > USER > GUEST)
---------------------------------------------------------------
  permitAll                                      ALLOWED  -> ok
  denyAll                                        DENIED   -> AuthorizationDeniedException: Access Denied
  isAuthenticated()                              ALLOWED  -> ok
  isAnonymous()                                  DENIED   -> AuthorizationDeniedException: Access Denied
  isFullyAuthenticated()                         ALLOWED  -> ok
  isRememberMe()                                 DENIED   -> AuthorizationDeniedException: Access Denied
  hasRole('ADMIN')                               ALLOWED  -> ok
  hasAnyRole('ADMIN','AUDITOR')                  ALLOWED  -> ok
  hasAllRoles('USER','AUDITOR')                  DENIED   -> AuthorizationDeniedException: Access Denied
  hasAuthority('report:read')                    DENIED   -> AuthorizationDeniedException: Access Denied
  hasAnyAuthority('report:read','x')             DENIED   -> AuthorizationDeniedException: Access Denied
  hasAllAuthorities('report:read','x')           DENIED   -> AuthorizationDeniedException: Access Denied
  authentication.name == 'alice'                 DENIED   -> AuthorizationDeniedException: Access Denied
  principal == 'alice'                           DENIED   -> AuthorizationDeniedException: Access Denied

Role prefix and hierarchy
-------------------------
  hasRole('USER')       -> ROLE_USER             ALLOWED  -> ok
  hasAuthority('USER')  -> literal 'USER'        DENIED   -> AuthorizationDeniedException: Access Denied
  hasAuthority('ROLE_USER')                      ALLOWED  -> ok
  root hasRole('GUEST') via RoleHierarchy        ALLOWED  -> ok

Method arguments, the return value, and bean references
-------------------------------------------------------
  #owner == authentication.name  ("alice")       ALLOWED  -> ok
  #owner == authentication.name  ("bob")         DENIED   -> AuthorizationDeniedException: Access Denied
  @P("o") alias, #o == ...name  ("alice")        ALLOWED  -> ok
  #root.this  (the target object)                ALLOWED  -> ok
  #root.args[0]  -- no such property             DENIED   -> IllegalArgumentException: Failed to evaluate expression '#root.args[0] == authentication.name'  [cause: SpelEvaluationException: EL1008E: Property or field 'args' cannot be found on object of type 'org.springframework.security.access.expression.method.MethodSecurityExpressionRoot' - maybe not public or not valid?]
  @policy.canRead(authentication, #id) id=1      ALLOWED  -> ok
  @policy.canRead(authentication, #id) id=9      DENIED   -> AuthorizationDeniedException: Access Denied
  hasPermission(#id, 'account', 'read') id=1     ALLOWED  -> ok
  hasPermission(#id, 'account', 'read') id=9     DENIED   -> AuthorizationDeniedException: Access Denied
  T(java.time.LocalDate) type reference          ALLOWED  -> ok
  @PostAuthorize returnObject.owner == ...name   ALLOWED  -> Account[1,alice,100]
  @PostAuthorize returnObject.owner == ...name   DENIED   -> AuthorizationDeniedException: Access Denied

The literal constants on SecurityExpressionRoot
-----------------------------------------------
  permitAll / denyAll exist as BOTH a boolean field and a no-arg method,
  and read/write/create/delete/admin are String constants meant for
  hasPermission(..) -- e.g. hasPermission(#id, 'account', read).
  hasPermission(#id, 'account', read) id=1       ALLOWED  -> ok
