Class AdminAclEvaluationTest

java.lang.Object
ubic.gemma.core.security.acl.AdminAclEvaluationTest

public class AdminAclEvaluationTest extends Object
Reproducer for the long-standing Phase-3 ACL evaluation bug surfaced by UserGroupServiceTest#testUpdateUserGroup: when the admin test user (authority GROUP_ADMIN) calls a method protected by @PreAuthorize("hasPermission(#group, 'administration')") on a UserGroup whose ACL was created by BaseAclAdvice.setupBaseAces(MutableAcl, ObjectIdentity, Sid, boolean) — which inserts a GrantedAuthoritySid("GROUP_ADMIN") ADMINISTRATION granting=true ACE — the evaluation returns false even though by inspection it should return true.

The hasAuthority('GROUP_ADMIN') or ... disjunct in gsec UserService.removeUserFromGroup is the workaround we want to drop; this test is the gating fixture for that work.

Runs on the same in-memory ACL fixture as AclEventListenerTest (no Hibernate, no JDBC, no MySQL), wired with the same Spring Security collaborators production uses: AclPermissionEvaluator, gsec's AclSidRetrievalStrategyImpl (role-hierarchy aware), and a real RoleHierarchyImpl carrying Gemma's GROUP_ADMIN > GROUP_USER > IS_AUTHENTICATED_ANONYMOUSLY hierarchy.

  • Constructor Details

    • AdminAclEvaluationTest

      public AdminAclEvaluationTest()
  • Method Details

    • setUp

      @BeforeEach public void setUp()
    • tearDown

      @AfterEach public void tearDown()
    • sidRetrievalForAdmin_includesGroupAdminAuthoritySid

      @Test public void sidRetrievalForAdmin_includesGroupAdminAuthoritySid()
      Sanity check: the role-hierarchy-aware sid retrieval really does emit a GrantedAuthoritySid("GROUP_ADMIN") for an admin user, so the ACE sid and the user sid should match.
    • adminHasAdministrationOnUserGroupAcl

      @Test public void adminHasAdministrationOnUserGroupAcl()
      The headline reproducer. ACL set up exactly as BaseAclAdvice#setupBaseAces would (with the UserGroup-specific extra READ-by-own-group ACE), then ask AclPermissionEvaluator.hasPermission(admin, group, "administration").
    • adminLacksWriteWhenOnlyAdministrationAceExists

      @Test public void adminLacksWriteWhenOnlyAdministrationAceExists()
      Same setup, but ask for WRITE. Spring's BasePermission.WRITE (mask=2) is NOT the same as BasePermission.ADMINISTRATION (mask=16), so an ADMINISTRATION-only ACE should NOT satisfy a WRITE permission check. This test exists to pin down the contract — if the hasPermission(group, 'write') disjunct in the SpEL is ever to do useful work for admin, it has to come from a different ACE.
    • curatorHasAdministrationOnAnObjectFromSetupBaseAces

      @Test public void curatorHasAdministrationOnAnObjectFromSetupBaseAces()
      A curator holds ADMINISTRATION through the ace setupBaseAces now grants GROUP_CURATOR, which is what lets every ACL_SECURABLE_EDIT check pass for them.

      ADMINISTRATION rather than WRITE is deliberate and this is where it shows: it is also what AclAuthorizationStrategyImpl falls back to when the caller lacks the configured authority, so the same ace covers editing a design AND changing a dataset's visibility. A WRITE ace would satisfy the edit check and then fail on makePublic.

    • anAdministratorSatisfiesACuratorAce

      @Test public void anAdministratorSatisfiesACuratorAce()
      🛑 The rule the whole widening rests on: an ADMINISTRATOR satisfies a GROUP_CURATOR ace through the hierarchy. 61 routes moved from hasAuthority('GROUP_ADMIN') to hasAuthority('GROUP_CURATOR'), and if this direction did not hold, every one of them would have locked administrators out of work they could do the day before.
    • aCuratorDoesNotSatisfyAnAdminOnlyAce

      @Test public void aCuratorDoesNotSatisfyAnAdminOnlyAce()
      🛑 And it does NOT run the other way. A curator must never satisfy an admin-only ace, or the user-account and server-operation routes that kept hasAuthority('GROUP_ADMIN') would be open to them — which is the entire distinction between the two groups.
    • aPlainUserDoesNotSatisfyACuratorAce

      @Test public void aPlainUserDoesNotSatisfyACuratorAce()
      A plain user is unaffected by the curator ace -- the widening gave nothing to GROUP_USER.
    • aCuratorHasNoAuthorityOverAUserGroup

      @Test public void aCuratorHasNoAuthorityOverAUserGroup()
      🛑 A curator has NO ace on a User or UserGroup, so they cannot reach BaseUserService.removeUserFromGroup — whose gate is hasPermission(#group, 'write') or hasPermission(#group, 'administration').

      Without the exclusion in setupBaseAces, a curator satisfies that check and can move anyone between groups, themselves into Administrators included — which is precisely the authority the group was defined not to have. This is not hypothetical: the first production backfill granted over every acl_object_identity and 668 aces (661 users plus the groups) had to be deleted back out an hour later.

      The ace list here is what setupBaseAces writes for a user-group object: admin and agent, no curator.