It's not the same without you

Join the community to find out what other Atlassian users are discussing, debating and creating.

Atlassian Community Hero Image Collage

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
Community showcase
Published in Training & Certification

Atlassian University Live: How to earn your first Atlassian credential

Atlassian University Live webinars provide you and your teams with the chance to strengthen your Atlassian product skills, and learn directly from Atlassian experts. Learn how to earn our newest A...

58 views 0 6
Read article

Community Events

Connect with like-minded Atlassian users at free events near you!

Find an event

Connect with like-minded Atlassian users at free events near you!

Unfortunately there are no Community Events near you at the moment.

Host an event

You're one step closer to meeting fellow Atlassian users at your local event. Learn more about Community Events

Events near you