Skip to content

Instantly share code, notes, and snippets.

@jechlin
Created August 7, 2019 10:39
Show Gist options
  • Save jechlin/969edd1ed05721492f063c55891c4b7a to your computer and use it in GitHub Desktop.
Save jechlin/969edd1ed05721492f063c55891c4b7a to your computer and use it in GitHub Desktop.
import com.atlassian.jira.bc.JiraServiceContextImpl
import com.atlassian.jira.bc.filter.SearchRequestService
import com.atlassian.jira.bc.portal.PortalPageService
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.permission.GlobalPermissionKey
import com.atlassian.jira.permission.GlobalPermissionType
import com.atlassian.jira.portal.PortalPage
import com.atlassian.jira.sharing.SharePermissionImpl
import com.atlassian.jira.sharing.SharedEntity
import com.atlassian.jira.sharing.search.SharedEntitySearchParametersBuilder
import com.atlassian.jira.sharing.type.ShareType
import com.atlassian.sal.api.ApplicationProperties
import com.atlassian.sal.api.UrlMode
import com.onresolve.scriptrunner.runner.ScriptRunnerImpl
import groovy.xml.MarkupBuilder
/**
* Run this with FIX_MODE = false to report on any problems.
* To rectify all the issues change to: FIX_MODE = true.
*/
final FIX_MODE = false
def searchRequestService = ComponentAccessor.getComponent(SearchRequestService)
def currentUser = ComponentAccessor.jiraAuthenticationContext.loggedInUser
def applicationProperties = ScriptRunnerImpl.getOsgiService(ApplicationProperties)
def portalPageService = ComponentAccessor.getComponent(PortalPageService)
def globalPermissionManager = ComponentAccessor.globalPermissionManager
def contextPath = applicationProperties.getBaseUrl(UrlMode.RELATIVE)
def writer = new StringWriter()
def markup = new MarkupBuilder(writer)
def serviceContext = new JiraServiceContextImpl(currentUser)
def publicSharePerm = new SharePermissionImpl(null, ShareType.Name.GLOBAL, null, null)
def searchParameters = new SharedEntitySearchParametersBuilder().setSharePermission(publicSharePerm).toSearchParameters()
searchRequestService.validateForSearch(serviceContext, searchParameters)
assert !serviceContext.errorCollection.hasAnyErrors()
def result = searchRequestService.search(serviceContext, searchParameters, 0, Integer.MAX_VALUE)
final authenticatedUserSharePerms = new SharedEntity.SharePermissions([
new SharePermissionImpl(null, ShareType.Name.AUTHENTICATED, null, null)
] as Set)
markup.h3('Filters')
if (!result.results) {
markup.p('No publicly accessible filters found')
}
result.results.each { filter ->
if (FIX_MODE) {
filter.setPermissions(authenticatedUserSharePerms)
def filterUpdateContext = new JiraServiceContextImpl(filter.owner)
searchRequestService.updateFilter(filterUpdateContext, filter)
if (filterUpdateContext.errorCollection.hasAnyErrors()) {
log.warn("Error updating filter - possibly owner has been deleted. Just delete the filter. " + filterUpdateContext.errorCollection)
}
}
markup.p {
a(href: "$contextPath/issues/?filter=${filter.id}", target: '_blank', filter.name)
i(' publicly accessible. ' + (FIX_MODE ? ' Fixed.' : ''))
}
}
def dashResults = portalPageService.search(serviceContext, searchParameters, 0, Integer.MAX_VALUE).results.findAll {
!it.systemDefaultPortalPage
}
markup.h3('Dashboards')
if (!dashResults) {
markup.p('No publicly accessible dashboards found')
}
dashResults.each { dashboard ->
if (dashboard.isSystemDefaultPortalPage()) {
// can't edit the system default dashboard
return
}
if (FIX_MODE) {
def updatedDashboard = new PortalPage.Builder().portalPage(dashboard).permissions(authenticatedUserSharePerms).build()
portalPageService.updatePortalPageUnconditionally(serviceContext, currentUser, updatedDashboard)
}
markup.p {
a(href: "$contextPath/secure/Dashboard.jspa?selectPageId=${dashboard.id}", target: '_blank', dashboard.name)
i(' publicly accessible. ' + (FIX_MODE ? ' Fixed.' : ''))
}
}
final GlobalPermissionType GPT_BROWSE_USERS = new GlobalPermissionType(GlobalPermissionKey.USER_PICKER.key, null, null, false);
markup.h3('Global Permissions')
if (globalPermissionManager.hasPermission(GlobalPermissionKey.USER_PICKER, null)) {
if (FIX_MODE) {
globalPermissionManager.removePermission(GPT_BROWSE_USERS, null)
}
markup.p {
b('Browse Users')
i(' is publicly accessible. ' + (FIX_MODE ? ' : Fixed' : ''))
}
} else {
markup.p('No problems with global permissions found')
}
writer.toString()
@mdoar
Copy link

mdoar commented Aug 7, 2019

Handy! The script was able to show 27,000 shared filters and dashboards just fine. But when I tried to fix that many I got an error
"Failed to post update"
I guess some limit on the number of changes to make would help avoid this, though the script would have to be run multiple times.

@jechlin
Copy link
Author

jechlin commented Aug 7, 2019

I think it probably carried on in the background... if you rerun with fix = false the number should be fewer. There's a long-standing issue where the UI times out if the script takes a long time. I did do it in pages originally, the problem was that results changed each time search is called as the ones that have been fixed no longer match the search params. Probably needs a bit more work tbh...

@mdoar
Copy link

mdoar commented Aug 7, 2019

You're right. Count is now at 11,000

@ItaloQualisoni
Copy link

Thanks @jechlin for this script, we used for bulk fix filters/dashboard for a migration.

We adapted the script to transfer filters ownership for deactivated users to the current user.

Sharing below in case someone needs it (probably the myself in the future...)

Tested in Jira 8.20 and the current user must have Admin rights in Jira.

import com.atlassian.jira.bc.JiraServiceContextImpl
import com.atlassian.jira.bc.filter.SearchRequestService
import com.atlassian.jira.bc.portal.PortalPageService
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.permission.GlobalPermissionKey
import com.atlassian.jira.permission.GlobalPermissionType
import com.atlassian.jira.portal.PortalPage
import com.atlassian.jira.sharing.SharePermissionImpl
import com.atlassian.jira.sharing.SharedEntity
import com.atlassian.jira.sharing.search.SharedEntitySearchParametersBuilder
import com.atlassian.jira.sharing.type.ShareType
import com.atlassian.sal.api.ApplicationProperties
import com.atlassian.sal.api.UrlMode
import com.onresolve.scriptrunner.runner.ScriptRunnerImpl
import groovy.xml.MarkupBuilder

/**
 * Run this with FIX_MODE = false to report on any problems.
 * To rectify all the issues change to: FIX_MODE = true.
 */

final FIX_MODE = true

def searchRequestService = ComponentAccessor.getComponent(SearchRequestService)
def currentUser = ComponentAccessor.jiraAuthenticationContext.loggedInUser
def applicationProperties = ScriptRunnerImpl.getOsgiService(ApplicationProperties)
def portalPageService = ComponentAccessor.getComponent(PortalPageService)
def globalPermissionManager = ComponentAccessor.globalPermissionManager

def contextPath = applicationProperties.getBaseUrl(UrlMode.RELATIVE)

def writer = new StringWriter()
def markup = new MarkupBuilder(writer)

def serviceContext = new JiraServiceContextImpl(currentUser)
def publicSharePerm = new SharePermissionImpl(null, ShareType.Name.GLOBAL, null, null)
def searchParameters = new SharedEntitySearchParametersBuilder().setSharePermission(publicSharePerm).toSearchParameters()

searchRequestService.validateForSearch(serviceContext, searchParameters)
assert !serviceContext.errorCollection.hasAnyErrors()

def result = searchRequestService.search(serviceContext, searchParameters, 0, Integer.MAX_VALUE)
final authenticatedUserSharePerms = new SharedEntity.SharePermissions([
    new SharePermissionImpl(null, ShareType.Name.AUTHENTICATED, null, null)
] as Set)

markup.h3('Filters')

if (!result.results) {
    markup.p('No publicly accessible filters found')
}
result.results.each { filter ->
    def filterOwnerActive = filter.owner.active;

    if (FIX_MODE) {

        filter.setPermissions(authenticatedUserSharePerms)

        def filterUpdateContext
        
        if(filterOwnerActive){
            filterUpdateContext = new JiraServiceContextImpl(filter.owner)
            searchRequestService.updateFilter(filterUpdateContext, filter)
            if (filterUpdateContext.errorCollection.hasAnyErrors()) {
                log.warn("Error updating filter - possibly owner has been deleted. Just delete the filter. " + filterUpdateContext.errorCollection)
            }
        }

        else{
            //change ownership to current User
            filterUpdateContext = new JiraServiceContextImpl(currentUser)
            filter.setOwner(currentUser)
            //This method apparently update both filter owner and its permissions
            searchRequestService.updateFilterOwner(filterUpdateContext, currentUser, filter)
        }
    }
    markup.p {
        a(href: "$contextPath/issues/?filter=${filter.id}", target: '_blank', filter.name)
        i(' publicly accessible. ' + (FIX_MODE ? ' Fixed.' : '') + (!filterOwnerActive? ' Transfering to ownership to current user':''))
    }
}

def dashResults = portalPageService.search(serviceContext, searchParameters, 0, Integer.MAX_VALUE).results.findAll {
    !it.systemDefaultPortalPage
}

markup.h3('Dashboards')

if (!dashResults) {
    markup.p('No publicly accessible dashboards found')
}
dashResults.each { dashboard ->
    if (dashboard.isSystemDefaultPortalPage()) {
        // can't edit the system default dashboard
        return
    }
    if (FIX_MODE) {
        def updatedDashboard = new PortalPage.Builder().portalPage(dashboard).permissions(authenticatedUserSharePerms).build()
        portalPageService.updatePortalPageUnconditionally(serviceContext, currentUser, updatedDashboard)
    }
    markup.p {
        a(href: "$contextPath/secure/Dashboard.jspa?selectPageId=${dashboard.id}", target: '_blank', dashboard.name)
        i(' publicly accessible. ' + (FIX_MODE ? ' Fixed.' : ''))
    }
}

final GlobalPermissionType GPT_BROWSE_USERS = new GlobalPermissionType(GlobalPermissionKey.USER_PICKER.key, null, null, false);

markup.h3('Global Permissions')
if (globalPermissionManager.hasPermission(GlobalPermissionKey.USER_PICKER, null)) {
    if (FIX_MODE) {
        globalPermissionManager.removePermission(GPT_BROWSE_USERS, null)
    }
    markup.p {
        b('Browse Users')
        i(' is publicly accessible. ' + (FIX_MODE ? ' : Fixed' : ''))
    }
} else {
    markup.p('No problems with global permissions found')
}

writer.toString()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment