2020-06-06 00:03:37 +02:00
|
|
|
"use strict";
|
2016-03-28 22:33:20 +02:00
|
|
|
|
2020-06-06 00:03:37 +02:00
|
|
|
const cookies = require("js-cookie");
|
|
|
|
const request = require("superagent");
|
|
|
|
const events = require("./events.js");
|
|
|
|
const progress = require("./util/progress.js");
|
|
|
|
const uri = require("./util/uri.js");
|
2016-03-28 22:33:20 +02:00
|
|
|
|
2017-01-08 23:52:20 +01:00
|
|
|
let fileTokens = {};
|
2018-06-25 16:47:20 +02:00
|
|
|
let remoteConfig = null;
|
2017-01-08 23:52:20 +01:00
|
|
|
|
2016-06-14 10:31:48 +02:00
|
|
|
class Api extends events.EventTarget {
|
2016-03-30 20:45:37 +02:00
|
|
|
constructor() {
|
2016-06-14 10:31:48 +02:00
|
|
|
super();
|
2016-03-30 22:05:57 +02:00
|
|
|
this.user = null;
|
2016-03-30 20:45:37 +02:00
|
|
|
this.userName = null;
|
|
|
|
this.userPassword = null;
|
2018-02-25 11:44:02 +01:00
|
|
|
this.token = null;
|
2016-04-11 18:45:58 +02:00
|
|
|
this.cache = {};
|
2016-05-08 16:59:25 +02:00
|
|
|
this.allRanks = [
|
2020-06-06 00:03:37 +02:00
|
|
|
"anonymous",
|
|
|
|
"restricted",
|
|
|
|
"regular",
|
|
|
|
"power",
|
|
|
|
"moderator",
|
|
|
|
"administrator",
|
|
|
|
"nobody",
|
2016-05-08 16:59:25 +02:00
|
|
|
];
|
2016-06-19 19:16:40 +02:00
|
|
|
this.rankNames = new Map([
|
2020-06-06 00:03:37 +02:00
|
|
|
["anonymous", "Anonymous"],
|
|
|
|
["restricted", "Restricted user"],
|
|
|
|
["regular", "Regular user"],
|
|
|
|
["power", "Power user"],
|
|
|
|
["moderator", "Moderator"],
|
|
|
|
["administrator", "Administrator"],
|
|
|
|
["nobody", "Nobody"],
|
2016-06-19 19:16:40 +02:00
|
|
|
]);
|
2016-03-30 20:45:37 +02:00
|
|
|
}
|
|
|
|
|
2016-05-22 11:16:25 +02:00
|
|
|
get(url, options) {
|
2016-04-11 18:45:58 +02:00
|
|
|
if (url in this.cache) {
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
resolve(this.cache[url]);
|
|
|
|
});
|
|
|
|
}
|
2020-06-06 00:03:37 +02:00
|
|
|
return this._wrappedRequest(url, request.get, {}, {}, options).then(
|
|
|
|
(response) => {
|
2016-05-22 11:16:25 +02:00
|
|
|
this.cache[url] = response;
|
|
|
|
return Promise.resolve(response);
|
2020-06-06 00:03:37 +02:00
|
|
|
}
|
|
|
|
);
|
2016-03-28 22:33:20 +02:00
|
|
|
}
|
|
|
|
|
2016-05-22 11:16:25 +02:00
|
|
|
post(url, data, files, options) {
|
2016-04-11 18:45:58 +02:00
|
|
|
this.cache = {};
|
2017-01-07 14:28:36 +01:00
|
|
|
return this._wrappedRequest(url, request.post, data, files, options);
|
2016-03-28 22:33:20 +02:00
|
|
|
}
|
|
|
|
|
2016-05-22 11:16:25 +02:00
|
|
|
put(url, data, files, options) {
|
2016-04-11 18:45:58 +02:00
|
|
|
this.cache = {};
|
2017-01-07 14:28:36 +01:00
|
|
|
return this._wrappedRequest(url, request.put, data, files, options);
|
2016-04-07 22:54:45 +02:00
|
|
|
}
|
|
|
|
|
2016-08-06 22:44:04 +02:00
|
|
|
delete(url, data, options) {
|
2016-04-11 18:45:58 +02:00
|
|
|
this.cache = {};
|
2017-01-07 14:28:36 +01:00
|
|
|
return this._wrappedRequest(url, request.delete, data, {}, options);
|
2016-03-28 22:33:20 +02:00
|
|
|
}
|
|
|
|
|
2018-06-25 16:47:20 +02:00
|
|
|
fetchConfig() {
|
|
|
|
if (remoteConfig === null) {
|
2020-06-06 00:03:37 +02:00
|
|
|
return this.get(uri.formatApiLink("info")).then((response) => {
|
|
|
|
remoteConfig = response.config;
|
|
|
|
});
|
2018-06-25 16:47:20 +02:00
|
|
|
} else {
|
|
|
|
return Promise.resolve();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
getName() {
|
|
|
|
return remoteConfig.name;
|
|
|
|
}
|
|
|
|
|
|
|
|
getTagNameRegex() {
|
|
|
|
return remoteConfig.tagNameRegex;
|
|
|
|
}
|
|
|
|
|
2020-05-04 04:53:28 +02:00
|
|
|
getPoolNameRegex() {
|
|
|
|
return remoteConfig.poolNameRegex;
|
|
|
|
}
|
|
|
|
|
2018-06-25 16:47:20 +02:00
|
|
|
getPasswordRegex() {
|
|
|
|
return remoteConfig.passwordRegex;
|
|
|
|
}
|
|
|
|
|
|
|
|
getUserNameRegex() {
|
|
|
|
return remoteConfig.userNameRegex;
|
|
|
|
}
|
|
|
|
|
|
|
|
getContactEmail() {
|
|
|
|
return remoteConfig.contactEmail;
|
|
|
|
}
|
|
|
|
|
|
|
|
canSendMails() {
|
|
|
|
return !!remoteConfig.canSendMails;
|
|
|
|
}
|
|
|
|
|
|
|
|
safetyEnabled() {
|
|
|
|
return !!remoteConfig.enableSafety;
|
|
|
|
}
|
|
|
|
|
2016-03-30 22:05:57 +02:00
|
|
|
hasPrivilege(lookup) {
|
|
|
|
let minViableRank = null;
|
2018-06-25 16:47:20 +02:00
|
|
|
for (let p of Object.keys(remoteConfig.privileges)) {
|
|
|
|
if (!p.startsWith(lookup)) {
|
2016-03-30 22:05:57 +02:00
|
|
|
continue;
|
|
|
|
}
|
2018-06-25 16:47:20 +02:00
|
|
|
const rankIndex = this.allRanks.indexOf(
|
2020-06-06 00:03:37 +02:00
|
|
|
remoteConfig.privileges[p]
|
|
|
|
);
|
2016-03-30 22:05:57 +02:00
|
|
|
if (minViableRank === null || rankIndex < minViableRank) {
|
|
|
|
minViableRank = rankIndex;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (minViableRank === null) {
|
2016-06-11 09:30:22 +02:00
|
|
|
throw `Bad privilege name: ${lookup}`;
|
2016-03-30 22:05:57 +02:00
|
|
|
}
|
2020-06-06 00:03:37 +02:00
|
|
|
let myRank =
|
|
|
|
this.user !== null ? this.allRanks.indexOf(this.user.rank) : 0;
|
2016-03-30 22:05:57 +02:00
|
|
|
return myRank >= minViableRank;
|
2016-03-30 20:45:37 +02:00
|
|
|
}
|
|
|
|
|
2016-04-08 10:01:32 +02:00
|
|
|
loginFromCookies() {
|
2020-06-06 00:03:37 +02:00
|
|
|
const auth = cookies.getJSON("auth");
|
|
|
|
return auth && auth.user && auth.token
|
|
|
|
? this.loginWithToken(auth.user, auth.token, true)
|
|
|
|
: Promise.resolve();
|
2016-04-08 10:01:32 +02:00
|
|
|
}
|
|
|
|
|
2018-02-25 11:44:02 +01:00
|
|
|
loginWithToken(userName, token, doRemember) {
|
2016-06-19 21:37:44 +02:00
|
|
|
this.cache = {};
|
2016-03-30 21:01:18 +02:00
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
this.userName = userName;
|
2018-02-25 11:44:02 +01:00
|
|
|
this.token = token;
|
2020-06-06 00:03:37 +02:00
|
|
|
this.get("/user/" + userName + "?bump-login=true").then(
|
|
|
|
(response) => {
|
2016-04-08 10:01:32 +02:00
|
|
|
const options = {};
|
|
|
|
if (doRemember) {
|
|
|
|
options.expires = 365;
|
|
|
|
}
|
|
|
|
cookies.set(
|
2020-06-06 00:03:37 +02:00
|
|
|
"auth",
|
|
|
|
{ user: userName, token: token },
|
|
|
|
options
|
|
|
|
);
|
2018-02-25 11:44:02 +01:00
|
|
|
this.user = response;
|
|
|
|
resolve();
|
2020-06-06 00:03:37 +02:00
|
|
|
this.dispatchEvent(new CustomEvent("login"));
|
|
|
|
},
|
|
|
|
(error) => {
|
2018-02-25 11:44:02 +01:00
|
|
|
reject(error);
|
|
|
|
this.logout();
|
2020-06-06 00:03:37 +02:00
|
|
|
}
|
|
|
|
);
|
2018-02-25 11:44:02 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
createToken(userName, options) {
|
|
|
|
let userTokenRequest = {
|
|
|
|
enabled: true,
|
2020-06-06 00:03:37 +02:00
|
|
|
note: "Web Login Token",
|
2018-02-25 11:44:02 +01:00
|
|
|
};
|
2020-06-06 00:03:37 +02:00
|
|
|
if (typeof options.expires !== "undefined") {
|
|
|
|
userTokenRequest.expirationTime = new Date()
|
|
|
|
.addDays(options.expires)
|
|
|
|
.toISOString();
|
2018-02-25 11:44:02 +01:00
|
|
|
}
|
|
|
|
return new Promise((resolve, reject) => {
|
2020-06-06 00:03:37 +02:00
|
|
|
this.post("/user-token/" + userName, userTokenRequest).then(
|
|
|
|
(response) => {
|
2018-02-25 11:44:02 +01:00
|
|
|
cookies.set(
|
2020-06-06 00:03:37 +02:00
|
|
|
"auth",
|
|
|
|
{ user: userName, token: response.token },
|
|
|
|
options
|
|
|
|
);
|
2018-02-25 11:44:02 +01:00
|
|
|
this.userName = userName;
|
|
|
|
this.token = response.token;
|
|
|
|
this.userPassword = null;
|
2020-06-06 00:03:37 +02:00
|
|
|
},
|
|
|
|
(error) => {
|
2018-02-25 11:44:02 +01:00
|
|
|
reject(error);
|
2020-06-06 00:03:37 +02:00
|
|
|
}
|
|
|
|
);
|
2018-02-25 11:44:02 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
deleteToken(userName, userToken) {
|
|
|
|
return new Promise((resolve, reject) => {
|
2020-06-06 00:03:37 +02:00
|
|
|
this.delete("/user-token/" + userName + "/" + userToken, {}).then(
|
|
|
|
(response) => {
|
2018-02-25 11:44:02 +01:00
|
|
|
const options = {};
|
|
|
|
cookies.set(
|
2020-06-06 00:03:37 +02:00
|
|
|
"auth",
|
|
|
|
{ user: userName, token: null },
|
|
|
|
options
|
|
|
|
);
|
2018-02-25 11:44:02 +01:00
|
|
|
resolve();
|
2020-06-06 00:03:37 +02:00
|
|
|
},
|
|
|
|
(error) => {
|
2018-02-25 11:44:02 +01:00
|
|
|
reject(error);
|
2020-06-06 00:03:37 +02:00
|
|
|
}
|
|
|
|
);
|
2018-02-25 11:44:02 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
login(userName, userPassword, doRemember) {
|
|
|
|
this.cache = {};
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
this.userName = userName;
|
|
|
|
this.userPassword = userPassword;
|
2020-06-06 00:03:37 +02:00
|
|
|
this.get("/user/" + userName + "?bump-login=true").then(
|
|
|
|
(response) => {
|
2018-02-25 11:44:02 +01:00
|
|
|
const options = {};
|
|
|
|
if (doRemember) {
|
|
|
|
options.expires = 365;
|
|
|
|
}
|
|
|
|
this.createToken(this.userName, options);
|
2016-05-30 22:20:42 +02:00
|
|
|
this.user = response;
|
2016-03-30 22:05:57 +02:00
|
|
|
resolve();
|
2020-06-06 00:03:37 +02:00
|
|
|
this.dispatchEvent(new CustomEvent("login"));
|
|
|
|
},
|
|
|
|
(error) => {
|
2017-01-08 02:12:38 +01:00
|
|
|
reject(error);
|
2016-03-30 21:01:18 +02:00
|
|
|
this.logout();
|
2020-06-06 00:03:37 +02:00
|
|
|
}
|
|
|
|
);
|
2016-03-30 21:01:18 +02:00
|
|
|
});
|
2016-03-30 20:45:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
logout() {
|
2018-02-25 11:44:02 +01:00
|
|
|
let self = this;
|
2020-06-06 00:03:37 +02:00
|
|
|
this.deleteToken(this.userName, this.token).then(
|
|
|
|
(response) => {
|
2018-02-25 11:44:02 +01:00
|
|
|
self._logout();
|
2020-06-06 00:03:37 +02:00
|
|
|
},
|
|
|
|
(error) => {
|
2018-02-25 11:44:02 +01:00
|
|
|
self._logout();
|
2020-06-06 00:03:37 +02:00
|
|
|
}
|
|
|
|
);
|
2018-02-25 11:44:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
_logout() {
|
2016-04-01 13:09:07 +02:00
|
|
|
this.user = null;
|
2016-03-30 20:45:37 +02:00
|
|
|
this.userName = null;
|
|
|
|
this.userPassword = null;
|
2018-02-25 11:44:02 +01:00
|
|
|
this.token = null;
|
2020-06-06 00:03:37 +02:00
|
|
|
this.dispatchEvent(new CustomEvent("logout"));
|
2016-03-30 20:45:37 +02:00
|
|
|
}
|
|
|
|
|
2016-04-09 19:53:53 +02:00
|
|
|
forget() {
|
2020-06-06 00:03:37 +02:00
|
|
|
cookies.remove("auth");
|
2016-04-09 19:53:53 +02:00
|
|
|
}
|
|
|
|
|
2016-04-16 15:07:33 +02:00
|
|
|
isLoggedIn(user) {
|
|
|
|
if (user) {
|
2020-06-06 00:03:37 +02:00
|
|
|
return (
|
|
|
|
this.userName !== null &&
|
|
|
|
this.userName.toLowerCase() === user.name.toLowerCase()
|
|
|
|
);
|
2016-04-16 15:07:33 +02:00
|
|
|
} else {
|
|
|
|
return this.userName !== null;
|
|
|
|
}
|
2016-03-30 20:45:37 +02:00
|
|
|
}
|
|
|
|
|
2018-02-25 11:44:02 +01:00
|
|
|
isCurrentAuthToken(userToken) {
|
|
|
|
return userToken.token === this.token;
|
|
|
|
}
|
|
|
|
|
2016-05-20 21:35:12 +02:00
|
|
|
_getFullUrl(url) {
|
2020-06-06 00:03:37 +02:00
|
|
|
const fullUrl = ("api/" + url).replace(/([^:])\/+/g, "$1/");
|
2016-09-04 01:25:19 +02:00
|
|
|
const matches = fullUrl.match(/^([^?]*)\??(.*)$/);
|
|
|
|
const baseUrl = matches[1];
|
|
|
|
const request = matches[2];
|
|
|
|
return [baseUrl, request];
|
2016-03-28 22:33:20 +02:00
|
|
|
}
|
2017-01-07 14:28:36 +01:00
|
|
|
|
2017-01-08 23:52:20 +01:00
|
|
|
_getFileId(file) {
|
|
|
|
if (file.constructor === String) {
|
|
|
|
return file;
|
|
|
|
}
|
|
|
|
return file.name + file.size;
|
|
|
|
}
|
|
|
|
|
2017-01-07 14:28:36 +01:00
|
|
|
_wrappedRequest(url, requestFactory, data, files, options) {
|
|
|
|
// transform the request: upload each file, then make the request use
|
|
|
|
// its tokens.
|
|
|
|
data = Object.assign({}, data);
|
|
|
|
let abortFunction = () => {};
|
2017-01-07 16:24:56 +01:00
|
|
|
let promise = Promise.resolve();
|
2017-01-07 14:28:36 +01:00
|
|
|
if (files) {
|
|
|
|
for (let key of Object.keys(files)) {
|
2017-01-08 23:52:20 +01:00
|
|
|
const file = files[key];
|
|
|
|
const fileId = this._getFileId(file);
|
|
|
|
if (fileTokens[fileId]) {
|
2020-06-06 00:03:37 +02:00
|
|
|
data[key + "Token"] = fileTokens[fileId];
|
2017-01-07 14:28:36 +01:00
|
|
|
} else {
|
|
|
|
promise = promise
|
|
|
|
.then(() => {
|
2017-01-07 16:24:56 +01:00
|
|
|
let uploadPromise = this._upload(file);
|
|
|
|
abortFunction = () => uploadPromise.abort();
|
|
|
|
return uploadPromise;
|
2017-01-07 14:28:36 +01:00
|
|
|
})
|
2020-06-06 00:03:37 +02:00
|
|
|
.then((token) => {
|
2017-01-07 14:28:36 +01:00
|
|
|
abortFunction = () => {};
|
2017-01-08 23:52:20 +01:00
|
|
|
fileTokens[fileId] = token;
|
2020-06-06 00:03:37 +02:00
|
|
|
data[key + "Token"] = token;
|
2017-01-07 14:28:36 +01:00
|
|
|
return Promise.resolve();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-06-06 00:03:37 +02:00
|
|
|
promise = promise
|
|
|
|
.then(() => {
|
2017-01-07 16:24:56 +01:00
|
|
|
let requestPromise = this._rawRequest(
|
2020-06-06 00:03:37 +02:00
|
|
|
url,
|
|
|
|
requestFactory,
|
|
|
|
data,
|
|
|
|
{},
|
|
|
|
options
|
|
|
|
);
|
2017-01-07 16:24:56 +01:00
|
|
|
abortFunction = () => requestPromise.abort();
|
|
|
|
return requestPromise;
|
2017-01-08 11:04:21 +01:00
|
|
|
})
|
2020-06-06 00:03:37 +02:00
|
|
|
.catch((error) => {
|
|
|
|
if (
|
|
|
|
error.response &&
|
|
|
|
error.response.name === "MissingOrExpiredRequiredFileError"
|
|
|
|
) {
|
2017-01-08 11:04:21 +01:00
|
|
|
for (let key of Object.keys(files)) {
|
2017-01-08 23:52:20 +01:00
|
|
|
const file = files[key];
|
|
|
|
const fileId = this._getFileId(file);
|
|
|
|
fileTokens[fileId] = null;
|
2017-01-08 11:04:21 +01:00
|
|
|
}
|
|
|
|
error.message =
|
2020-06-06 00:03:37 +02:00
|
|
|
"The uploaded file has expired; " +
|
|
|
|
"please resend the form to reupload.";
|
2017-01-08 11:04:21 +01:00
|
|
|
}
|
2017-01-07 16:24:56 +01:00
|
|
|
return Promise.reject(error);
|
|
|
|
});
|
2017-01-07 14:28:36 +01:00
|
|
|
promise.abort = () => abortFunction();
|
|
|
|
return promise;
|
|
|
|
}
|
|
|
|
|
|
|
|
_upload(file, options) {
|
|
|
|
let abortFunction = () => {};
|
|
|
|
let returnedPromise = new Promise((resolve, reject) => {
|
2017-01-07 16:24:56 +01:00
|
|
|
let uploadPromise = this._rawRequest(
|
2020-06-06 00:03:37 +02:00
|
|
|
"uploads",
|
|
|
|
request.post,
|
|
|
|
{},
|
|
|
|
{ content: file },
|
|
|
|
options
|
|
|
|
);
|
2017-01-07 16:24:56 +01:00
|
|
|
abortFunction = () => uploadPromise.abort();
|
2020-06-06 00:03:37 +02:00
|
|
|
return uploadPromise.then((response) => {
|
|
|
|
abortFunction = () => {};
|
|
|
|
return resolve(response.token);
|
|
|
|
}, reject);
|
2017-01-07 14:28:36 +01:00
|
|
|
});
|
|
|
|
returnedPromise.abort = () => abortFunction();
|
|
|
|
return returnedPromise;
|
|
|
|
}
|
|
|
|
|
|
|
|
_rawRequest(url, requestFactory, data, files, options) {
|
|
|
|
options = options || {};
|
|
|
|
data = Object.assign({}, data);
|
|
|
|
const [fullUrl, query] = this._getFullUrl(url);
|
|
|
|
|
2017-01-07 16:24:56 +01:00
|
|
|
let abortFunction = () => {};
|
|
|
|
let returnedPromise = new Promise((resolve, reject) => {
|
2017-01-07 14:28:36 +01:00
|
|
|
let req = requestFactory(fullUrl);
|
|
|
|
|
2020-06-06 00:03:37 +02:00
|
|
|
req.set("Accept", "application/json");
|
2017-01-07 14:28:36 +01:00
|
|
|
|
|
|
|
if (query) {
|
|
|
|
req.query(query);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (files) {
|
|
|
|
for (let key of Object.keys(files)) {
|
|
|
|
const value = files[key];
|
|
|
|
if (value.constructor === String) {
|
2020-06-06 00:03:37 +02:00
|
|
|
data[key + "Url"] = value;
|
2017-01-07 14:28:36 +01:00
|
|
|
} else {
|
|
|
|
req.attach(key, value || new Blob());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (data) {
|
|
|
|
if (files && Object.keys(files).length) {
|
2020-06-06 00:03:37 +02:00
|
|
|
req.attach("metadata", new Blob([JSON.stringify(data)]));
|
2017-01-07 14:28:36 +01:00
|
|
|
} else {
|
2020-06-06 00:03:37 +02:00
|
|
|
req.set("Content-Type", "application/json");
|
2017-01-07 14:28:36 +01:00
|
|
|
req.send(data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
2018-02-25 11:44:02 +01:00
|
|
|
if (this.userName && this.token) {
|
|
|
|
req.auth = null;
|
2020-06-04 20:09:35 +02:00
|
|
|
// eslint-disable-next-line no-undef
|
2020-06-06 00:03:37 +02:00
|
|
|
req.set(
|
|
|
|
"Authorization",
|
|
|
|
"Token " +
|
|
|
|
new Buffer(
|
|
|
|
this.userName + ":" + this.token
|
|
|
|
).toString("base64")
|
|
|
|
);
|
2018-02-25 11:44:02 +01:00
|
|
|
} else if (this.userName && this.userPassword) {
|
2017-01-07 14:28:36 +01:00
|
|
|
req.auth(
|
|
|
|
this.userName,
|
2020-06-06 00:03:37 +02:00
|
|
|
encodeURIComponent(this.userPassword).replace(
|
|
|
|
/%([0-9A-F]{2})/g,
|
|
|
|
(match, p1) => {
|
|
|
|
return String.fromCharCode("0x" + p1);
|
|
|
|
}
|
|
|
|
)
|
|
|
|
);
|
2017-01-07 14:28:36 +01:00
|
|
|
}
|
|
|
|
} catch (e) {
|
2017-01-08 02:12:38 +01:00
|
|
|
reject(
|
2020-06-06 00:03:37 +02:00
|
|
|
new Error("Authentication error (malformed credentials)")
|
|
|
|
);
|
2017-01-07 14:28:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!options.noProgress) {
|
2017-01-08 22:24:46 +01:00
|
|
|
progress.start();
|
2017-01-07 14:28:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
abortFunction = () => {
|
2020-06-06 00:03:37 +02:00
|
|
|
req.abort(); // does *NOT* call the callback passed in .end()
|
2017-01-08 22:24:46 +01:00
|
|
|
progress.done();
|
2017-01-08 02:12:38 +01:00
|
|
|
reject(
|
2020-06-06 00:03:37 +02:00
|
|
|
new Error("The request was aborted due to user cancel.")
|
|
|
|
);
|
2017-01-07 14:28:36 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
req.end((error, response) => {
|
2017-01-08 22:24:46 +01:00
|
|
|
progress.done();
|
2017-01-07 16:24:56 +01:00
|
|
|
abortFunction = () => {};
|
2017-01-07 14:28:36 +01:00
|
|
|
if (error) {
|
2017-01-08 02:12:38 +01:00
|
|
|
if (response && response.body) {
|
|
|
|
error = new Error(
|
2020-06-06 00:03:37 +02:00
|
|
|
response.body.description || "Unknown error"
|
|
|
|
);
|
2017-01-08 02:12:38 +01:00
|
|
|
error.response = response.body;
|
|
|
|
}
|
|
|
|
reject(error);
|
2017-01-07 14:28:36 +01:00
|
|
|
} else {
|
|
|
|
resolve(response.body);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
2017-01-07 16:24:56 +01:00
|
|
|
returnedPromise.abort = () => abortFunction();
|
|
|
|
return returnedPromise;
|
2017-01-07 14:28:36 +01:00
|
|
|
}
|
2016-03-28 22:33:20 +02:00
|
|
|
}
|
|
|
|
|
2016-04-01 00:20:34 +02:00
|
|
|
module.exports = new Api();
|