You can now vote for scripts to help people know if they're useful or not. Login or create an account to vote!

1

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)
  • ScriptRunner for Confluence ScriptRunner for Confluence (6.21.0)
    
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