Confluence Macro to Show User Installed Jira Apps

Overview

When working in Jira it is good to know which apps are installed the capabilities they provide. This script provides a Confluence macro to show a list of apps a user has installed on their Jira instance, and the gadgets and functionality they provide.

Example

I am a project manager preparing a report. I would like to see a full list of all apps installed and their gadgets so I can make use of all available capabilities to customise and enhance my flexible dashboards.

Good to Know

  • This script requires Application Links. If an error like this You don’t have an authorized access token for the remote resource is rendered when macro is executed, this means that an OAuth impersonation needs to be added to the link.

Requirements

Confluence Confluence (6.6 - 6.15)

    
import com.atlassian.applinks.api.ApplicationLinkResponseHandler import com.atlassian.applinks.api.ApplicationLinkService import com.atlassian.applinks.api.application.jira.JiraApplicationType import com.atlassian.confluence.xhtml.api.XhtmlContent import com.atlassian.sal.api.component.ComponentLocator import com.atlassian.sal.api.net.Request import com.atlassian.sal.api.net.Response import com.atlassian.sal.api.net.ResponseException import groovy.json.JsonSlurper import groovy.xml.MarkupBuilder import groovyx.net.http.HTTPBuilder import groovyx.net.http.HttpResponseException import org.json.JSONObject // Link to primary linked Jira instance def appLinkService = ComponentLocator.getComponent(ApplicationLinkService) def appLink = appLinkService.getPrimaryApplicationLink(JiraApplicationType) def applicationLinkRequestFactory = appLink.createAuthenticatedRequestFactory() // HTTP Request to Marketplace def httpBuilder = new HTTPBuilder("https://marketplace.atlassian.com") // Content access def xhtmlContent = ComponentLocator.getComponent(XhtmlContent) def writer = new StringWriter() def builder = new MarkupBuilder(writer) // Application Link check as per https://scriptrunner.adaptavist.com/latest/confluence/interacting-with-other-apps-via-applinks.html def handler = new ApplicationLinkResponseHandler() { @Override Map credentialsRequired(Response response) throws ResponseException { [:] } @Override Map handle(Response response) throws ResponseException { if (response.statusCode == 200) { new JsonSlurper().parseText(response.responseBodyAsString) as Map } else { [:] } } } def req = applicationLinkRequestFactory.createRequest(Request.MethodType.GET, "rest/plugins/latest/") def pluginListEndpoint = req.execute(handler) def plugins = pluginListEndpoint["plugins"] builder.table { tbody { tr { th { p("App Name") } th { p("Vendor") } th { p("Installed Version") } th { p("Status") } th { p("License Type") } th { p("Expiry Date") } th { p("Marketplace Version") } th { p("Description") } } plugins.each { plugin -> if (plugin["userInstalled"] && !plugin["applicationPluginType"]) { def encodedKey = URLEncoder.encode(plugin["key"].toString(), 'UTF-8') def licenseRequest = applicationLinkRequestFactory.createRequest(Request.MethodType.GET, "rest/plugins/1.0/${encodedKey}-key/license") def licenseData = licenseRequest.execute(handler) def summaryRequest = applicationLinkRequestFactory.createRequest(Request.MethodType.GET, "rest/plugins/1.0/${encodedKey}-key/summary") def summaryData = summaryRequest.execute(handler) def addonsData try { addonsData = httpBuilder.get( path: "/rest/latest/addons/${encodedKey}" ) as JSONObject } catch (HttpResponseException ex) { addonsData = new JSONObject("{}") } def latestVersionData try { latestVersionData = httpBuilder.get( path: "/rest/latest/addons/${encodedKey}/versions/latest" ) as JSONObject } catch (HttpResponseException ex) { latestVersionData = new JSONObject("{}") } tr { td { p(plugin["name"]) } td { p(plugin["vendor"]["name"]) } td { p(plugin["version"]) } if (summaryData["enabled"].toString().contains("true")) { td { p { "ac:emoticon"("ac:name": "tick") } } } else { td { p("") } } td { p(licenseData["licenseType"]) } td { p(licenseData["expiryDateString"]) } if (latestVersionData.has("name")) { td { p(latestVersionData["name"]) } } else { td { p("") } } if (addonsData.has("summary")) { td { p(addonsData["summary"]) } } else { td { p("") } } } } } } } xhtmlContent.convertStorageToView(writer.toString(), context)
Discovered an issue? Report it here

Suggested for you