REST API calls from atlassian-connect-express /installed

867 views
Skip to first unread message

luka koczorowski

unread,
May 17, 2016, 7:35:44 PM5/17/16
to Atlassian Connect Dev
Hey everyone,

I'm trying to make some REST API calls (create custom issue types) when my plugin is installed. Currently I'm adding my code inside

self.app.post( basePath + '/installed', verifyInstallation(self), function (req, res) { ... }

in atlassian-connect-express/lib/index.js

I'm using the below to create my httpClient. It works only if the plugin is already installed and I'm reinstalling. If it's a first-time install httpClient is null and fails to make the API calls.

var httpClient = self.httpClient(req);

Is there a better way to do this? I feel like I shouldn't be mucking around in lib/index.js

Thanks!


Daniel Wester

unread,
May 17, 2016, 8:47:43 PM5/17/16
to Atlassian Connect Dev
You don't have to go that far. There's a host settings saved event so you can do something like:
addon.on('host_settings_saved', function( k, data1)

Take a look at https://bitbucket.org/atlassian/atlassian-connect-express/src/e2f045db8d13c6cae9242de089b01de0ed540638/lib/index.js?at=master&fileviewer=file-view-default#index.js-138

Seb Ruiz

unread,
May 17, 2016, 9:09:03 PM5/17/16
to atlassian-...@googlegroups.com
Luka,

You can't make a request back to the host during installation as the installation hasn't completed yet.

What are you trying to achieve?

Cheers,
Seb

--
You received this message because you are subscribed to the Google Groups "Atlassian Connect Dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to atlassian-connec...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Seb Ruiz
Atlassian

luka koczorowski

unread,
May 22, 2016, 10:11:25 AM5/22/16
to Atlassian Connect Dev
What I'm trying to do is add two issue types upon install. What I've done is

In app.js
var listeners = require('./listeners')
listeners(app, addon);

Then in listeners/index.js

It's not ideal because if any of my API calls fail it's too late, the addon is installed and the user won't know. Initially I had
self.settings.set('clientInfo', settings, settings.clientKey).then(function (data) {
    var httpClient = hostRequest(self, req.body, req.body.clientKey);

     // API calls here 

    self.logger.info("Saved tenant details for " + settings.clientKey + " to database\n" + util.inspect(data));
    self.emit('host_settings_saved', settings.clientKey, data);
    res.status(204).end();

And it worked too but was total hack. 

Dave Haden

unread,
May 22, 2016, 10:19:06 AM5/22/16
to Atlassian Connect Dev
Hey Luka,

On a authenticated request, the middleware will inject the httpClient into the req object.
However, the first install is not authenticated with JWT since we are only seeing a shared secret from this Atlassian host for the first time.

If you were to listen for an enabled webhook, then this code would work and you would not have to use the hack.

When you mention, `API calls here`, do you mean to the host which has just installed your add-on?
Does that work for first installs? (ie, not re-installing, or an uninstall before re-installing)

Thanks,
Dave

James Hazelwood

unread,
May 24, 2016, 10:16:26 PM5/24/16
to Atlassian Connect Dev
Just to build on Dave's comments, the 'failing an install due to a failed REST request' flow you are after doesn't fit with how the connect installation flow works, I'm afraid. Have you considered an approach like the following?
It's not exactly what you were originally after, but it does have the benefit of also handling the case where a user deletes your custom issue types.

Hope that helps,
James

luka koczorowski

unread,
May 26, 2016, 11:40:38 AM5/26/16
to Atlassian Connect Dev
Thanks Dave and James, you guys have definitely got me on the right path :)

I was thinking something along the lines of a health-check type page but must have overlooked  postInstallPage, I was going to add it to the config page instead but this sounds much better. 

Again appreciate all the feedback, you guys are great!




luka koczorowski

unread,
Jun 9, 2016, 5:09:26 PM6/9/16
to Atlassian Connect Dev
 
Hey team, 

I'm experiencing some odd behavior recently. In my event listener...
module.exports = function (app, addon) {
addon.on('host_settings_saved', function (clientKey, settings) {
var httpClient = addon.httpClient(settings);

The first thing I do is try to create two issue types with the following:
createIssueType(httpClient, settings, 'st', stIssueTypeData).then(function (stRes){
console.log("st: " + stRes.id);
createIssueType(httpClient, settings, 'us', usIssueTypeData).then(function (usRes){
console.log("us: " + usRes.id);

However, the first call to createIssueType always fails with:
 {"errorMessages":["You are not authenticated. Authentication required to perform this operation."],"errors":{}}

The second call to createIssueType passes every time. I've been forced to call createIssueType three times, twice for 'st' issue type and then once for 'us' issue type to ensure success for both. 

createIssueType is:
var createIssueType = function (httpClient, settings, key, data){
   var promise = new RSVP.Promise(function (resolve, reject) {
       httpClient.post({   url : '/rest/api/2/issuetype', 
                       headers: {
                           'X-Atlassian-Token': 'nocheck',
                           'Content-Type': 'application/json',
                           'Accept': 'application/json'
                       },
                       json: data 
                   },
           function(err, res, body) {
           if (err) {
               console.log("rejecting promise");
               reject(err);
           }
           else {
               console.log("resovling promise, sending: " + JSON.stringify(body));
               resolve(body);
           }
       });
   });
   return promise;
};

Any ideas? I tried rearranging them, using different data, using only callbacks and no promises, it's always the same behavior, the first one fails and the rest work. I even tried adding a 5 second delay before making the first API call inside the event listener, none of which have been successful. 

Raimonds Simanovskis

unread,
Jun 10, 2016, 4:49:12 AM6/10/16
to Atlassian Connect Dev
Hi

As I understand one of the recent changes is that during the install callback the add-on is not yet registered in JIRA as installed (it will only be registered after receiving successful response from the callback) and therefore you cannot make JWT signed REST API requests back to JIRA. In addition, currently, there is a very short 5 seconds timeout that JIRA waits for the installed callback response. Therefore, you should respond quickly to installed callback and should not make REST API requests which may take longer time.

I recommend moving creation of issue types to "enabled" callback which will be executed after the "installed" callback. During the "enabled" callback you can successfully use JWT signed REST API requests and JIRA will not give any timeout errors if the "enabled" callback takes longer time to execute.

Kind regards,
Raimonds

luka koczorowski

unread,
Jun 14, 2016, 10:28:14 AM6/14/16
to Atlassian Connect Dev
Just to close the loop on this one, moving the code to eventType: enabled worked.  in /state I simply put

if (req.body.eventType = "enabled") {
   addon.emit('registered_with_jira', req.body.clientKey, req.body);
}


santhosh....@solitontech.com

unread,
Jan 20, 2017, 8:37:21 AM1/20/17
to Atlassian Connect Dev
Hi,

Normally we use the AP object in all.js file to get the data from the JIRA page.
Is there any other way to get the data from the JIRA page from the add on's server?

James Hazelwood

unread,
Jan 23, 2017, 1:40:02 AM1/23/17
to Atlassian Connect Dev
Hi santhosh,

If you're talking about accessing data via the REST resources, one is with AP.request on the page, as you mention. The other is to make JWT-signed requests. If you're using atlassian-connect-express, this can be done via the addon.httpClient object, but please check out the docs for more information. If you have more questions, please feel free to start a new thread.

Regards,
James
Reply all
Reply to author
Forward
0 new messages