api.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689
  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. reject(new Error('Upload failed: ' + xhr.status));
  123. } else {
  124. resolve(xhr.responseText);
  125. }
  126. }
  127. };
  128. });
  129. }
  130. module.exports = {
  131. status: function () {
  132. return fetch('get', '');
  133. },
  134. Tokens: {
  135. /**
  136. * @param {String} identity
  137. * @param {String} secret
  138. * @param {Boolean} [wipe] Will wipe the stack before adding to it again if login was successful
  139. * @returns {Promise}
  140. */
  141. login: function (identity, secret, wipe) {
  142. return fetch('post', 'tokens', {identity: identity, secret: secret})
  143. .then(response => {
  144. if (response.token) {
  145. if (wipe) {
  146. Tokens.clearTokens();
  147. }
  148. // Set storage token
  149. Tokens.addToken(response.token);
  150. return response.token;
  151. } else {
  152. Tokens.clearTokens();
  153. throw(new Error('No token returned'));
  154. }
  155. });
  156. },
  157. /**
  158. * @returns {Promise}
  159. */
  160. refresh: function () {
  161. return fetch('get', 'tokens')
  162. .then(response => {
  163. if (response.token) {
  164. Tokens.setCurrentToken(response.token);
  165. return response.token;
  166. } else {
  167. Tokens.clearTokens();
  168. throw(new Error('No token returned'));
  169. }
  170. });
  171. }
  172. },
  173. Users: {
  174. /**
  175. * @param {Number|String} user_id
  176. * @param {Array} [expand]
  177. * @returns {Promise}
  178. */
  179. getById: function (user_id, expand) {
  180. return fetch('get', 'users/' + user_id + (typeof expand === 'object' && expand.length ? '?expand=' + makeExpansionString(expand) : ''));
  181. },
  182. /**
  183. * @param {Array} [expand]
  184. * @param {String} [query]
  185. * @returns {Promise}
  186. */
  187. getAll: function (expand, query) {
  188. return getAllObjects('users', expand, query);
  189. },
  190. /**
  191. * @param {Object} data
  192. * @returns {Promise}
  193. */
  194. create: function (data) {
  195. return fetch('post', 'users', data);
  196. },
  197. /**
  198. * @param {Object} data
  199. * @param {Number} data.id
  200. * @returns {Promise}
  201. */
  202. update: function (data) {
  203. let id = data.id;
  204. delete data.id;
  205. return fetch('put', 'users/' + id, data);
  206. },
  207. /**
  208. * @param {Number} id
  209. * @returns {Promise}
  210. */
  211. delete: function (id) {
  212. return fetch('delete', 'users/' + id);
  213. },
  214. /**
  215. *
  216. * @param {Number} id
  217. * @param {Object} auth
  218. * @returns {Promise}
  219. */
  220. setPassword: function (id, auth) {
  221. return fetch('put', 'users/' + id + '/auth', auth);
  222. },
  223. /**
  224. * @param {Number} id
  225. * @returns {Promise}
  226. */
  227. loginAs: function (id) {
  228. return fetch('post', 'users/' + id + '/login');
  229. },
  230. /**
  231. *
  232. * @param {Number} id
  233. * @param {Object} perms
  234. * @returns {Promise}
  235. */
  236. setPermissions: function (id, perms) {
  237. return fetch('put', 'users/' + id + '/permissions', perms);
  238. }
  239. },
  240. Nginx: {
  241. ProxyHosts: {
  242. /**
  243. * @param {Array} [expand]
  244. * @param {String} [query]
  245. * @returns {Promise}
  246. */
  247. getAll: function (expand, query) {
  248. return getAllObjects('nginx/proxy-hosts', expand, query);
  249. },
  250. /**
  251. * @param {Object} data
  252. */
  253. create: function (data) {
  254. return fetch('post', 'nginx/proxy-hosts', data);
  255. },
  256. /**
  257. * @param {Object} data
  258. * @param {Number} data.id
  259. * @returns {Promise}
  260. */
  261. update: function (data) {
  262. let id = data.id;
  263. delete data.id;
  264. return fetch('put', 'nginx/proxy-hosts/' + id, data);
  265. },
  266. /**
  267. * @param {Number} id
  268. * @returns {Promise}
  269. */
  270. delete: function (id) {
  271. return fetch('delete', 'nginx/proxy-hosts/' + id);
  272. },
  273. /**
  274. * @param {Number} id
  275. * @returns {Promise}
  276. */
  277. get: function (id) {
  278. return fetch('get', 'nginx/proxy-hosts/' + id);
  279. },
  280. /**
  281. * @param {Number} id
  282. * @returns {Promise}
  283. */
  284. enable: function (id) {
  285. return fetch('post', 'nginx/proxy-hosts/' + id + '/enable');
  286. },
  287. /**
  288. * @param {Number} id
  289. * @returns {Promise}
  290. */
  291. disable: function (id) {
  292. return fetch('post', 'nginx/proxy-hosts/' + id + '/disable');
  293. }
  294. },
  295. RedirectionHosts: {
  296. /**
  297. * @param {Array} [expand]
  298. * @param {String} [query]
  299. * @returns {Promise}
  300. */
  301. getAll: function (expand, query) {
  302. return getAllObjects('nginx/redirection-hosts', expand, query);
  303. },
  304. /**
  305. * @param {Object} data
  306. */
  307. create: function (data) {
  308. return fetch('post', 'nginx/redirection-hosts', data);
  309. },
  310. /**
  311. * @param {Object} data
  312. * @param {Number} data.id
  313. * @returns {Promise}
  314. */
  315. update: function (data) {
  316. let id = data.id;
  317. delete data.id;
  318. return fetch('put', 'nginx/redirection-hosts/' + id, data);
  319. },
  320. /**
  321. * @param {Number} id
  322. * @returns {Promise}
  323. */
  324. delete: function (id) {
  325. return fetch('delete', 'nginx/redirection-hosts/' + id);
  326. },
  327. /**
  328. * @param {Number} id
  329. * @returns {Promise}
  330. */
  331. get: function (id) {
  332. return fetch('get', 'nginx/redirection-hosts/' + id);
  333. },
  334. /**
  335. * @param {Number} id
  336. * @param {FormData} form_data
  337. * @params {Promise}
  338. */
  339. setCerts: function (id, form_data) {
  340. return FileUpload('nginx/redirection-hosts/' + id + '/certificates', form_data);
  341. },
  342. /**
  343. * @param {Number} id
  344. * @returns {Promise}
  345. */
  346. enable: function (id) {
  347. return fetch('post', 'nginx/redirection-hosts/' + id + '/enable');
  348. },
  349. /**
  350. * @param {Number} id
  351. * @returns {Promise}
  352. */
  353. disable: function (id) {
  354. return fetch('post', 'nginx/redirection-hosts/' + id + '/disable');
  355. }
  356. },
  357. Streams: {
  358. /**
  359. * @param {Array} [expand]
  360. * @param {String} [query]
  361. * @returns {Promise}
  362. */
  363. getAll: function (expand, query) {
  364. return getAllObjects('nginx/streams', expand, query);
  365. },
  366. /**
  367. * @param {Object} data
  368. */
  369. create: function (data) {
  370. return fetch('post', 'nginx/streams', data);
  371. },
  372. /**
  373. * @param {Object} data
  374. * @param {Number} data.id
  375. * @returns {Promise}
  376. */
  377. update: function (data) {
  378. let id = data.id;
  379. delete data.id;
  380. return fetch('put', 'nginx/streams/' + id, data);
  381. },
  382. /**
  383. * @param {Number} id
  384. * @returns {Promise}
  385. */
  386. delete: function (id) {
  387. return fetch('delete', 'nginx/streams/' + id);
  388. },
  389. /**
  390. * @param {Number} id
  391. * @returns {Promise}
  392. */
  393. get: function (id) {
  394. return fetch('get', 'nginx/streams/' + id);
  395. },
  396. /**
  397. * @param {Number} id
  398. * @returns {Promise}
  399. */
  400. enable: function (id) {
  401. return fetch('post', 'nginx/streams/' + id + '/enable');
  402. },
  403. /**
  404. * @param {Number} id
  405. * @returns {Promise}
  406. */
  407. disable: function (id) {
  408. return fetch('post', 'nginx/streams/' + id + '/disable');
  409. }
  410. },
  411. DeadHosts: {
  412. /**
  413. * @param {Array} [expand]
  414. * @param {String} [query]
  415. * @returns {Promise}
  416. */
  417. getAll: function (expand, query) {
  418. return getAllObjects('nginx/dead-hosts', expand, query);
  419. },
  420. /**
  421. * @param {Object} data
  422. */
  423. create: function (data) {
  424. return fetch('post', 'nginx/dead-hosts', data);
  425. },
  426. /**
  427. * @param {Object} data
  428. * @param {Number} data.id
  429. * @returns {Promise}
  430. */
  431. update: function (data) {
  432. let id = data.id;
  433. delete data.id;
  434. return fetch('put', 'nginx/dead-hosts/' + id, data);
  435. },
  436. /**
  437. * @param {Number} id
  438. * @returns {Promise}
  439. */
  440. delete: function (id) {
  441. return fetch('delete', 'nginx/dead-hosts/' + id);
  442. },
  443. /**
  444. * @param {Number} id
  445. * @returns {Promise}
  446. */
  447. get: function (id) {
  448. return fetch('get', 'nginx/dead-hosts/' + id);
  449. },
  450. /**
  451. * @param {Number} id
  452. * @param {FormData} form_data
  453. * @params {Promise}
  454. */
  455. setCerts: function (id, form_data) {
  456. return FileUpload('nginx/dead-hosts/' + id + '/certificates', form_data);
  457. },
  458. /**
  459. * @param {Number} id
  460. * @returns {Promise}
  461. */
  462. enable: function (id) {
  463. return fetch('post', 'nginx/dead-hosts/' + id + '/enable');
  464. },
  465. /**
  466. * @param {Number} id
  467. * @returns {Promise}
  468. */
  469. disable: function (id) {
  470. return fetch('post', 'nginx/dead-hosts/' + id + '/disable');
  471. }
  472. },
  473. AccessLists: {
  474. /**
  475. * @param {Array} [expand]
  476. * @param {String} [query]
  477. * @returns {Promise}
  478. */
  479. getAll: function (expand, query) {
  480. return getAllObjects('nginx/access-lists', expand, query);
  481. },
  482. /**
  483. * @param {Object} data
  484. */
  485. create: function (data) {
  486. return fetch('post', 'nginx/access-lists', data);
  487. },
  488. /**
  489. * @param {Object} data
  490. * @param {Number} data.id
  491. * @returns {Promise}
  492. */
  493. update: function (data) {
  494. let id = data.id;
  495. delete data.id;
  496. return fetch('put', 'nginx/access-lists/' + id, data);
  497. },
  498. /**
  499. * @param {Number} id
  500. * @returns {Promise}
  501. */
  502. delete: function (id) {
  503. return fetch('delete', 'nginx/access-lists/' + id);
  504. }
  505. },
  506. Certificates: {
  507. /**
  508. * @param {Array} [expand]
  509. * @param {String} [query]
  510. * @returns {Promise}
  511. */
  512. getAll: function (expand, query) {
  513. return getAllObjects('nginx/certificates', expand, query);
  514. },
  515. /**
  516. * @param {Object} data
  517. */
  518. create: function (data) {
  519. const timeout = 180000 + (data.meta.propagation_seconds ? Number(data.meta.propagation_seconds) * 1000 : 0);
  520. return fetch('post', 'nginx/certificates', data, {timeout});
  521. },
  522. /**
  523. * @param {Object} data
  524. * @param {Number} data.id
  525. * @returns {Promise}
  526. */
  527. update: function (data) {
  528. let id = data.id;
  529. delete data.id;
  530. return fetch('put', 'nginx/certificates/' + id, data);
  531. },
  532. /**
  533. * @param {Number} id
  534. * @returns {Promise}
  535. */
  536. delete: function (id) {
  537. return fetch('delete', 'nginx/certificates/' + id);
  538. },
  539. /**
  540. * @param {Number} id
  541. * @param {FormData} form_data
  542. * @params {Promise}
  543. */
  544. upload: function (id, form_data) {
  545. return FileUpload('nginx/certificates/' + id + '/upload', form_data);
  546. },
  547. /**
  548. * @param {FormData} form_data
  549. * @params {Promise}
  550. */
  551. validate: function (form_data) {
  552. return FileUpload('nginx/certificates/validate', form_data);
  553. },
  554. /**
  555. * @param {Number} id
  556. * @returns {Promise}
  557. */
  558. renew: function (id, timeout = 180000) {
  559. return fetch('post', 'nginx/certificates/' + id + '/renew', undefined, {timeout});
  560. }
  561. }
  562. },
  563. AuditLog: {
  564. /**
  565. * @param {Array} [expand]
  566. * @param {String} [query]
  567. * @returns {Promise}
  568. */
  569. getAll: function (expand, query) {
  570. return getAllObjects('audit-log', expand, query);
  571. }
  572. },
  573. Reports: {
  574. /**
  575. * @returns {Promise}
  576. */
  577. getHostStats: function () {
  578. return fetch('get', 'reports/hosts');
  579. }
  580. },
  581. Settings: {
  582. /**
  583. * @param {String} setting_id
  584. * @returns {Promise}
  585. */
  586. getById: function (setting_id) {
  587. return fetch('get', 'settings/' + setting_id);
  588. },
  589. /**
  590. * @returns {Promise}
  591. */
  592. getAll: function () {
  593. return getAllObjects('settings');
  594. },
  595. /**
  596. * @param {Object} data
  597. * @param {Number} data.id
  598. * @returns {Promise}
  599. */
  600. update: function (data) {
  601. let id = data.id;
  602. delete data.id;
  603. return fetch('put', 'settings/' + id, data);
  604. }
  605. }
  606. };