-
Notifications
You must be signed in to change notification settings - Fork 1
/
utils.js
141 lines (130 loc) · 4.06 KB
/
utils.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/**
* Project Oracle
* TIE-13106 Project Work on Pervasive Systems
* Module for common utils
*/
var https = require('https');
var querystring = require('querystring');
module.exports = (function() {
var utils = {};
utils.pivotalHost = "www.pivotaltracker.com";
utils.pivotalServicePath = "/services/v5";
utils.flowdockHost = "api.flowdock.com";
utils.flowdockRevokePath = "/oauth/revoke";
utils.flowdockTokenPath = "/oauth/token";
/**
* Fetches JSON objects from given source
* @param hostname
* @param path
* @param headers
* @param callback (err, status, data)
*/
utils.fetchJSON = function(hostname, path, headers, callback) {
var opt = {hostname: hostname, port:443, path: path, agent: false};
opt.headers = headers != null ? headers : {};
opt.headers["Content-Type"] = "application/json";
https.get(opt,
function(res) {
var data = '';
res.on('data', function(chunk) {
data += chunk;
});
res.on('end', function() {
try {
var obj = JSON.parse(data);
return callback(null, res.statusCode, obj);
} catch (err) {
return callback(err, res.statusCode, data);
}
});
}).on('error', function(err) {
callback(err, null);
});
}
/**
* @param db
* @param authInfo
* @param user
* @param accountInfo
* @param hostname
* @param path
* @param headers
* @param callback (err, statuscode, data)
*/
utils.OAuthRequest = function(db, authInfo, user, accountInfo, hostname, path, headers, callback) {
var originalHeaders = {};
for (prop in headers) {
originalHeaders[prop] = headers[prop];
}
doRequest(true);
function doRequest(allowRetry) {
headers = headers || {};
headers['Authorization'] = 'Bearer ' + accountInfo.access_token;
utils.fetchJSON(hostname, path, headers, function(err, statusCode, receivedData) {
if (statusCode == 401 || statusCode == 403) {
if (!allowRetry) return callback(new Error('Fetching new access token failed'));
var body = {"refresh_token": accountInfo.refresh_token, "client_id": authInfo.clientId, "client_secret": authInfo.clientSecret, "grant_type": "refresh_token"};
var tokenPath = null;
if (accountInfo.account_name == db.utils.projects.appIds.FLOWDOCK) {
tokenPath = utils.flowdockTokenPath;
}
if (tokenPath) {
utils.post(hostname, tokenPath, headers, body, function(err, statusCode, data) {
if (err) return callback(err);
try {
var obj = JSON.parse(data);
// Update access token and try again
accountInfo.access_token = obj.access_token;
db.utils.updateAccessToken(accountInfo.account, user, obj.access_token, function(err) {
if (err) return callback(err);
headers = originalHeaders;
headers['Authorization'] = 'Bearer ' + obj.access_token;
utils.fetchJSON(hostname, path, headers, function(err, statusCode, receivedData) {
callback(err, statusCode, receivedData);
});
});
} catch (err) {
return callback(err, statusCode, data);
}
});
} else {
callback(new Error('Invalid access token'));
}
} else if (!err) {
callback(null, statusCode, receivedData);
} else {
return callback(err);
}
});
}
}
/**
* @param hostname
* @param path
* @param headers
* @param dataToSend Data to be sent
* @param callback (err, status, data)
*/
utils.post = function(hostname, path, headers, dataToSend, callback) {
var opt = {hostname: hostname, port:443, path: path, method: 'POST', agent: false};
var formattedData = querystring.stringify(dataToSend);
opt.headers = headers != null ? headers : {};
opt.headers["Content-Type"] = "application/x-www-form-urlencoded";
opt.headers["Content-Length"] = formattedData.length;
var req = https.request(opt,
function(res) {
var data = '';
res.on('data', function(chunk) {
data += chunk;
});
res.on('end', function() {
callback(null, res.statusCode, data);
});
}).on('error', function(err) {
callback(err, null);
});
req.write(formattedData);
req.end();
}
return utils;
})();