Come for the products,
stay for the community

The Atlassian Community can help you and your team get more value out of Atlassian products and practices.

Atlassian Community about banner
4,331,552
Community Members
 
Community Events
169
Community Groups

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

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 Nov 02, 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

 

 

Yes!. Thank you!

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

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

TAGS

Atlassian Community Events