api.js 22 KB

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