mirror of
https://github.com/NodeBB/NodeBB.git
synced 2025-10-26 16:46:12 +01:00
feat: bypass cropper for gifs
This commit is contained in:
@@ -228,6 +228,7 @@ define('forum/account/edit', ['forum/account/header', 'translator', 'components'
|
|||||||
|
|
||||||
pictureCropper.show({
|
pictureCropper.show({
|
||||||
socketMethod: 'user.uploadCroppedPicture',
|
socketMethod: 'user.uploadCroppedPicture',
|
||||||
|
route: config.relative_path + '/api/user/' + ajaxify.data.userslug + '/uploadpicture',
|
||||||
aspectRatio: 1 / 1,
|
aspectRatio: 1 / 1,
|
||||||
paramName: 'uid',
|
paramName: 'uid',
|
||||||
paramValue: ajaxify.data.theirid,
|
paramValue: ajaxify.data.theirid,
|
||||||
@@ -235,7 +236,7 @@ define('forum/account/edit', ['forum/account/header', 'translator', 'components'
|
|||||||
allowSkippingCrop: false,
|
allowSkippingCrop: false,
|
||||||
title: '[[user:upload_picture]]',
|
title: '[[user:upload_picture]]',
|
||||||
description: '[[user:upload_a_picture]]',
|
description: '[[user:upload_a_picture]]',
|
||||||
accept: '.png,.jpg,.bmp',
|
accept: ajaxify.data.allowedProfileImageExtensios,
|
||||||
}, function (url) {
|
}, function (url) {
|
||||||
onUploadComplete(url);
|
onUploadComplete(url);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -18,6 +18,11 @@ define('pictureCropper', ['cropper'], function (Cropper) {
|
|||||||
uploadModal.remove();
|
uploadModal.remove();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var uploadForm = uploadModal.find('#uploadForm');
|
||||||
|
if (data.route) {
|
||||||
|
uploadForm.attr('action', data.route);
|
||||||
|
}
|
||||||
|
|
||||||
uploadModal.find('#fileUploadSubmitBtn').on('click', function () {
|
uploadModal.find('#fileUploadSubmitBtn').on('click', function () {
|
||||||
$(this).addClass('disabled');
|
$(this).addClass('disabled');
|
||||||
data.uploadModal = uploadModal;
|
data.uploadModal = uploadModal;
|
||||||
@@ -170,21 +175,27 @@ define('pictureCropper', ['cropper'], function (Cropper) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var file = fileInput[0].files[0];
|
var file = fileInput[0].files[0];
|
||||||
var reader = new FileReader();
|
|
||||||
var imageUrl;
|
|
||||||
var imageType = file.type;
|
|
||||||
var fileSize = data.hasOwnProperty('fileSize') && data.fileSize !== undefined ? parseInt(data.fileSize, 10) : false;
|
var fileSize = data.hasOwnProperty('fileSize') && data.fileSize !== undefined ? parseInt(data.fileSize, 10) : false;
|
||||||
if (fileSize && file.size > fileSize * 1024) {
|
if (fileSize && file.size > fileSize * 1024) {
|
||||||
return app.alertError('[[error:file-too-big, ' + fileSize + ']]');
|
return app.alertError('[[error:file-too-big, ' + fileSize + ']]');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (file.name.endsWith('.gif')) {
|
||||||
|
require(['uploader'], function (uploader) {
|
||||||
|
uploader.ajaxSubmit(data.uploadModal, callback);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var reader = new FileReader();
|
||||||
reader.addEventListener('load', function () {
|
reader.addEventListener('load', function () {
|
||||||
imageUrl = reader.result;
|
var imageUrl = reader.result;
|
||||||
|
|
||||||
data.uploadModal.modal('hide');
|
data.uploadModal.modal('hide');
|
||||||
|
|
||||||
module.handleImageCrop({
|
module.handleImageCrop({
|
||||||
url: imageUrl,
|
url: imageUrl,
|
||||||
imageType: imageType,
|
imageType: file.type,
|
||||||
socketMethod: data.socketMethod,
|
socketMethod: data.socketMethod,
|
||||||
aspectRatio: data.aspectRatio,
|
aspectRatio: data.aspectRatio,
|
||||||
allowSkippingCrop: data.allowSkippingCrop,
|
allowSkippingCrop: data.allowSkippingCrop,
|
||||||
|
|||||||
@@ -42,34 +42,38 @@ define('uploader', ['translator', 'benchpress'], function (translator, Benchpres
|
|||||||
};
|
};
|
||||||
|
|
||||||
function onSubmit(uploadModal, fileSize, callback) {
|
function onSubmit(uploadModal, fileSize, callback) {
|
||||||
function showAlert(type, message) {
|
showAlert(uploadModal, 'status', '[[uploads:uploading-file]]');
|
||||||
module.hideAlerts(uploadModal);
|
|
||||||
if (type === 'error') {
|
|
||||||
uploadModal.find('#fileUploadSubmitBtn').removeClass('disabled');
|
|
||||||
}
|
|
||||||
uploadModal.find('#alert-' + type).translateText(message).removeClass('hide');
|
|
||||||
}
|
|
||||||
|
|
||||||
showAlert('status', '[[uploads:uploading-file]]');
|
|
||||||
|
|
||||||
uploadModal.find('#upload-progress-bar').css('width', '0%');
|
uploadModal.find('#upload-progress-bar').css('width', '0%');
|
||||||
uploadModal.find('#upload-progress-box').show().removeClass('hide');
|
uploadModal.find('#upload-progress-box').show().removeClass('hide');
|
||||||
|
|
||||||
var fileInput = uploadModal.find('#fileInput');
|
var fileInput = uploadModal.find('#fileInput');
|
||||||
if (!fileInput.val()) {
|
if (!fileInput.val()) {
|
||||||
return showAlert('error', '[[uploads:select-file-to-upload]]');
|
return showAlert(uploadModal, 'error', '[[uploads:select-file-to-upload]]');
|
||||||
}
|
}
|
||||||
if (!hasValidFileSize(fileInput[0], fileSize)) {
|
if (!hasValidFileSize(fileInput[0], fileSize)) {
|
||||||
return showAlert('error', '[[error:file-too-big, ' + fileSize + ']]');
|
return showAlert(uploadModal, 'error', '[[error:file-too-big, ' + fileSize + ']]');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.ajaxSubmit(uploadModal, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
function showAlert(uploadModal, type, message) {
|
||||||
|
module.hideAlerts(uploadModal);
|
||||||
|
if (type === 'error') {
|
||||||
|
uploadModal.find('#fileUploadSubmitBtn').removeClass('disabled');
|
||||||
|
}
|
||||||
|
uploadModal.find('#alert-' + type).translateText(message).removeClass('hide');
|
||||||
|
}
|
||||||
|
|
||||||
|
module.ajaxSubmit = function (uploadModal, callback) {
|
||||||
uploadModal.find('#uploadForm').ajaxSubmit({
|
uploadModal.find('#uploadForm').ajaxSubmit({
|
||||||
headers: {
|
headers: {
|
||||||
'x-csrf-token': config.csrf_token,
|
'x-csrf-token': config.csrf_token,
|
||||||
},
|
},
|
||||||
error: function (xhr) {
|
error: function (xhr) {
|
||||||
xhr = maybeParse(xhr);
|
xhr = maybeParse(xhr);
|
||||||
showAlert('error', xhr.responseJSON ? (xhr.responseJSON.error || xhr.statusText) : 'error uploading, code : ' + xhr.status);
|
showAlert(uploadModal, 'error', xhr.responseJSON ? (xhr.responseJSON.error || xhr.statusText) : 'error uploading, code : ' + xhr.status);
|
||||||
},
|
},
|
||||||
uploadProgress: function (event, position, total, percent) {
|
uploadProgress: function (event, position, total, percent) {
|
||||||
uploadModal.find('#upload-progress-bar').css('width', percent + '%');
|
uploadModal.find('#upload-progress-bar').css('width', percent + '%');
|
||||||
@@ -78,19 +82,19 @@ define('uploader', ['translator', 'benchpress'], function (translator, Benchpres
|
|||||||
response = maybeParse(response);
|
response = maybeParse(response);
|
||||||
|
|
||||||
if (response.error) {
|
if (response.error) {
|
||||||
return showAlert('error', response.error);
|
return showAlert(uploadModal, 'error', response.error);
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(response[0].url);
|
callback(response[0].url);
|
||||||
|
|
||||||
showAlert('success', '[[uploads:upload-success]]');
|
showAlert(uploadModal, 'success', '[[uploads:upload-success]]');
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
module.hideAlerts(uploadModal);
|
module.hideAlerts(uploadModal);
|
||||||
uploadModal.modal('hide');
|
uploadModal.modal('hide');
|
||||||
}, 750);
|
}, 750);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
function parseModal(tplVals, callback) {
|
function parseModal(tplVals, callback) {
|
||||||
Benchpress.parse('partials/modals/upload_file_modal', tplVals, function (html) {
|
Benchpress.parse('partials/modals/upload_file_modal', tplVals, function (html) {
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ editController.get = async function (req, res, next) {
|
|||||||
userData.allowProfilePicture = !userData.isSelf || !!meta.config['reputation:disabled'] || userData.reputation >= meta.config['min:rep:profile-picture'];
|
userData.allowProfilePicture = !userData.isSelf || !!meta.config['reputation:disabled'] || userData.reputation >= meta.config['min:rep:profile-picture'];
|
||||||
userData.allowCoverPicture = !userData.isSelf || !!meta.config['reputation:disabled'] || userData.reputation >= meta.config['min:rep:cover-picture'];
|
userData.allowCoverPicture = !userData.isSelf || !!meta.config['reputation:disabled'] || userData.reputation >= meta.config['min:rep:cover-picture'];
|
||||||
userData.allowProfileImageUploads = meta.config.allowProfileImageUploads;
|
userData.allowProfileImageUploads = meta.config.allowProfileImageUploads;
|
||||||
|
userData.allowedProfileImageExtensios = user.getAllowedProfileImageExtensions().map(ext => '.' + ext).join(', ');
|
||||||
userData.allowMultipleBadges = meta.config.allowMultipleBadges === 1;
|
userData.allowMultipleBadges = meta.config.allowMultipleBadges === 1;
|
||||||
userData.allowAccountDelete = meta.config.allowAccountDelete === 1;
|
userData.allowAccountDelete = meta.config.allowAccountDelete === 1;
|
||||||
userData.allowWebsite = !userData.isSelf || !!meta.config['reputation:disabled'] || userData.reputation >= meta.config['min:rep:website'];
|
userData.allowWebsite = !userData.isSelf || !!meta.config['reputation:disabled'] || userData.reputation >= meta.config['min:rep:website'];
|
||||||
|
|||||||
@@ -1,14 +1,27 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const winston = require('winston');
|
const winston = require('winston');
|
||||||
|
const mime = require('mime');
|
||||||
|
|
||||||
const db = require('../database');
|
const db = require('../database');
|
||||||
const file = require('../file');
|
const file = require('../file');
|
||||||
const image = require('../image');
|
const image = require('../image');
|
||||||
const meta = require('../meta');
|
const meta = require('../meta');
|
||||||
|
const plugins = require('../plugins');
|
||||||
|
|
||||||
module.exports = function (User) {
|
module.exports = function (User) {
|
||||||
const allowedTypes = ['image/png', 'image/jpeg', 'image/bmp'];
|
User.getAllowedProfileImageExtensions = function () {
|
||||||
|
return User.getAllowedImageTypes().map(type => mime.getExtension(type));
|
||||||
|
};
|
||||||
|
|
||||||
|
User.getAllowedImageTypes = function () {
|
||||||
|
const allowedTypes = ['image/png', 'image/jpeg', 'image/bmp'];
|
||||||
|
if (plugins.hasListeners('filter:image.isFileTypeAllowed')) {
|
||||||
|
allowedTypes.push('image/gif');
|
||||||
|
}
|
||||||
|
return allowedTypes;
|
||||||
|
};
|
||||||
|
|
||||||
User.updateCoverPosition = async function (uid, position) {
|
User.updateCoverPosition = async function (uid, position) {
|
||||||
// Reject anything that isn't two percentages
|
// Reject anything that isn't two percentages
|
||||||
if (!/^[\d.]+%\s[\d.]+%$/.test(position)) {
|
if (!/^[\d.]+%\s[\d.]+%$/.test(position)) {
|
||||||
@@ -30,7 +43,7 @@ module.exports = function (User) {
|
|||||||
return await User.updateCoverPosition(data.uid, data.position);
|
return await User.updateCoverPosition(data.uid, data.position);
|
||||||
}
|
}
|
||||||
|
|
||||||
validateUpload(data, meta.config.maximumCoverImageSize);
|
validateUpload(data, meta.config.maximumCoverImageSize, ['image/png', 'image/jpeg', 'image/bmp']);
|
||||||
|
|
||||||
picture.path = await getTempPath(data);
|
picture.path = await getTempPath(data);
|
||||||
|
|
||||||
@@ -63,7 +76,7 @@ module.exports = function (User) {
|
|||||||
throw new Error('[[error:profile-image-uploads-disabled]]');
|
throw new Error('[[error:profile-image-uploads-disabled]]');
|
||||||
}
|
}
|
||||||
|
|
||||||
validateUpload(data, meta.config.maximumProfileImageSize);
|
validateUpload(data, meta.config.maximumProfileImageSize, User.getAllowedImageTypes());
|
||||||
|
|
||||||
const extension = file.typeToExtension(getMimeType(data));
|
const extension = file.typeToExtension(getMimeType(data));
|
||||||
if (!extension) {
|
if (!extension) {
|
||||||
@@ -92,7 +105,7 @@ module.exports = function (User) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function validateUpload(data, maxSize) {
|
function validateUpload(data, maxSize, allowedTypes) {
|
||||||
if (!data.imageData && !data.file) {
|
if (!data.imageData && !data.file) {
|
||||||
throw new Error('[[error:invalid-data]]');
|
throw new Error('[[error:invalid-data]]');
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user