permissionadminservice.revokeAllRepositoryPermissions in a listener

I want to revoke permissions from a repository’s forks in an event listener. I’m using permissionadminservice.revokeAllRepositoryPermissions in 5.3.0. no matter what i do it throws a hibernate exception saying it needs to be called in a transaction. how do i do this?

Btw this same code worked in 4.14.4.

So at this point this is the only thing keeping me from upgrading to 5.3+ from 4.14.4. Any help on getting this to work in my listener would be most appreciated. Alternate solutions also welcome.

    private void propagate()
    {
        final List<Repository> forks = new ArrayList<>();

        Page<Repository> page = repositoryService.findByOrigin(repository, new PageRequestImpl(0, PageRequest.MAX_PAGE_LIMIT));
        forks.addAll(newHashSet(page.getValues()));

        boolean allGathered = page.getIsLastPage();

        while (!allGathered)
        {
            page = repositoryService.findByOrigin(repository,
                new PageRequestImpl(page.getNextPageRequest().getStart(), PageRequest.MAX_PAGE_LIMIT));
            forks.addAll(newHashSet(page.getValues()));
            allGathered = page.getIsLastPage();
        }

        forks.forEach(fork -> {
            List<String> permittedUsers = getPermittedUserNames(repository);
            List<String> permittedGroups = getPermittedGroupNames(repository);

            getPermittedUsers(fork).forEach(user ->
            {
                if (!permittedUsers.contains(user.getUser().getName()))
                {
                    permissionAdminService.revokeAllRepositoryPermissions(fork, user.getUser());
                }
            });
            
            getPermittedGroupNames(fork).forEach(group ->
            {
                if (!permittedGroups.contains(group))
                {
                    permissionAdminService.revokeAllRepositoryPermissions(fork, group);
                }
            });

            // propagate to forks of forks
            new ForkRepositoryType(propertiesService, fork, permissionAdminService, bambooPlanService, mailService,
                permissionService, repositoryService, stashHelper).propagate();

        });
    }

I’ve encountered that a couple of times that 5.x’s transaction model is slightly different that pre-5.x (My best guess would be because of spring boot). Before doing write’s and things like that would be done automagically on GETs and such. However with 5.x it looks like there’s a difference of a read translation AND a READ/WRITE transaction.

Couple of things to try:

  1. Inject https://developer.atlassian.com/static/javadoc/sal/2.3/reference/com/atlassian/sal/api/transaction/TransactionTemplate.html and do everything that would be a write operation in it.
  2. Annotate your event with https://developer.atlassian.com/static/javadoc/bitbucket-server/5.3.1/api/reference/com/atlassian/bitbucket/event/annotation/TransactionAware.html

I think #1 will fix it for you though…

Same deal with both of those :pensive:

javax.persistence.TransactionRequiredException: Executing an update/delete query

Did I use this right?

            getPermittedUsers(fork).forEach(user -> {
                if (!permittedUsers.contains(user.getUser().getName()))
                {
                    transactionTemplate.execute((TransactionCallback<Void>)() -> {
                        permissionAdminService.revokeAllRepositoryPermissions(fork, user.getUser());
                        return null;
                    });
                }
            });

            getPermittedGroupNames(fork).forEach(group -> {
                if (!permittedGroups.contains(group))
                {
                    transactionTemplate.execute((TransactionCallback<Void>)() -> {
                        permissionAdminService.revokeAllRepositoryPermissions(fork, group);
                        return null;
                    });
                }
            });

Yeah that looks right. Which event are you triggering off (so I can try to recreate)?

PermissionGrantedEvent and PermissionRevokedEvent

Here’s a stripped down version of my plugin to demonstrate the issue I’m seeing.

Once installed, when you add, modify, or remove permissions from a repository the listener will attempt make sure the repository’s forks don’t allow unauthorized access to the code. This fails however because the exception mentioned above is thrown.

https://github.com/jshap999/lib/raw/master/ccad-listener-permissions-broken-1.0.0-STASH_5.3.0.jar

BTW code is bundled in the jar.

Didn’t think it would be different but still see the issue going from 5.3.0 to 5.3.1. Let me just say having all site specific configuration outside of the installation is amazing. Needing JAVA_HOME and JRE_HOME is a bit weird but seriously 5.3.0 to 5.3.1 upgrade was essentially shut it down move a symlink and start it back up. kudos.

This is really odd. Looking at the source code for Bitbucket it has a lot of Transactional( org.springframework.transaction.annotation.Transactional ) stuff in it (particular this area).

Digging through the source code though - it looks like ActiveObjects has transaction stuff as well - so on idea would be to wrap your call with
ao.executeInTransaction(() -> { ...your code here... });

I’m grasping at straws but that’s my last guess (or perhaps annotating with @Transactional )

Tried both of those to no avail. Also tried changing the method visibility. Guess it’s time to start looking for another way to handle this task. Thanks for your help.

Any thoughts on this one Brent? @bplump

Well, my company no longer exists so I guess I don’t care about this anymore. Hope it gets fixed. My final solution was just to email me so I could manage the permissions manually.