mirror of
https://github.com/opensupports/opensupports.git
synced 2025-05-03 06:10:56 +02:00
Add image file size validation
This commit is contained in:
parent
4df3bab1ff
commit
285b62832a
@ -1,17 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var babel = require('babel-core');
|
||||
|
||||
module.exports = {
|
||||
process: function(src, filename) {
|
||||
// Ignore files other than .js, .es, .jsx or .es6
|
||||
if (!babel.canCompile(filename)) {
|
||||
return '';
|
||||
}
|
||||
// Ignore all files within node_modules
|
||||
if (filename.indexOf('node_modules') === -1) {
|
||||
return babel.transform(src, {filename: filename}).code;
|
||||
}
|
||||
return src;
|
||||
}
|
||||
};
|
@ -1,13 +1,11 @@
|
||||
// MOCKS
|
||||
const ValidationFactoryMock = require('lib-app/__mocks__/validations/validation-factory-mock');
|
||||
const TextEditorMock = require('core-components/__mocks__/text-editor-mock');
|
||||
const FormField = ReactMock();
|
||||
|
||||
// COMPONENT
|
||||
const Form = requireUnit('core-components/form', {
|
||||
'lib-app/validations/validator-factory': ValidationFactoryMock,
|
||||
'core-components/form-field': FormField,
|
||||
'core-components/text-editor': TextEditorMock
|
||||
});
|
||||
|
||||
describe('Form component', function () {
|
||||
@ -187,18 +185,6 @@ describe('Form component', function () {
|
||||
expect(form.props.onSubmit).to.not.have.been.called;
|
||||
});
|
||||
|
||||
it('should transform TextEdit value to HTML', function () {
|
||||
form.state.form.first = TextEditorMock.createEmpty();
|
||||
|
||||
TestUtils.Simulate.submit(ReactDOM.findDOMNode(form));
|
||||
expect(TextEditorMock.getHTMLFromEditorState).to.have.been.calledWith(form.state.form.first);
|
||||
expect(form.props.onSubmit).to.have.been.calledWith({
|
||||
first: 'HTML_CODE',
|
||||
second: 'value2',
|
||||
third: 'value3'
|
||||
});
|
||||
});
|
||||
|
||||
it('should focus the first field with error', function () {
|
||||
ValidationFactoryMock.validators.defaultValidatorMock.performValidation = stub().returns('MOCK_ERROR');
|
||||
ValidationFactoryMock.validators.customValidatorMock.performValidation = stub().returns('MOCK_ERROR_2');
|
||||
|
@ -6,7 +6,6 @@ import {reactDFS, renderChildrenWithProps} from 'lib-core/react-dfs';
|
||||
import ValidationFactory from 'lib-app/validations/validator-factory';
|
||||
|
||||
import FormField from 'core-components/form-field';
|
||||
import TextEditor from 'core-components/text-editor';
|
||||
|
||||
class Form extends React.Component {
|
||||
|
||||
|
@ -21,7 +21,7 @@ module.exports = [
|
||||
'session-prefix': 'opensupports-z6ctpq2winvfhchX2_',
|
||||
'maintenance-mode': false,
|
||||
'allow-attachments': true,
|
||||
'max-size': 500,
|
||||
'max-size': 1,
|
||||
'departments': [
|
||||
{id: 1, name: 'Sales Support', owners: 2},
|
||||
{id: 2, name: 'Technical Issues', owners: 5},
|
||||
|
@ -321,6 +321,7 @@ export default {
|
||||
'INVALID_EMAIL_OR_TICKET_NUMBER': 'Número de e-mail ou chamado inválido',
|
||||
'INVALID_FILE': 'arquivo inválido',
|
||||
'ERRORS_FOUND': 'Erros encontrados',
|
||||
'ERROR_IMAGE_SIZE': 'Nenhuma imagem pode ter um tamanho maior que {size} MB',
|
||||
|
||||
//MESSAGES
|
||||
'SIGNUP_SUCCESS': 'Você se registrou com sucesso em nosso sistema de suporte.',
|
||||
|
@ -321,6 +321,7 @@ export default {
|
||||
'INVALID_EMAIL_OR_TICKET_NUMBER': '電子郵件或機票號無效',
|
||||
'INVALID_FILE': '無效文件',
|
||||
'ERRORS_FOUND': '發現錯誤',
|
||||
'ERROR_IMAGE_SIZE': '没有图像的大小可以超过{size}MB',
|
||||
|
||||
//MESSAGES
|
||||
'SIGNUP_SUCCESS': '您已在我們的支持系統中成功註冊',
|
||||
|
@ -321,6 +321,7 @@ export default {
|
||||
'INVALID_EMAIL_OR_TICKET_NUMBER': 'Ungültige E-Mail-Adresse oder Ticketnummer!',
|
||||
'INVALID_FILE': 'Ungültige Datei!',
|
||||
'ERRORS_FOUND': 'Fehler gefunden!',
|
||||
'ERROR_IMAGE_SIZE': 'Kein Bild darf größer als {size} MB sein',
|
||||
|
||||
//MESSAGES
|
||||
'SIGNUP_SUCCESS': 'Sie haben sich erfolgreich in unserem Support-System registriert.',
|
||||
|
@ -322,6 +322,7 @@ export default {
|
||||
'INVALID_EMAIL_OR_TICKET_NUMBER': 'Invalid email or ticket number',
|
||||
'INVALID_FILE': 'Invalid file',
|
||||
'ERRORS_FOUND': 'Errors found',
|
||||
'ERROR_IMAGE_SIZE': 'No image can have a size greater than {size} MB',
|
||||
|
||||
//MESSAGES
|
||||
'SIGNUP_SUCCESS': 'You have registered successfully in our support system.',
|
||||
|
@ -346,6 +346,7 @@ export default {
|
||||
'WILL_RECOVER_EMAIL_TEMPLATE': 'Esta plantilla de correo electrónico se recuperará a su valor predeterminado en este idioma.',
|
||||
'SUCCESS_IMPORTING_CSV_DESCRIPTION': 'El archivo CSV se ha importado correctamente',
|
||||
'SUCCESS_DELETING_ALL_USERS': 'Los usuarios se han eliminado correctamente',
|
||||
'ERROR_IMAGE_SIZE': 'Ninguna imagen puede tener un tamaño superior a {size} MB',
|
||||
|
||||
'LAST_7_DAYS': 'Últimos 7 dias',
|
||||
'LAST_30_DAYS': 'Últimos 30 dias',
|
||||
|
@ -321,6 +321,7 @@ export default {
|
||||
'INVALID_EMAIL_OR_TICKET_NUMBER': 'Numéro de courriel ou de ticket invalide',
|
||||
'INVALID_FILE': 'Fichier invalide',
|
||||
'ERRORS_FOUND': 'Des erreurs sont survenues',
|
||||
'ERROR_IMAGE_SIZE': 'Aucune image ne peut avoir une taille supérieure à {size} MB',
|
||||
|
||||
//MESSAGES
|
||||
'SIGNUP_SUCCESS': 'Vous êtes inscrit avec succès dans notre système de support.',
|
||||
|
@ -322,6 +322,7 @@
|
||||
'INVALID_EMAIL_OR_TICKET_NUMBER': 'Μη έγκυρη ηλεκτρονική διεύθυνση ή αριθμός εισιτηρίου',
|
||||
'INVALID_FILE': 'Μη έγκυρο αρχείο',
|
||||
'ERRORS_FOUND': 'Βρέθηκαν Σφάλματα',
|
||||
'ERROR_IMAGE_SIZE': 'Καμία εικόνα δεν μπορεί να έχει μέγεθος μεγαλύτερο από {size} MB',
|
||||
|
||||
//MESSAGES
|
||||
'SIGNUP_SUCCESS': 'Έχετε εγγραφεί με επιτυχία στο σύστημα υποστήριξης μας.',
|
||||
|
@ -321,6 +321,7 @@ export default {
|
||||
'INVALID_EMAIL_OR_TICKET_NUMBER': 'अमान्य ईमेल या टिकट नंबर',
|
||||
'INVALID_FILE': 'अवैध फाइल',
|
||||
'ERRORS_FOUND': 'त्रुटियां मिलीं',
|
||||
'ERROR_IMAGE_SIZE': 'कोई छवि {size} एमबी से अधिक आकार नहीं हो सकती है',
|
||||
|
||||
//MESSAGES
|
||||
'SIGNUP_SUCCESS': 'आप हमारे समर्थन प्रणाली में सफलतापूर्वक दर्ज कर लिया है।',
|
||||
|
@ -321,6 +321,7 @@ export default {
|
||||
'INVALID_EMAIL_OR_TICKET_NUMBER': 'E-mail o numero di ticket non validi',
|
||||
'INVALID_FILE': 'File non valido',
|
||||
'ERRORS_FOUND': 'Trovati errori',
|
||||
'ERROR_IMAGE_SIZE': 'Nessuna immagine può avere una dimensione superiore a {size} MB',
|
||||
|
||||
//MESSAGES
|
||||
'SIGNUP_SUCCESS': 'È stato registrato con successo nel nostro sistema di supporto.',
|
||||
|
@ -321,6 +321,7 @@ export default {
|
||||
'INVALID_EMAIL_OR_TICKET_NUMBER': '電子メールまたはチケット番号が無効です',
|
||||
'INVALID_FILE': '無効なファイル',
|
||||
'ERRORS_FOUND': 'エラーが見つかりました',
|
||||
'ERROR_IMAGE_SIZE': 'イメージのサイズが{size} MBを超えることはできません',
|
||||
|
||||
//MESSAGES
|
||||
'SIGNUP_SUCCESS': 'あなたは私たちのサポートシステムに正常に登録しました。',
|
||||
|
@ -322,6 +322,7 @@ export default {
|
||||
'INVALID_EMAIL_OR_TICKET_NUMBER': 'Ongeldig e-mailadres of incidentnummer',
|
||||
'INVALID_FILE': 'Ongeldig bestand',
|
||||
'ERRORS_FOUND': 'Er is een fout opgetreden',
|
||||
'ERROR_IMAGE_SIZE': 'Geen enkele afbeelding kan groter zijn dan {size} MB',
|
||||
|
||||
//MESSAGES
|
||||
'SIGNUP_SUCCESS': 'U hebt zich succesvol geregistreerd in ons ondersteuningssysteem.',
|
||||
|
@ -321,6 +321,7 @@ export default {
|
||||
'INVALID_EMAIL_OR_TICKET_NUMBER': 'Número de e-mail ou bilhete inválido',
|
||||
'INVALID_FILE': 'arquivo inválido',
|
||||
'ERRORS_FOUND': 'Erros encontrados',
|
||||
'ERROR_IMAGE_SIZE': 'Nenhuma imagem pode ter um tamanho maior que {size} MB',
|
||||
|
||||
//MESSAGES
|
||||
'SIGNUP_SUCCESS': 'Você se registrou com sucesso em nosso sistema de suporte.',
|
||||
|
@ -320,6 +320,7 @@ export default {
|
||||
'INVALID_EMAIL_OR_TICKET_NUMBER': 'Неправильный номер эл. Почты или номера билета.',
|
||||
'INVALID_FILE': 'неверный файл',
|
||||
'ERRORS_FOUND': 'Ошибки найдены',
|
||||
'ERROR_IMAGE_SIZE': 'Изображение не может иметь размер больше {size} МБ',
|
||||
|
||||
//MESSAGES
|
||||
'SIGNUP_SUCCESS': 'Вы успешно зарегистрировались в нашей системе поддержки.',
|
||||
|
@ -321,6 +321,7 @@ export default {
|
||||
'INVALID_EMAIL_OR_TICKET_NUMBER': 'Geçersiz e-posta veya bilet numarası',
|
||||
'INVALID_FILE': 'geçersiz dosya',
|
||||
'ERRORS_FOUND': 'Hatalar bulundu',
|
||||
'ERROR_IMAGE_SIZE': 'Hiçbir resmin boyutu {size} MB\'den büyük olabilir',
|
||||
|
||||
//MESSAGES
|
||||
'SIGNUP_SUCCESS': 'Destek sistemimize başarılı bir şekilde kayıt oldunuz.',
|
||||
|
@ -61,6 +61,7 @@ class SessionStore {
|
||||
this.setItem('user-system-enabled', configs['user-system-enabled']);
|
||||
this.setItem('allow-attachments', configs['allow-attachments']);
|
||||
this.setItem('maintenance-mode', configs['maintenance-mode']);
|
||||
this.setItem('max-size', configs['max-size']);
|
||||
}
|
||||
|
||||
getConfigs() {
|
||||
@ -75,7 +76,8 @@ class SessionStore {
|
||||
registration: (this.getItem('registration') * 1),
|
||||
'user-system-enabled': (this.getItem('user-system-enabled') * 1),
|
||||
'allow-attachments': (this.getItem('allow-attachments') * 1),
|
||||
'maintenance-mode': (this.getItem('maintenance-mode') * 1)
|
||||
'maintenance-mode': (this.getItem('maintenance-mode') * 1),
|
||||
'max-size': this.getItem('max-size'),
|
||||
};
|
||||
}
|
||||
|
||||
|
24
client/src/lib-app/validations/image-size-validator.js
Normal file
24
client/src/lib-app/validations/image-size-validator.js
Normal file
@ -0,0 +1,24 @@
|
||||
import _ from 'lodash';
|
||||
|
||||
import Validator from 'lib-app/validations/validator';
|
||||
import SessionStore from 'lib-app/session-store';
|
||||
import Base64ImageParser from 'lib-core/base64-image-parser';
|
||||
|
||||
class ImageSizeValidator extends Validator {
|
||||
constructor(errorKey = 'ERROR_IMAGE_SIZE', validator = null) {
|
||||
super(validator);
|
||||
|
||||
this.maxSize = 1;
|
||||
this.errorKey = errorKey;
|
||||
}
|
||||
|
||||
validate(value = '', form = {}) {
|
||||
let images = Base64ImageParser.getImagesSrc(value).map(Base64ImageParser.dataURLtoFile);
|
||||
|
||||
if(_.some(images, f => f.size > 1048576 * SessionStore.getItem('max-size'))) {
|
||||
return this.getError(this.errorKey, {size: SessionStore.getItem('max-size')});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default ImageSizeValidator;
|
@ -1,5 +1,3 @@
|
||||
import TextEditor from 'core-components/text-editor';
|
||||
|
||||
import Validator from 'lib-app/validations/validator';
|
||||
|
||||
class LengthValidator extends Validator {
|
||||
@ -11,11 +9,11 @@ class LengthValidator extends Validator {
|
||||
}
|
||||
|
||||
validate(value = '', form = {}) {
|
||||
if (TextEditor.isEditorState(value)) {
|
||||
value = value.getCurrentContent().getPlainText();
|
||||
}
|
||||
let div = document.createElement("div");
|
||||
div.innerHTML = value;
|
||||
let text = div.textContent || div.innerText || "";
|
||||
|
||||
if (value.length < this.minlength) return this.getError(this.errorKey);
|
||||
if (text.length < this.minlength) return this.getError(this.errorKey);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,13 +3,14 @@ import EmailValidator from 'lib-app/validations/email-validator';
|
||||
import RepeatPasswordValidator from 'lib-app/validations/repeat-password-validator';
|
||||
import LengthValidator from 'lib-app/validations/length-validator';
|
||||
import ListValidator from 'lib-app/validations/list-validator';
|
||||
import ImageSizeValidator from 'lib-app/validations/image-size-validator';
|
||||
|
||||
let validators = {
|
||||
'DEFAULT': new Validator(),
|
||||
'NAME': new LengthValidator(2, 'ERROR_NAME'),
|
||||
'TITLE': new LengthValidator(1, 'ERROR_TITLE'),
|
||||
'EMAIL': new EmailValidator(),
|
||||
'TEXT_AREA': new LengthValidator(10, 'ERROR_CONTENT_SHORT'),
|
||||
'TEXT_AREA': new ImageSizeValidator(undefined, new LengthValidator(10, 'ERROR_CONTENT_SHORT')),
|
||||
'PASSWORD': new LengthValidator(6, 'ERROR_PASSWORD'),
|
||||
'REPEAT_PASSWORD': new RepeatPasswordValidator(),
|
||||
'URL': new LengthValidator(5, 'ERROR_URL'),
|
||||
|
@ -27,8 +27,8 @@ class Validator {
|
||||
if (value.length === 0) return this.getError('ERROR_EMPTY');
|
||||
}
|
||||
|
||||
getError(errorKey) {
|
||||
return i18n(errorKey);
|
||||
getError(errorKey, params) {
|
||||
return i18n(errorKey, params);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@ var jsdom = require('jsdom').jsdom;
|
||||
|
||||
global.document = jsdom('<html><body></body></html>');
|
||||
global.window = document.defaultView;
|
||||
global.Node = global.window.Node;
|
||||
global.navigator = {
|
||||
userAgent: 'node.js'
|
||||
};
|
||||
|
@ -77,7 +77,7 @@ class InitSettingsController extends Controller {
|
||||
'maintenance-mode' => 0,
|
||||
'layout' => 'boxed',
|
||||
'allow-attachments' => !!Controller::request('allow-attachments'),
|
||||
'max-size' => 1024,
|
||||
'max-size' => 1,
|
||||
'title' => Controller::request('title') ? Controller::request('title') : 'Support Center',
|
||||
'url' => Controller::request('url') ? Controller::request('url') : ('http://' . $_SERVER['HTTP_HOST']),
|
||||
'registration' => !!Controller::request('registration'),
|
||||
|
@ -109,6 +109,14 @@ abstract class Controller {
|
||||
$fileUploader = FileUploader::getInstance();
|
||||
$fileUploader->setMaxSize($maxSize);
|
||||
|
||||
$allImagesValidSize = true;
|
||||
|
||||
for($i=0;$i<$totalImages;$i++) {
|
||||
$allImagesValidSize = $allImagesValidSize && $fileUploader->isSizeValid($_FILES["image_$i"]);
|
||||
}
|
||||
|
||||
if(!$allImagesValidSize) throw new Exception(ERRORS::INVALID_FILE);
|
||||
|
||||
$imagePaths = [];
|
||||
$url = Setting::getSetting('url')->getValue();
|
||||
for($i=0;$i<$totalImages;$i++) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
class FileUploader extends FileManager {
|
||||
private $maxSize = 1024;
|
||||
private $maxSize = 1;
|
||||
private $linearCongruentialGenerator;
|
||||
private $linearCongruentialGeneratorOffset;
|
||||
private $fileName;
|
||||
@ -19,10 +19,14 @@ class FileUploader extends FileManager {
|
||||
|
||||
private function __construct() {}
|
||||
|
||||
public function isSizeValid($file) {
|
||||
return $file['size'] <= (1048576 * $this->maxSize);
|
||||
}
|
||||
|
||||
public function upload($file) {
|
||||
$this->setNewName($file['name']);
|
||||
|
||||
if($file['size'] > (1024 * $this->maxSize)) {
|
||||
if(!$this->isSizeValid($file)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@ describe'system/edit-settings' do
|
||||
"time-zone" => -3,
|
||||
"layout" => 'full-width',
|
||||
"allow-attachments" => 1,
|
||||
"max-size" => 2048,
|
||||
"max-size" => 2,
|
||||
"language" => 'en',
|
||||
"no-reply-email" => 'testemail@hotmail.com'
|
||||
})
|
||||
@ -27,7 +27,7 @@ describe'system/edit-settings' do
|
||||
(row['value']).should.equal('full-width')
|
||||
|
||||
row = $database.getRow('setting', 'max-size', 'name')
|
||||
(row['value']).should.equal('2048')
|
||||
(row['value']).should.equal('2')
|
||||
|
||||
row = $database.getRow('setting', 'language', 'name')
|
||||
(row['value']).should.equal('en')
|
||||
|
Loading…
x
Reference in New Issue
Block a user