I can't create multiple restrictions for a branch using rest api

Javier Perez
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 1, 2016

Description: I want to set read-only and fast-forward-only restrictions to a branch using REST API as explained here, to which I'm using the following json body

[{
     "type": "read-only",
     "matcher": {
         "id": "refs/heads/branch",
         "type": {
             "id": "BRANCH"
         }
     },
     "users": ["user1", "user2"]
 }, {
     "type": "fast-forward-only",
     "matcher": {
         "id": "refs/heads/branch",
         "type": {
             "id": "BRANCH"
         }
     },
     "users": []
 }]

Problem: the server returns this error

2016-11-01 20:40:11,595 ERROR [http-nio-7990-exec-5] user @TXKC43x1240x158645x0 twtz3z xxx.xx.xx.xxx,yyy.yy.yy.yyy "POST /rest/branch-permissions/2.0/projects/project/repos/repo/restrictions HTTP/1.1" c.a.s.i.r.e.DefaultUnhandledExceptionMapperHelper Unhandled exception while processing REST request: "POST /rest/branch-permissions/2.0/projects/project/repos/repo/restrictions HTTP/1.1"
org.codehaus.jackson.map.JsonMappingException: Can not deserialize instance of com.atlassian.stash.internal.repository.ref.restriction.rest.RestRestrictionRequest out of START_ARRAY token
 at [Source: com.atlassian.stash.internal.web.util.web.CountingServletInputStream@4f61a3c8; line: 2, column: 1]
        at org.codehaus.jackson.map.JsonMappingException.from(JsonMappingException.java:163) ~[atlassian-rest-module-3.0.12_1465914404000.jar:1.9.13]
...
...

Question1: What's wrong?

Question2: We have tens of repos so we need to use REST API to lock a branch across all of them. This works well when the restriction is a single request, like read-only. But when using REST with a single request to lock/unlock the branch any other restriction the branch could have, like fast-forward-only, goes away. If the multiple request REST API above is faulty like it seems to be, what other alternative could be used, using just bitbucket, without the help of external plugins?

2 answers

1 accepted

Comments for this post are closed

Community moderators have prevented the ability to post new answers.

Post a new question

0 votes
Answer accepted
rsperafico
Atlassian Team
Atlassian Team members are employees working across the company in a wide variety of roles.
November 2, 2016

Hello Javier Perez,

Tested

[{
        "type": "read-only",
        "matcher": {
            "id": "refs/heads/feature/branch-a",
            "displayId": "feature/branch-a",
            "type": {
                "id": "BRANCH",
                "name": "Branch"
            },
            "active": true
        },
        "users": ["admin", "git"],
        "groups": []
    }, {
        "type": "fast-forward-only",
        "matcher": {
            "id": "refs/heads/feature/branch-b",
            "displayId": "feature/branch-b",
            "type": {
                "id": "BRANCH",
                "name": "Branch"
            },
            "active": true
        },
        "users": ["admin"],
        "groups": []
}]
$ curl -u admin:admin -H "Content-Type: application/vnd.atl.bitbucket.bulk+json" -X POST -d '@payload.json' -X POST http://localhost:7990/rest/branch-permissions/2.0/projects/proj/repos/repository/restrictions

What should be

Please, make sure you have used "Content-Type: application/vnd.atl.bitbucket.bulk+json" as described in https://developer.atlassian.com/static/rest/bitbucket-server/4.7.1/bitbucket-ref-restriction-rest.html#idp55472

Allows creating multiple restrictions at once.

Example request representations:

  • application/vnd.atl.bitbucket.bulk+json

What you have used

The link you have provided https://developer.atlassian.com/static/rest/bitbucket-server/4.7.1/bitbucket-ref-restriction-rest.html#idp33216 refers to "Content-Type: application/json"

Create a restriction for the supplied branch or set of branches.

Example request representations:

  • application/json

Kind regards,
Rafael P. Sperafico

 

 

Javier Perez
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 2, 2016

Yes!. Thank you!

2 votes
adammarkham
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 2, 2016

You could use ScriptRunner for Bitbucket Server to do this which allows you to write scripts to automate tasks and extends the capabilities of Bitbucket Server.

You can run the following code in the Script Console to restrict branch permissions across all the master branches for each repository you have in your instance. The Script Console can be found by going to Admin ->ScriptRunner -> Script Console.

import com.atlassian.bitbucket.repository.Repository
import com.atlassian.bitbucket.repository.RepositoryService
import com.atlassian.bitbucket.repository.StandardRefType
import com.atlassian.bitbucket.repository.ref.restriction.RefMatcherProviderRegistry
import com.atlassian.bitbucket.repository.ref.restriction.RefRestrictionService
import com.atlassian.bitbucket.repository.ref.restriction.RefRestrictionType
import com.atlassian.bitbucket.repository.ref.restriction.SetRestrictionRequest
import com.atlassian.bitbucket.user.UserService
import com.atlassian.bitbucket.util.*
import com.atlassian.sal.api.component.ComponentLocator
import com.onresolve.scriptrunner.runner.ScriptRunnerImpl

import javax.annotation.Nonnull

def repositoryService = ComponentLocator.getComponent(RepositoryService)
def userService = ComponentLocator.getComponent(UserService)
def restrictionService = ScriptRunnerImpl.getOsgiService(RefRestrictionService)
def refMatcherProviderRegistry = ScriptRunnerImpl.getOsgiService(RefMatcherProviderRegistry)

// this will read 50 repositories at a time
def repositories = new PagedIterable<Repository>(new PageProvider<Repository>() {
    @Override
    Page<Repository> get(@Nonnull PageRequest pageRequest) {
        repositoryService.findAll(pageRequest)
    }
}, new PageRequestImpl(0, 50))

// replace with your user name/slugs
def userSlugs = ["user1", "user2"]

// this will apply branch restrictions to each repository
repositories.each { repository ->

    def provider = refMatcherProviderRegistry.getProvider(StandardRefType.BRANCH.name())

    // replace this with your branch
    def branchId = "refs/heads/master"
    def matcher = provider.create(repository, branchId)

    def users = userSlugs.collect {
        userService.getUserBySlug(it)
    }

    def readOnlyRestriction = new SetRestrictionRequest.Builder(repository, matcher, RefRestrictionType.READ_ONLY).grantUsers(users).build()

// prevent rewriting history def fastForwardRestriction = new SetRestrictionRequest.Builder(repository, matcher, RefRestrictionType.FAST_FORWARD_ONLY).build() def modified = restrictionService.setRestrictions([readOnlyRestriction, fastForwardRestriction]) log.warn "Restrictions modified: ${modified*.type}" } "Restrictions modified"

If you would like to just do it for a single repository you can use the script below:

import com.atlassian.bitbucket.repository.RepositoryService
import com.atlassian.bitbucket.repository.StandardRefType
import com.atlassian.bitbucket.repository.ref.restriction.RefMatcherProviderRegistry
import com.atlassian.bitbucket.repository.ref.restriction.RefRestrictionService
import com.atlassian.bitbucket.repository.ref.restriction.RefRestrictionType
import com.atlassian.bitbucket.repository.ref.restriction.SetRestrictionRequest
import com.atlassian.bitbucket.user.UserService
import com.atlassian.sal.api.component.ComponentLocator
import com.onresolve.scriptrunner.runner.ScriptRunnerImpl

def repositoryService = ComponentLocator.getComponent(RepositoryService)
def userService = ComponentLocator.getComponent(UserService)
def restrictionService = ScriptRunnerImpl.getOsgiService(RefRestrictionService)
def refMatcherProviderRegistry = ScriptRunnerImpl.getOsgiService(RefMatcherProviderRegistry)

// replace the two below with your project key and repository slug
def repositorySlug = "rep_1"
def projectKey = "PROJECT_1"

def repository = repositoryService.getBySlug(projectKey, repositorySlug)

// replace with your user name/slugs
def userSlugs = ["admin", "user"]

// this will apply branch restrictions to each repository

def provider = refMatcherProviderRegistry.getProvider(StandardRefType.BRANCH.name())

// replace this with your branch
def branchId = "refs/heads/master"
def matcher = provider.create(repository, branchId)

def users = userSlugs.collect {
    userService.getUserBySlug(it)
}

def readOnlyRestriction = new SetRestrictionRequest.Builder(repository, matcher, RefRestrictionType.READ_ONLY).grantUsers(users).build()

def fastForwardRestriction = new SetRestrictionRequest.Builder(repository, matcher, RefRestrictionType.FAST_FORWARD_ONLY).build()

def modified = restrictionService.setRestrictions([readOnlyRestriction, fastForwardRestriction])

"Restrictions modified: ${modified*.type}"

I have indicated in each script where you can replace the usernames and repository slugs with your ones.

Let me know if you have any further questions regarding the product and how you get on with it.

Hope this helps,
Adam

Brad Moulder July 22, 2019

This is great. However I need this to be able to set permissions based on pattern. Is this possible?

TAGS
AUG Leaders

Atlassian Community Events