diff --git a/admin/api/s3.js b/admin/api/s3.js new file mode 100644 index 0000000000..2eb5e172f8 --- /dev/null +++ b/admin/api/s3.js @@ -0,0 +1,48 @@ +var knox = require('knox'); +var keystone = require('../../'); +var Types = keystone.Field.Types; + +exports = module.exports = { + + upload: function(req, res) { + if (!keystone.security.csrf.validate(req, req.body.authenticity_token)) { + return res.status(400).send({ error: { message:'invalid csrf' } }); + } + + if(req.files && req.files.file){ + + var s3Config = keystone.get('s3 config'); + + var file = req.files.file, + path = s3Config.s3path ? s3Config.s3path + '/' : ''; + + var headers = Types.S3File.prototype.generateHeaders.call({ s3config: s3Config, options: {} }, null, file); + + var s3Client = knox.createClient(s3Config); + + s3Client.putFile(file.path, path + file.name, headers, function(err, s3Response) { + var sendResult = function () { + if(err){ + return res.send({ error: { message: err.message } }); + } + + if (s3Response) { + if (s3Response.statusCode !== 200) { + return res.send({ error: { message:'Amazon returned Http Code: ' + s3Response.statusCode } }); + } else { + return res.send({ image: { url: 'https://s3.amazonaws.com/' + s3Config.bucket + '/' + file.name } }); + } + } + }; + + res.format({ + html: sendResult, + json: sendResult + }); + }); + + } else { + res.json({ error: { message: 'No image selected' } }); + } + } +}; diff --git a/fields/types/html/HtmlField.js b/fields/types/html/HtmlField.js index ab9b120595..8e906a7bce 100644 --- a/fields/types/html/HtmlField.js +++ b/fields/types/html/HtmlField.js @@ -108,7 +108,7 @@ module.exports = Field.create({ toolbar += ' | image'; } - if (options.enableCloudinaryUploads) { + if (options.enableCloudinaryUploads || options.enableS3Uploads) { plugins.push('uploadimage'); toolbar += options.enableImages ? ' uploadimage' : ' | uploadimage'; } @@ -149,7 +149,7 @@ module.exports = Field.create({ }; if (this.shouldRenderField()) { - opts.uploadimage_form_url = '/keystone/api/cloudinary/upload'; + opts.uploadimage_form_url = options.enableS3Uploads ? '/keystone/api/s3/upload' : '/keystone/api/cloudinary/upload'; } else { _.extend(opts, { mode: 'textareas', diff --git a/lib/core/render.js b/lib/core/render.js index 5d804531cb..ebf4bcc796 100644 --- a/lib/core/render.js +++ b/lib/core/render.js @@ -84,6 +84,7 @@ function render(req, res, view, ext) { wysiwygOptions: { enableImages: keystone.get('wysiwyg images') ? true : false, enableCloudinaryUploads: keystone.get('wysiwyg cloudinary images') ? true : false, + enableS3Uploads: keystone.get('wysiwyg s3 images') ? true : false, additionalButtons: keystone.get('wysiwyg additional buttons') || '', additionalPlugins: keystone.get('wysiwyg additional plugins') || '', additionalOptions: keystone.get('wysiwyg additional options') || {}, diff --git a/lib/core/routes.js b/lib/core/routes.js index c6f0b08fb3..ccb15cdd8f 100644 --- a/lib/core/routes.js +++ b/lib/core/routes.js @@ -82,6 +82,12 @@ function routes(app) { app.post('/keystone/api/cloudinary/upload', require('../../admin/api/cloudinary').upload); } + // S3 API for uploading a new image + if (keystone.get('s3 config')) { + debug('setting S3 api'); + app.post('/keystone/api/s3/upload', require('../../admin/api/s3').upload); + } + // Init API request helpers app.use('/keystone/api', function(req, res, next) { res.apiError = function(key, err) { diff --git a/templates/layout/base.jade b/templates/layout/base.jade index cea96249e6..8589b411d2 100644 --- a/templates/layout/base.jade +++ b/templates/layout/base.jade @@ -5,6 +5,7 @@ html head meta(charset="utf-8") meta(name="viewport", content="initial-scale=1.0,user-scalable=no,maximum-scale=1,width=device-width") + meta(name="csrf-token", content="#{csrf_token_value}") title= title @@ -50,7 +51,7 @@ html - path = navList.path else - path = '/keystone/' + navList.path - + li(class=navList.key == list.key ? 'active' : null): a(href=path tabIndex="-1")= navList.label .keystone-body +flash-messages(messages) @@ -61,7 +62,7 @@ html a(href=backUrl tabIndex="-1").keystone-footer__link #{brand + (appversion ? (' ' + appversion) : '')} | Powered by KeystoneJS version #{version}. if User && user - | Signed in as + | Signed in as a(href='/keystone/' + User.path + '/' + user.id tabIndex="-1").keystone-footer__link= User.getDocumentName(user) | . @@ -115,7 +116,7 @@ html script(src="/keystone/js/common/ui.js") script(src="/keystone/js/common/ui-alt-text.js") script(src="/keystone/js/common/ui-sortable.js") - + //- Page Scripts block js