Skip to main content
Example scripts
arrow icon
To homepage
Confluence
Data centre icon
Data Center

Confluence Macro to Show User Installed Jira Apps

Features
Macros
Created 1 year ago, Updated 1 month(s) ago
App in script
ScriptRunner For Confluence
ScriptRunner For Confluence
by Adaptavist
Compatibility
compatibility bullet
Confluence (7.15 - 8.6)
compatibility bullet
ScriptRunner For Confluence (7.10.0)
Language |
groovy
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<Map>() {
    @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)
Having an issue with this script?
Report it here