space_exports.js 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. "use strict";
  2. var config = require('config');
  3. const db = require('../../models/db');
  4. var mailer = require('../../helpers/mailer');
  5. var uploader = require('../../helpers/uploader');
  6. var space_render = require('../../helpers/space-render');
  7. var phantom = require('../../helpers/phantom');
  8. var async = require('async');
  9. var moment = require('moment');
  10. var fs = require('fs');
  11. var _ = require("underscore");
  12. var archiver = require('archiver');
  13. var request = require('request');
  14. var url = require("url");
  15. var path = require("path");
  16. var crypto = require('crypto');
  17. var glob = require('glob');
  18. var gm = require('gm');
  19. var sanitizeHtml = require('sanitize-html');
  20. var express = require('express');
  21. var router = express.Router({mergeParams: true});
  22. // JSON MAPPINGS
  23. var userMapping = {
  24. _id: 1,
  25. nickname: 1,
  26. email: 1,
  27. avatar_thumb_uri: 1
  28. };
  29. var spaceMapping = {
  30. _id: 1,
  31. name: 1,
  32. thumbnail_url: 1
  33. };
  34. var roleMapping = {
  35. "none": 0,
  36. "viewer": 1,
  37. "editor": 2,
  38. "admin": 3
  39. }
  40. router.get('/png', function(req, res, next) {
  41. var triggered = new Date();
  42. var s3_filename = "s" + req.space._id + "/" + "thumb_" + triggered.getTime() + ".jpg";
  43. if (!req.space.thumbnail_updated_at || req.space.thumbnail_updated_at < req.space.updated_at || !req.space.thumbnail_url) {
  44. db.Space.update({ thumbnail_updated_at: triggered }, {where : {"_id": req.space._id }});
  45. phantom.takeScreenshot(req.space, "png",
  46. function(local_path) {
  47. var localResizedFilePath = local_path + ".thumb.jpg";
  48. gm(local_path).resize(640, 480).quality(70.0).autoOrient().write(localResizedFilePath, function(err) {
  49. if (err) {
  50. console.error("[space screenshot] resize error: ", err);
  51. res.status(500).send("Error taking screenshot.");
  52. return;
  53. }
  54. uploader.uploadFile(s3_filename, "image/jpeg", localResizedFilePath, function(err, thumbnailUrl) {
  55. if (err) {
  56. console.error("[space screenshot] upload error. filename: " + s3_filename + " details: ", err);
  57. res.status(500).send("Error uploading screenshot.");
  58. return;
  59. }
  60. var oldUrl = req.space.thumbnail_url;
  61. db.Space.update({ thumbnail_url: thumbnailUrl }, {where : {"_id": req.space._id }}).then(() => {
  62. res.redirect(thumbnailUrl);
  63. try {
  64. if (oldUrl) {
  65. var oldPath = url.parse(oldUrl).pathname;
  66. uploader.removeFile(oldPath, function(err, res) {});
  67. }
  68. fs.unlink(local_path);
  69. } catch (e) {
  70. console.error(e);
  71. }
  72. });
  73. try {
  74. fs.unlink(localResizedFilePath);
  75. } catch (e) {
  76. console.error(e);
  77. }
  78. });
  79. });
  80. },
  81. function() {
  82. // on_error
  83. console.error("phantom could not create screenshot for space " + req.space_id);
  84. res.status(404).send("Not found");
  85. });
  86. } else {
  87. res.redirect(req.space.thumbnail_url);
  88. }
  89. });
  90. function make_export_filename(space, extension) {
  91. return space.name.replace(/[^\w]/g, '') + "-" + space._id + "-" + moment().format("YYYYMMDD-HH-mm-ss") + "." + extension;
  92. }
  93. router.get('/pdf', function(req, res, next) {
  94. var s3_filename = make_export_filename(req.space, "pdf");
  95. phantom.takeScreenshot(req.space, "pdf", function(local_path) {
  96. uploader.uploadFile(s3_filename, "application/pdf", local_path, function(err, url) {
  97. res.status(201).json({
  98. url: url
  99. });
  100. fs.unlink(local_path);
  101. });
  102. }, (err) => {
  103. res.status(500).json({
  104. error: "PDF could not created (500)"
  105. });
  106. });
  107. });
  108. router.get('/zip', function(req, res, next) {
  109. db.Artifact.findOne({
  110. space_id: req.space._id
  111. }, function(err, artifacts) {
  112. if (!artifacts || !artifacts.length || err) {
  113. res.status(404).json({
  114. "error": "no artifacts"
  115. });
  116. return;
  117. }
  118. var localPath = "/tmp/" + req.space._id;
  119. try {
  120. var files = fs.readdirSync(localPath);
  121. for (var i = 0; i < files.length; i++) {
  122. console.log("[zip export] unlink old file: ", localPath + "/" + files[i]);
  123. if (files[i] != "." && files[i] != "..") {
  124. fs.unlinkSync(localPath + "/" + files[i]);
  125. }
  126. }
  127. fs.rmdirSync(localPath);
  128. } catch (e) {
  129. console.error(e);
  130. }
  131. var used_filenames = {};
  132. fs.mkdir(localPath, function(err, cb) {
  133. async.eachLimit(artifacts, 10, function(artifact, cb) {
  134. try {
  135. if (artifact.payload_uri) {
  136. if (artifact.payload_uri.indexOf("https://") > -1 || artifact.payload_uri.indexOf("http://") > -1) {
  137. var parsed = url.parse(artifact.payload_uri);
  138. var fileName = path.basename(parsed.pathname) || "file.bin";
  139. if (fileName.length > 128) {
  140. fileName = fileName.substr(fileName.length - 128);
  141. }
  142. if (used_filenames[fileName]) {
  143. // if there is a fileName collision, we insert a number before the extension
  144. // to differentiate
  145. var ext = path.extname(fileName);
  146. fileName = path.basename(fileName, ext) + "_" + (parseInt(Math.random() * 10000)) + ext;
  147. }
  148. used_filenames[fileName] = true;
  149. //fix for old artifacts where no .pdf is in the filename
  150. if (artifact.mime == "application/pdf" && fileName.indexOf(".pdf") < 0) {
  151. fileName = fileName + ".pdf";
  152. }
  153. if (artifact.mime == "image/png" && fileName.indexOf(".png") < 0) {
  154. fileName = fileName + ".png";
  155. }
  156. var localFilePath = localPath + '/' + fileName;
  157. request
  158. .get(artifact.payload_uri)
  159. .on('error', function(err) {
  160. console.error(err);
  161. cb(null, artifact.payload_uri);
  162. })
  163. .on('end', function() {
  164. cb(null, artifact.payload_uri);
  165. }).pipe(fs.createWriteStream(localFilePath));
  166. } else {
  167. cb(null, artifact.payload_uri);
  168. }
  169. } else {
  170. cb(null, artifact.payload_uri);
  171. }
  172. } catch (e) {
  173. console.log(e);
  174. cb(null);
  175. }
  176. }, function(err, payloads) {
  177. var outputPath = '/tmp/' + req.space._id + '.zip';
  178. var output = fs.createWriteStream(outputPath);
  179. var archive = archiver('zip');
  180. output.on('close', function() {
  181. var name = make_export_filename(req.space, "zip");
  182. uploader.uploadFile(name, "application/zip", outputPath, function(err, url) {
  183. res.status(201).json({
  184. url: url
  185. });
  186. try {
  187. fs.unlink(outputPath);
  188. } catch (e) {
  189. console.error(e);
  190. }
  191. });
  192. });
  193. archive.on('error', function(err) {
  194. console.error(err);
  195. });
  196. archive.pipe(output);
  197. archive.directory(localPath, false, {
  198. date: new Date()
  199. });
  200. archive.finalize();
  201. });
  202. });
  203. });
  204. });
  205. router.get('/html', function(req, res) {
  206. db.Artifact.findAll({where: {
  207. space_id: req.space._id
  208. }}).then(function(artifacts) {
  209. var space = req.space;
  210. res.send(space_render.render_space_as_html(space, artifacts));
  211. });
  212. });
  213. module.exports = router;