api.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694
  1. const $ = require('jquery');
  2. const _ = require('underscore');
  3. const Tokens = require('./tokens');
  4. /**
  5. * @param {String} message
  6. * @param {*} debug
  7. * @param {Number} code
  8. * @constructor
  9. */
  10. const ApiError = function (message, debug, code) {
  11. let temp = Error.call(this, message);
  12. temp.name = this.name = 'ApiError';
  13. this.stack = temp.stack;
  14. this.message = temp.message;
  15. this.debug = debug;
  16. this.code = code;
  17. };
  18. ApiError.prototype = Object.create(Error.prototype, {
  19. constructor: {
  20. value: ApiError,
  21. writable: true,
  22. configurable: true
  23. }
  24. });
  25. /**
  26. *
  27. * @param {String} verb
  28. * @param {String} path
  29. * @param {Object} [data]
  30. * @param {Object} [options]
  31. * @returns {Promise}
  32. */
  33. function fetch(verb, path, data, options) {
  34. options = options || {};
  35. return new Promise(function (resolve, reject) {
  36. let api_url = '/api/';
  37. let url = api_url + path;
  38. let token = Tokens.getTopToken();
  39. if ((typeof options.contentType === 'undefined' || options.contentType.match(/json/im)) && typeof data === 'object') {
  40. data = JSON.stringify(data);
  41. }
  42. $.ajax({
  43. url: url,
  44. data: typeof data === 'object' ? JSON.stringify(data) : data,
  45. type: verb,
  46. dataType: 'json',
  47. contentType: options.contentType || 'application/json; charset=UTF-8',
  48. processData: options.processData || true,
  49. crossDomain: true,
  50. timeout: options.timeout ? options.timeout : 180000,
  51. xhrFields: {
  52. withCredentials: true
  53. },
  54. beforeSend: function (xhr) {
  55. xhr.setRequestHeader('Authorization', 'Bearer ' + (token ? token.t : null));
  56. },
  57. success: function (data, textStatus, response) {
  58. let total = response.getResponseHeader('X-Dataset-Total');
  59. if (total !== null) {
  60. resolve({
  61. data: data,
  62. pagination: {
  63. total: parseInt(total, 10),
  64. offset: parseInt(response.getResponseHeader('X-Dataset-Offset'), 10),
  65. limit: parseInt(response.getResponseHeader('X-Dataset-Limit'), 10)
  66. }
  67. });
  68. } else {
  69. resolve(response);
  70. }
  71. },
  72. error: function (xhr, status, error_thrown) {
  73. let code = 400;
  74. if (typeof xhr.responseJSON !== 'undefined' && typeof xhr.responseJSON.error !== 'undefined' && typeof xhr.responseJSON.error.message !== 'undefined') {
  75. error_thrown = xhr.responseJSON.error.message;
  76. code = xhr.responseJSON.error.code || 500;
  77. }
  78. reject(new ApiError(error_thrown, xhr.responseText, code));
  79. }
  80. });
  81. });
  82. }
  83. /**
  84. *
  85. * @param {Array} expand
  86. * @returns {String}
  87. */
  88. function makeExpansionString(expand) {
  89. let items = [];
  90. _.forEach(expand, function (exp) {
  91. items.push(encodeURIComponent(exp));
  92. });
  93. return items.join(',');
  94. }
  95. /**
  96. * @param {String} path
  97. * @param {Array} [expand]
  98. * @param {String} [query]
  99. * @returns {Promise}
  100. */
  101. function getAllObjects(path, expand, query) {
  102. let params = [];
  103. if (typeof expand === 'object' && expand !== null && expand.length) {
  104. params.push('expand=' + makeExpansionString(expand));
  105. }
  106. if (typeof query === 'string') {
  107. params.push('query=' + query);
  108. }
  109. return fetch('get', path + (params.length ? '?' + params.join('&') : ''));
  110. }
  111. function FileUpload(path, fd) {
  112. return new Promise((resolve, reject) => {
  113. let xhr = new XMLHttpRequest();
  114. let token = Tokens.getTopToken();
  115. xhr.open('POST', '/api/' + path);
  116. xhr.overrideMimeType('text/plain');
  117. xhr.setRequestHeader('Authorization', 'Bearer ' + (token ? token.t : null));
  118. xhr.send(fd);
  119. xhr.onreadystatechange = function () {
  120. if (this.readyState === XMLHttpRequest.DONE) {
  121. if (xhr.status !== 200 && xhr.status !== 201) {
  122. try {
  123. reject(new Error('Upload failed: ' + JSON.parse(xhr.responseText).error.message));
  124. } catch (err) {
  125. reject(new Error('Upload failed: ' + xhr.status));
  126. }
  127. } else {
  128. resolve(xhr.responseText);
  129. }
  130. }
  131. };
  132. });
  133. }
  134. module.exports = {
  135. status: function () {
  136. return fetch('get', '');
  137. },
  138. Tokens: {
  139. /**
  140. * @param {String} identity
  141. * @param {String} secret
  142. * @param {Boolean} [wipe] Will wipe the stack before adding to it again if login was successful
  143. * @returns {Promise}
  144. */
  145. login: function (identity, secret, wipe) {
  146. return fetch('post', 'tokens', {identity: identity, secret: secret})
  147. .then(response => {
  148. if (response.token) {
  149. if (wipe) {
  150. Tokens.clearTokens();
  151. }
  152. // Set storage token
  153. Tokens.addToken(response.token);
  154. return response.token;
  155. } else {
  156. Tokens.clearTokens();
  157. throw(new Error('No token returned'));
  158. }
  159. });
  160. },
  161. /**
  162. * @returns {Promise}
  163. */
  164. refresh: function () {
  165. return fetch('get', 'tokens')
  166. .then(response => {
  167. if (response.token) {
  168. Tokens.setCurrentToken(response.token);
  169. return response.token;
  170. } else {
  171. Tokens.clearTokens();
  172. throw(new Error('No token returned'));
  173. }
  174. });
  175. }
  176. },
  177. Users: {
  178. /**
  179. * @param {Number|String} user_id
  180. * @param {Array} [expand]
  181. * @returns {Promise}
  182. */
  183. getById: function (user_id, expand) {
  184. return fetch('get', 'users/' + user_id + (typeof expand === 'object' && expand.length ? '?expand=' + makeExpansionString(expand) : ''));
  185. },
  186. /**
  187. * @param {Array} [expand]
  188. * @param {String} [query]
  189. * @returns {Promise}
  190. */
  191. getAll: function (expand, query) {
  192. return getAllObjects('users', expand, query);
  193. },
  194. /**
  195. * @param {Object} data
  196. * @returns {Promise}
  197. */
  198. create: function (data) {
  199. return fetch('post', 'users', data);
  200. },
  201. /**
  202. * @param {Object} data
  203. * @param {Number} data.id
  204. * @returns {Promise}
  205. */
  206. update: function (data) {
  207. let id = data.id;
  208. delete data.id;
  209. return fetch('put', 'users/' + id, data);
  210. },
  211. /**
  212. * @param {Number} id
  213. * @returns {Promise}
  214. */
  215. delete: function (id) {
  216. return fetch('delete', 'users/' + id);
  217. },
  218. /**
  219. *
  220. * @param {Number} id
  221. * @param {Object} auth
  222. * @returns {Promise}
  223. */
  224. setPassword: function (id, auth) {
  225. return fetch('put', 'users/' + id + '/auth', auth);
  226. },
  227. /**
  228. * @param {Number} id
  229. * @returns {Promise}
  230. */
  231. loginAs: function (id) {
  232. return fetch('post', 'users/' + id + '/login');
  233. },
  234. /**
  235. *
  236. * @param {Number} id
  237. * @param {Object} perms
  238. * @returns {Promise}
  239. */
  240. setPermissions: function (id, perms) {
  241. return fetch('put', 'users/' + id + '/permissions', perms);
  242. }
  243. },
  244. Nginx: {
  245. ProxyHosts: {
  246. /**
  247. * @param {Array} [expand]
  248. * @param {String} [query]
  249. * @returns {Promise}
  250. */
  251. getAll: function (expand, query) {
  252. return getAllObjects('nginx/proxy-hosts', expand, query);
  253. },
  254. /**
  255. * @param {Object} data
  256. */
  257. create: function (data) {
  258. return fetch('post', 'nginx/proxy-hosts', data);
  259. },
  260. /**
  261. * @param {Object} data
  262. * @param {Number} data.id
  263. * @returns {Promise}
  264. */
  265. update: function (data) {
  266. let id = data.id;
  267. delete data.id;
  268. return fetch('put', 'nginx/proxy-hosts/' + id, data);
  269. },
  270. /**
  271. * @param {Number} id
  272. * @returns {Promise}
  273. */
  274. delete: function (id) {
  275. return fetch('delete', 'nginx/proxy-hosts/' + id);
  276. },
  277. /**
  278. * @param {Number} id
  279. * @returns {Promise}
  280. */
  281. get: function (id) {
  282. return fetch('get', 'nginx/proxy-hosts/' + id);
  283. },
  284. /**
  285. * @param {Number} id
  286. * @returns {Promise}
  287. */
  288. enable: function (id) {
  289. return fetch('post', 'nginx/proxy-hosts/' + id + '/enable');
  290. },
  291. /**
  292. * @param {Number} id
  293. * @returns {Promise}
  294. */
  295. disable: function (id) {
  296. return fetch('post', 'nginx/proxy-hosts/' + id + '/disable');
  297. }
  298. },
  299. RedirectionHosts: {
  300. /**
  301. * @param {Array} [expand]
  302. * @param {String} [query]
  303. * @returns {Promise}
  304. */
  305. getAll: function (expand, query) {
  306. return getAllObjects('nginx/redirection-hosts', expand, query);
  307. },
  308. /**
  309. * @param {Object} data
  310. */
  311. create: function (data) {
  312. return fetch('post', 'nginx/redirection-hosts', data);
  313. },
  314. /**
  315. * @param {Object} data
  316. * @param {Number} data.id
  317. * @returns {Promise}
  318. */
  319. update: function (data) {
  320. let id = data.id;
  321. delete data.id;
  322. return fetch('put', 'nginx/redirection-hosts/' + id, data);
  323. },
  324. /**
  325. * @param {Number} id
  326. * @returns {Promise}
  327. */
  328. delete: function (id) {
  329. return fetch('delete', 'nginx/redirection-hosts/' + id);
  330. },
  331. /**
  332. * @param {Number} id
  333. * @returns {Promise}
  334. */
  335. get: function (id) {
  336. return fetch('get', 'nginx/redirection-hosts/' + id);
  337. },
  338. /**
  339. * @param {Number} id
  340. * @param {FormData} form_data
  341. * @params {Promise}
  342. */
  343. setCerts: function (id, form_data) {
  344. return FileUpload('nginx/redirection-hosts/' + id + '/certificates', form_data);
  345. },
  346. /**
  347. * @param {Number} id
  348. * @returns {Promise}
  349. */
  350. enable: function (id) {
  351. return fetch('post', 'nginx/redirection-hosts/' + id + '/enable');
  352. },
  353. /**
  354. * @param {Number} id
  355. * @returns {Promise}
  356. */
  357. disable: function (id) {
  358. return fetch('post', 'nginx/redirection-hosts/' + id + '/disable');
  359. }
  360. },
  361. Streams: {
  362. /**
  363. * @param {Array} [expand]
  364. * @param {String} [query]
  365. * @returns {Promise}
  366. */
  367. getAll: function (expand, query) {
  368. return getAllObjects('nginx/streams', expand, query);
  369. },
  370. /**
  371. * @param {Object} data
  372. */
  373. create: function (data) {
  374. return fetch('post', 'nginx/streams', data);
  375. },
  376. /**
  377. * @param {Object} data
  378. * @param {Number} data.id
  379. * @returns {Promise}
  380. */
  381. update: function (data) {
  382. let id = data.id;
  383. delete data.id;
  384. return fetch('put', 'nginx/streams/' + id, data);
  385. },
  386. /**
  387. * @param {Number} id
  388. * @returns {Promise}
  389. */
  390. delete: function (id) {
  391. return fetch('delete', 'nginx/streams/' + id);
  392. },
  393. /**
  394. * @param {Number} id
  395. * @returns {Promise}
  396. */
  397. get: function (id) {
  398. return fetch('get', 'nginx/streams/' + id);
  399. },
  400. /**
  401. * @param {Number} id
  402. * @returns {Promise}
  403. */
  404. enable: function (id) {
  405. return fetch('post', 'nginx/streams/' + id + '/enable');
  406. },
  407. /**
  408. * @param {Number} id
  409. * @returns {Promise}
  410. */
  411. disable: function (id) {
  412. return fetch('post', 'nginx/streams/' + id + '/disable');
  413. }
  414. },
  415. DeadHosts: {
  416. /**
  417. * @param {Array} [expand]
  418. * @param {String} [query]
  419. * @returns {Promise}
  420. */
  421. getAll: function (expand, query) {
  422. return getAllObjects('nginx/dead-hosts', expand, query);
  423. },
  424. /**
  425. * @param {Object} data
  426. */
  427. create: function (data) {
  428. return fetch('post', 'nginx/dead-hosts', data);
  429. },
  430. /**
  431. * @param {Object} data
  432. * @param {Number} data.id
  433. * @returns {Promise}
  434. */
  435. update: function (data) {
  436. let id = data.id;
  437. delete data.id;
  438. return fetch('put', 'nginx/dead-hosts/' + id, data);
  439. },
  440. /**
  441. * @param {Number} id
  442. * @returns {Promise}
  443. */
  444. delete: function (id) {
  445. return fetch('delete', 'nginx/dead-hosts/' + id);
  446. },
  447. /**
  448. * @param {Number} id
  449. * @returns {Promise}
  450. */
  451. get: function (id) {
  452. return fetch('get', 'nginx/dead-hosts/' + id);
  453. },
  454. /**
  455. * @param {Number} id
  456. * @param {FormData} form_data
  457. * @params {Promise}
  458. */
  459. setCerts: function (id, form_data) {
  460. return FileUpload('nginx/dead-hosts/' + id + '/certificates', form_data);
  461. },
  462. /**
  463. * @param {Number} id
  464. * @returns {Promise}
  465. */
  466. enable: function (id) {
  467. return fetch('post', 'nginx/dead-hosts/' + id + '/enable');
  468. },
  469. /**
  470. * @param {Number} id
  471. * @returns {Promise}
  472. */
  473. disable: function (id) {
  474. return fetch('post', 'nginx/dead-hosts/' + id + '/disable');
  475. }
  476. },
  477. AccessLists: {
  478. /**
  479. * @param {Array} [expand]
  480. * @param {String} [query]
  481. * @returns {Promise}
  482. */
  483. getAll: function (expand, query) {
  484. return getAllObjects('nginx/access-lists', expand, query);
  485. },
  486. /**
  487. * @param {Object} data
  488. */
  489. create: function (data) {
  490. return fetch('post', 'nginx/access-lists', data);
  491. },
  492. /**
  493. * @param {Object} data
  494. * @param {Number} data.id
  495. * @returns {Promise}
  496. */
  497. update: function (data) {
  498. let id = data.id;
  499. delete data.id;
  500. return fetch('put', 'nginx/access-lists/' + id, data);
  501. },
  502. /**
  503. * @param {Number} id
  504. * @returns {Promise}
  505. */
  506. delete: function (id) {
  507. return fetch('delete', 'nginx/access-lists/' + id);
  508. }
  509. },
  510. Certificates: {
  511. /**
  512. * @param {Array} [expand]
  513. * @param {String} [query]
  514. * @returns {Promise}
  515. */
  516. getAll: function (expand, query) {
  517. return getAllObjects('nginx/certificates', expand, query);
  518. },
  519. /**
  520. * @param {Object} data
  521. */
  522. create: function (data) {
  523. const timeout = 180000 + (data && data.meta && data.meta.propagation_seconds ? Number(data.meta.propagation_seconds) * 1000 : 0);
  524. return fetch('post', 'nginx/certificates', data, {timeout});
  525. },
  526. /**
  527. * @param {Object} data
  528. * @param {Number} data.id
  529. * @returns {Promise}
  530. */
  531. update: function (data) {
  532. let id = data.id;
  533. delete data.id;
  534. return fetch('put', 'nginx/certificates/' + id, data);
  535. },
  536. /**
  537. * @param {Number} id
  538. * @returns {Promise}
  539. */
  540. delete: function (id) {
  541. return fetch('delete', 'nginx/certificates/' + id);
  542. },
  543. /**
  544. * @param {Number} id
  545. * @param {FormData} form_data
  546. * @params {Promise}
  547. */
  548. upload: function (id, form_data) {
  549. return FileUpload('nginx/certificates/' + id + '/upload', form_data);
  550. },
  551. /**
  552. * @param {FormData} form_data
  553. * @params {Promise}
  554. */
  555. validate: function (form_data) {
  556. return FileUpload('nginx/certificates/validate', form_data);
  557. },
  558. /**
  559. * @param {Number} id
  560. * @returns {Promise}
  561. */
  562. renew: function (id, timeout = 180000) {
  563. return fetch('post', 'nginx/certificates/' + id + '/renew', undefined, {timeout});
  564. }
  565. }
  566. },
  567. AuditLog: {
  568. /**
  569. * @param {Array} [expand]
  570. * @param {String} [query]
  571. * @returns {Promise}
  572. */
  573. getAll: function (expand, query) {
  574. return getAllObjects('audit-log', expand, query);
  575. }
  576. },
  577. Reports: {
  578. /**
  579. * @returns {Promise}
  580. */
  581. getHostStats: function () {
  582. return fetch('get', 'reports/hosts');
  583. }
  584. },
  585. Settings: {
  586. /**
  587. * @param {String} setting_id
  588. * @returns {Promise}
  589. */
  590. getById: function (setting_id) {
  591. return fetch('get', 'settings/' + setting_id);
  592. },
  593. /**
  594. * @returns {Promise}
  595. */
  596. getAll: function () {
  597. return getAllObjects('settings');
  598. },
  599. /**
  600. * @param {Object} data
  601. * @param {Number} data.id
  602. * @returns {Promise}
  603. */
  604. update: function (data) {
  605. let id = data.id;
  606. delete data.id;
  607. return fetch('put', 'settings/' + id, data);
  608. }
  609. }
  610. };