api.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817
  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. //ref : https://codepen.io/chrisdpratt/pen/RKxJNo
  135. function DownloadFile(verb, path, filename) {
  136. return new Promise(function (resolve, reject) {
  137. let api_url = '/api/';
  138. let url = api_url + path;
  139. let token = Tokens.getTopToken();
  140. $.ajax({
  141. url: url,
  142. type: verb,
  143. crossDomain: true,
  144. xhrFields: {
  145. withCredentials: true,
  146. responseType: 'blob'
  147. },
  148. beforeSend: function (xhr) {
  149. xhr.setRequestHeader('Authorization', 'Bearer ' + (token ? token.t : null));
  150. },
  151. success: function (data) {
  152. var a = document.createElement('a');
  153. var url = window.URL.createObjectURL(data);
  154. a.href = url;
  155. a.download = filename;
  156. document.body.append(a);
  157. a.click();
  158. a.remove();
  159. window.URL.revokeObjectURL(url);
  160. },
  161. error: function (xhr, status, error_thrown) {
  162. let code = 400;
  163. if (typeof xhr.responseJSON !== 'undefined' && typeof xhr.responseJSON.error !== 'undefined' && typeof xhr.responseJSON.error.message !== 'undefined') {
  164. error_thrown = xhr.responseJSON.error.message;
  165. code = xhr.responseJSON.error.code || 500;
  166. }
  167. reject(new ApiError(error_thrown, xhr.responseText, code));
  168. }
  169. });
  170. });
  171. }
  172. module.exports = {
  173. status: function () {
  174. return fetch('get', '');
  175. },
  176. Tokens: {
  177. /**
  178. * @param {String} identity
  179. * @param {String} secret
  180. * @param {Boolean} [wipe] Will wipe the stack before adding to it again if login was successful
  181. * @returns {Promise}
  182. */
  183. login: function (identity, secret, wipe) {
  184. return fetch('post', 'tokens', {identity: identity, secret: secret})
  185. .then(response => {
  186. if (response.token) {
  187. if (wipe) {
  188. Tokens.clearTokens();
  189. }
  190. // Set storage token
  191. Tokens.addToken(response.token);
  192. return response.token;
  193. } else {
  194. Tokens.clearTokens();
  195. throw(new Error('No token returned'));
  196. }
  197. });
  198. },
  199. /**
  200. * @returns {Promise}
  201. */
  202. refresh: function () {
  203. return fetch('get', 'tokens')
  204. .then(response => {
  205. if (response.token) {
  206. Tokens.setCurrentToken(response.token);
  207. return response.token;
  208. } else {
  209. Tokens.clearTokens();
  210. throw(new Error('No token returned'));
  211. }
  212. });
  213. }
  214. },
  215. Users: {
  216. /**
  217. * @param {Number|String} user_id
  218. * @param {Array} [expand]
  219. * @returns {Promise}
  220. */
  221. getById: function (user_id, expand) {
  222. return fetch('get', 'users/' + user_id + (typeof expand === 'object' && expand.length ? '?expand=' + makeExpansionString(expand) : ''));
  223. },
  224. /**
  225. * @param {Array} [expand]
  226. * @param {String} [query]
  227. * @returns {Promise}
  228. */
  229. getAll: function (expand, query) {
  230. return getAllObjects('users', expand, query);
  231. },
  232. /**
  233. * @param {Object} data
  234. * @returns {Promise}
  235. */
  236. create: function (data) {
  237. return fetch('post', 'users', data);
  238. },
  239. /**
  240. * @param {Object} data
  241. * @param {Number} data.id
  242. * @returns {Promise}
  243. */
  244. update: function (data) {
  245. let id = data.id;
  246. delete data.id;
  247. return fetch('put', 'users/' + id, data);
  248. },
  249. /**
  250. * @param {Number} id
  251. * @returns {Promise}
  252. */
  253. delete: function (id) {
  254. return fetch('delete', 'users/' + id);
  255. },
  256. /**
  257. *
  258. * @param {Number} id
  259. * @param {Object} auth
  260. * @returns {Promise}
  261. */
  262. setPassword: function (id, auth) {
  263. return fetch('put', 'users/' + id + '/auth', auth);
  264. },
  265. /**
  266. * @param {Number} id
  267. * @returns {Promise}
  268. */
  269. loginAs: function (id) {
  270. return fetch('post', 'users/' + id + '/login');
  271. },
  272. /**
  273. *
  274. * @param {Number} id
  275. * @param {Object} perms
  276. * @returns {Promise}
  277. */
  278. setPermissions: function (id, perms) {
  279. return fetch('put', 'users/' + id + '/permissions', perms);
  280. }
  281. },
  282. Nginx: {
  283. ProxyHosts: {
  284. /**
  285. * @param {Array} [expand]
  286. * @param {String} [query]
  287. * @returns {Promise}
  288. */
  289. getAll: function (expand, query) {
  290. return getAllObjects('nginx/proxy-hosts', expand, query);
  291. },
  292. /**
  293. * @param {Object} data
  294. */
  295. create: function (data) {
  296. return fetch('post', 'nginx/proxy-hosts', data);
  297. },
  298. /**
  299. * @param {Object} data
  300. * @param {Number} data.id
  301. * @returns {Promise}
  302. */
  303. update: function (data) {
  304. let id = data.id;
  305. delete data.id;
  306. return fetch('put', 'nginx/proxy-hosts/' + id, data);
  307. },
  308. /**
  309. * @param {Number} id
  310. * @returns {Promise}
  311. */
  312. delete: function (id) {
  313. return fetch('delete', 'nginx/proxy-hosts/' + id);
  314. },
  315. /**
  316. * @param {Number} id
  317. * @returns {Promise}
  318. */
  319. get: function (id) {
  320. return fetch('get', 'nginx/proxy-hosts/' + id);
  321. },
  322. /**
  323. * @param {Number} id
  324. * @returns {Promise}
  325. */
  326. enable: function (id) {
  327. return fetch('post', 'nginx/proxy-hosts/' + id + '/enable');
  328. },
  329. /**
  330. * @param {Number} id
  331. * @returns {Promise}
  332. */
  333. disable: function (id) {
  334. return fetch('post', 'nginx/proxy-hosts/' + id + '/disable');
  335. }
  336. },
  337. RedirectionHosts: {
  338. /**
  339. * @param {Array} [expand]
  340. * @param {String} [query]
  341. * @returns {Promise}
  342. */
  343. getAll: function (expand, query) {
  344. return getAllObjects('nginx/redirection-hosts', expand, query);
  345. },
  346. /**
  347. * @param {Object} data
  348. */
  349. create: function (data) {
  350. return fetch('post', 'nginx/redirection-hosts', data);
  351. },
  352. /**
  353. * @param {Object} data
  354. * @param {Number} data.id
  355. * @returns {Promise}
  356. */
  357. update: function (data) {
  358. let id = data.id;
  359. delete data.id;
  360. return fetch('put', 'nginx/redirection-hosts/' + id, data);
  361. },
  362. /**
  363. * @param {Number} id
  364. * @returns {Promise}
  365. */
  366. delete: function (id) {
  367. return fetch('delete', 'nginx/redirection-hosts/' + id);
  368. },
  369. /**
  370. * @param {Number} id
  371. * @returns {Promise}
  372. */
  373. get: function (id) {
  374. return fetch('get', 'nginx/redirection-hosts/' + id);
  375. },
  376. /**
  377. * @param {Number} id
  378. * @param {FormData} form_data
  379. * @params {Promise}
  380. */
  381. setCerts: function (id, form_data) {
  382. return FileUpload('nginx/redirection-hosts/' + id + '/certificates', form_data);
  383. },
  384. /**
  385. * @param {Number} id
  386. * @returns {Promise}
  387. */
  388. enable: function (id) {
  389. return fetch('post', 'nginx/redirection-hosts/' + id + '/enable');
  390. },
  391. /**
  392. * @param {Number} id
  393. * @returns {Promise}
  394. */
  395. disable: function (id) {
  396. return fetch('post', 'nginx/redirection-hosts/' + id + '/disable');
  397. }
  398. },
  399. Streams: {
  400. /**
  401. * @param {Array} [expand]
  402. * @param {String} [query]
  403. * @returns {Promise}
  404. */
  405. getAll: function (expand, query) {
  406. return getAllObjects('nginx/streams', expand, query);
  407. },
  408. /**
  409. * @param {Object} data
  410. */
  411. create: function (data) {
  412. return fetch('post', 'nginx/streams', data);
  413. },
  414. /**
  415. * @param {Object} data
  416. * @param {Number} data.id
  417. * @returns {Promise}
  418. */
  419. update: function (data) {
  420. let id = data.id;
  421. delete data.id;
  422. return fetch('put', 'nginx/streams/' + id, data);
  423. },
  424. /**
  425. * @param {Number} id
  426. * @returns {Promise}
  427. */
  428. delete: function (id) {
  429. return fetch('delete', 'nginx/streams/' + id);
  430. },
  431. /**
  432. * @param {Number} id
  433. * @returns {Promise}
  434. */
  435. get: function (id) {
  436. return fetch('get', 'nginx/streams/' + id);
  437. },
  438. /**
  439. * @param {Number} id
  440. * @returns {Promise}
  441. */
  442. enable: function (id) {
  443. return fetch('post', 'nginx/streams/' + id + '/enable');
  444. },
  445. /**
  446. * @param {Number} id
  447. * @returns {Promise}
  448. */
  449. disable: function (id) {
  450. return fetch('post', 'nginx/streams/' + id + '/disable');
  451. }
  452. },
  453. SslPassthroughHosts: {
  454. /**
  455. * @param {Array} [expand]
  456. * @param {String} [query]
  457. * @returns {Promise}
  458. */
  459. getFeatureEnabled: function () {
  460. return fetch('get', 'ssl-passthrough-enabled');
  461. },
  462. /**
  463. * @param {Array} [expand]
  464. * @param {String} [query]
  465. * @returns {Promise}
  466. */
  467. getAll: function (expand, query) {
  468. return getAllObjects('nginx/ssl-passthrough-hosts', expand, query);
  469. },
  470. /**
  471. * @param {Object} data
  472. */
  473. create: function (data) {
  474. return fetch('post', 'nginx/ssl-passthrough-hosts', data);
  475. },
  476. /**
  477. * @param {Object} data
  478. * @param {Number} data.id
  479. * @returns {Promise}
  480. */
  481. update: function (data) {
  482. let id = data.id;
  483. delete data.id;
  484. return fetch('put', 'nginx/ssl-passthrough-hosts/' + id, data);
  485. },
  486. /**
  487. * @param {Number} id
  488. * @returns {Promise}
  489. */
  490. delete: function (id) {
  491. return fetch('delete', 'nginx/ssl-passthrough-hosts/' + id);
  492. },
  493. /**
  494. * @param {Number} id
  495. * @returns {Promise}
  496. */
  497. get: function (id) {
  498. return fetch('get', 'nginx/ssl-passthrough-hosts/' + id);
  499. },
  500. /**
  501. * @param {Number} id
  502. * @returns {Promise}
  503. */
  504. enable: function (id) {
  505. return fetch('post', 'nginx/ssl-passthrough-hosts/' + id + '/enable');
  506. },
  507. /**
  508. * @param {Number} id
  509. * @returns {Promise}
  510. */
  511. disable: function (id) {
  512. return fetch('post', 'nginx/ssl-passthrough-hosts/' + id + '/disable');
  513. }
  514. },
  515. DeadHosts: {
  516. /**
  517. * @param {Array} [expand]
  518. * @param {String} [query]
  519. * @returns {Promise}
  520. */
  521. getAll: function (expand, query) {
  522. return getAllObjects('nginx/dead-hosts', expand, query);
  523. },
  524. /**
  525. * @param {Object} data
  526. */
  527. create: function (data) {
  528. return fetch('post', 'nginx/dead-hosts', data);
  529. },
  530. /**
  531. * @param {Object} data
  532. * @param {Number} data.id
  533. * @returns {Promise}
  534. */
  535. update: function (data) {
  536. let id = data.id;
  537. delete data.id;
  538. return fetch('put', 'nginx/dead-hosts/' + id, data);
  539. },
  540. /**
  541. * @param {Number} id
  542. * @returns {Promise}
  543. */
  544. delete: function (id) {
  545. return fetch('delete', 'nginx/dead-hosts/' + id);
  546. },
  547. /**
  548. * @param {Number} id
  549. * @returns {Promise}
  550. */
  551. get: function (id) {
  552. return fetch('get', 'nginx/dead-hosts/' + id);
  553. },
  554. /**
  555. * @param {Number} id
  556. * @param {FormData} form_data
  557. * @params {Promise}
  558. */
  559. setCerts: function (id, form_data) {
  560. return FileUpload('nginx/dead-hosts/' + id + '/certificates', form_data);
  561. },
  562. /**
  563. * @param {Number} id
  564. * @returns {Promise}
  565. */
  566. enable: function (id) {
  567. return fetch('post', 'nginx/dead-hosts/' + id + '/enable');
  568. },
  569. /**
  570. * @param {Number} id
  571. * @returns {Promise}
  572. */
  573. disable: function (id) {
  574. return fetch('post', 'nginx/dead-hosts/' + id + '/disable');
  575. }
  576. },
  577. AccessLists: {
  578. /**
  579. * @param {Array} [expand]
  580. * @param {String} [query]
  581. * @returns {Promise}
  582. */
  583. getAll: function (expand, query) {
  584. return getAllObjects('nginx/access-lists', expand, query);
  585. },
  586. /**
  587. * @param {Object} data
  588. */
  589. create: function (data) {
  590. return fetch('post', 'nginx/access-lists', data);
  591. },
  592. /**
  593. * @param {Object} data
  594. * @param {Number} data.id
  595. * @returns {Promise}
  596. */
  597. update: function (data) {
  598. let id = data.id;
  599. delete data.id;
  600. return fetch('put', 'nginx/access-lists/' + id, data);
  601. },
  602. /**
  603. * @param {Number} id
  604. * @returns {Promise}
  605. */
  606. delete: function (id) {
  607. return fetch('delete', 'nginx/access-lists/' + id);
  608. }
  609. },
  610. Certificates: {
  611. /**
  612. * @param {Array} [expand]
  613. * @param {String} [query]
  614. * @returns {Promise}
  615. */
  616. getAll: function (expand, query) {
  617. return getAllObjects('nginx/certificates', expand, query);
  618. },
  619. /**
  620. * @param {Object} data
  621. */
  622. create: function (data) {
  623. const timeout = 180000 + (data && data.meta && data.meta.propagation_seconds ? Number(data.meta.propagation_seconds) * 1000 : 0);
  624. return fetch('post', 'nginx/certificates', data, {timeout});
  625. },
  626. /**
  627. * @param {Object} data
  628. * @param {Number} data.id
  629. * @returns {Promise}
  630. */
  631. update: function (data) {
  632. let id = data.id;
  633. delete data.id;
  634. return fetch('put', 'nginx/certificates/' + id, data);
  635. },
  636. /**
  637. * @param {Number} id
  638. * @returns {Promise}
  639. */
  640. delete: function (id) {
  641. return fetch('delete', 'nginx/certificates/' + id);
  642. },
  643. /**
  644. * @param {Number} id
  645. * @param {FormData} form_data
  646. * @params {Promise}
  647. */
  648. upload: function (id, form_data) {
  649. return FileUpload('nginx/certificates/' + id + '/upload', form_data);
  650. },
  651. /**
  652. * @param {FormData} form_data
  653. * @params {Promise}
  654. */
  655. validate: function (form_data) {
  656. return FileUpload('nginx/certificates/validate', form_data);
  657. },
  658. /**
  659. * @param {Number} id
  660. * @returns {Promise}
  661. */
  662. renew: function (id, timeout = 180000) {
  663. return fetch('post', 'nginx/certificates/' + id + '/renew', undefined, {timeout});
  664. },
  665. /**
  666. * @param {Number} id
  667. * @returns {Promise}
  668. */
  669. download: function (id) {
  670. return DownloadFile('get', "nginx/certificates/" + id + "/download", "certificate.zip")
  671. }
  672. }
  673. },
  674. AuditLog: {
  675. /**
  676. * @param {Array} [expand]
  677. * @param {String} [query]
  678. * @returns {Promise}
  679. */
  680. getAll: function (expand, query) {
  681. return getAllObjects('audit-log', expand, query);
  682. }
  683. },
  684. Reports: {
  685. /**
  686. * @returns {Promise}
  687. */
  688. getHostStats: function () {
  689. return fetch('get', 'reports/hosts');
  690. }
  691. },
  692. Settings: {
  693. /**
  694. * @param {String} setting_id
  695. * @returns {Promise}
  696. */
  697. getById: function (setting_id) {
  698. return fetch('get', 'settings/' + setting_id);
  699. },
  700. /**
  701. * @returns {Promise}
  702. */
  703. getAll: function () {
  704. return getAllObjects('settings');
  705. },
  706. /**
  707. * @param {Object} data
  708. * @param {Number} data.id
  709. * @returns {Promise}
  710. */
  711. update: function (data) {
  712. let id = data.id;
  713. delete data.id;
  714. return fetch('put', 'settings/' + id, data);
  715. }
  716. }
  717. };