Change dynamic dependency of FileUpload in Messages models (#13776)

* Change dynamic dependency of FileUpload in Messages models

* Move require to top

* Fix lint

* Move file upload from lib to server only

* Fix wrong import
pull/14022/head
Marcos Spessatto Defendi 7 years ago committed by Rodrigo Nascimento
parent 40fed25a48
commit 7bf6f3b62d
  1. 2
      app/authorization/server/functions/canAccessRoom.js
  2. 3
      app/authorization/server/functions/hasPermission.js
  3. 7
      app/file-upload/client/lib/fileUploadHandler.js
  4. 61
      app/file-upload/lib/FileUpload.js
  5. 1
      app/file-upload/lib/FileUploadBase.js
  6. 103
      app/file-upload/server/lib/FileUpload.js
  7. 7
      app/models/server/models/Messages.js
  8. 2
      app/settings/server/functions/settings.js
  9. 11
      app/utils/lib/RoomTypeConfig.js

@ -1,5 +1,5 @@
import { settings } from '../../../settings';
import { Subscriptions } from '../../../models';
import Subscriptions from '../../../models/server/models/Subscriptions';
import { hasPermission } from './hasPermission';
export const roomAccessValidators = [

@ -1,4 +1,5 @@
import { Roles, Permissions } from '../../../models';
import Roles from '../../../models/server/models/Roles';
import Permissions from '../../../models/server/models/Permissions';
function atLeastOne(userId, permissions = [], scope) {
return permissions.some((permissionId) => {

@ -4,22 +4,15 @@ import { Tracker } from 'meteor/tracker';
import { UploadFS } from 'meteor/jalik:ufs';
import { FileUploadBase } from '../../lib/FileUploadBase';
import { Uploads, Avatars } from '../../../models';
import { FileUpload } from '../../lib/FileUpload';
new UploadFS.Store({
collection: Uploads.model,
name: 'Uploads',
filter: new UploadFS.Filter({
onCheck: FileUpload.validateFileUpload,
}),
});
new UploadFS.Store({
collection: Avatars.model,
name: 'Avatars',
filter: new UploadFS.Filter({
onCheck: FileUpload.validateFileUpload,
}),
});
export const fileUploadHandler = (directive, meta, file) => {

@ -1,61 +0,0 @@
import { Meteor } from 'meteor/meteor';
import { Match } from 'meteor/check';
import { TAPi18n } from 'meteor/tap:i18n';
import { Rooms, Settings } from '../../models';
import { settings } from '../../settings';
import { fileUploadIsValidContentType } from '../../utils';
import { canAccessRoom } from '../../authorization';
import filesize from 'filesize';
let maxFileSize = 0;
export const FileUpload = {
validateFileUpload(file) {
if (!Match.test(file.rid, String)) {
return false;
}
// livechat users can upload files but they don't have an userId
const user = file.userId ? Meteor.users.findOne(file.userId) : null;
const room = Rooms.findOneById(file.rid);
const directMessageAllow = settings.get('FileUpload_Enabled_Direct');
const fileUploadAllowed = settings.get('FileUpload_Enabled');
if (canAccessRoom(room, user, file) !== true) {
return false;
}
const language = user ? user.language : 'en';
if (!fileUploadAllowed) {
const reason = TAPi18n.__('FileUpload_Disabled', language);
throw new Meteor.Error('error-file-upload-disabled', reason);
}
if (!directMessageAllow && room.t === 'd') {
const reason = TAPi18n.__('File_not_allowed_direct_messages', language);
throw new Meteor.Error('error-direct-message-file-upload-not-allowed', reason);
}
// -1 maxFileSize means there is no limit
if (maxFileSize > -1 && file.size > maxFileSize) {
const reason = TAPi18n.__('File_exceeds_allowed_size_of_bytes', {
size: filesize(maxFileSize),
}, language);
throw new Meteor.Error('error-file-too-large', reason);
}
if (!fileUploadIsValidContentType(file.type)) {
const reason = TAPi18n.__('File_type_is_not_accepted', language);
throw new Meteor.Error('error-invalid-file-type', reason);
}
return true;
},
};
settings.get('FileUpload_MaxFileSize', function(key, value) {
try {
maxFileSize = parseInt(value);
} catch (e) {
maxFileSize = Settings.findOneById('FileUpload_MaxFileSize').packageValue;
}
});

@ -35,7 +35,6 @@ UploadFS.config.defaultStorePermissions = new UploadFS.StorePermissions({
},
});
export class FileUploadBase {
constructor(store, meta, file) {
this.id = Random.id();

@ -7,15 +7,34 @@ import Future from 'fibers/future';
import sharp from 'sharp';
import { Cookies } from 'meteor/ostrio:cookies';
import { UploadFS } from 'meteor/jalik:ufs';
import { Match } from 'meteor/check';
import { TAPi18n } from 'meteor/tap:i18n';
import { settings } from '../../../settings';
import * as Models from '../../../models';
import { FileUpload as _FileUpload } from '../../lib/FileUpload';
import { roomTypes } from '../../../utils';
import { hasPermission } from '../../../authorization';
import Uploads from '../../../models/server/models/Uploads';
import UserDataFiles from '../../../models/server/models/UserDataFiles';
import Avatars from '../../../models/server/models/Avatars';
import Users from '../../../models/server/models/Users';
import Rooms from '../../../models/server/models/Rooms';
import Settings from '../../../models/server/models/Settings';
import { roomTypes } from '../../../utils/server/lib/roomTypes';
import { hasPermission } from '../../../authorization/server/functions/hasPermission';
import { canAccessRoom } from '../../../authorization/server/functions/canAccessRoom';
import { fileUploadIsValidContentType } from '../../../utils/lib/fileUploadRestrictions';
import filesize from 'filesize';
const cookie = new Cookies();
let maxFileSize = 0;
export const FileUpload = Object.assign(_FileUpload, {
settings.get('FileUpload_MaxFileSize', function(key, value) {
try {
maxFileSize = parseInt(value);
} catch (e) {
maxFileSize = Settings.findOneById('FileUpload_MaxFileSize').packageValue;
}
});
export const FileUpload = {
handlers: {},
configureUploadsStore(store, name, options) {
@ -28,9 +47,50 @@ export const FileUpload = Object.assign(_FileUpload, {
}, options, FileUpload[`default${ type }`]()));
},
validateFileUpload(file) {
if (!Match.test(file.rid, String)) {
return false;
}
// livechat users can upload files but they don't have an userId
const user = file.userId ? Meteor.users.findOne(file.userId) : null;
const room = Rooms.findOneById(file.rid);
const directMessageAllow = settings.get('FileUpload_Enabled_Direct');
const fileUploadAllowed = settings.get('FileUpload_Enabled');
if (canAccessRoom(room, user, file) !== true) {
return false;
}
const language = user ? user.language : 'en';
if (!fileUploadAllowed) {
const reason = TAPi18n.__('FileUpload_Disabled', language);
throw new Meteor.Error('error-file-upload-disabled', reason);
}
if (!directMessageAllow && room.t === 'd') {
const reason = TAPi18n.__('File_not_allowed_direct_messages', language);
throw new Meteor.Error('error-direct-message-file-upload-not-allowed', reason);
}
// -1 maxFileSize means there is no limit
if (maxFileSize > -1 && file.size > maxFileSize) {
const reason = TAPi18n.__('File_exceeds_allowed_size_of_bytes', {
size: filesize(maxFileSize),
}, language);
throw new Meteor.Error('error-file-too-large', reason);
}
if (!fileUploadIsValidContentType(file.type)) {
const reason = TAPi18n.__('File_type_is_not_accepted', language);
throw new Meteor.Error('error-invalid-file-type', reason);
}
return true;
},
defaultUploads() {
return {
collection: Models.Uploads.model,
collection: Uploads.model,
filter: new UploadFS.Filter({
onCheck: FileUpload.validateFileUpload,
}),
@ -52,7 +112,7 @@ export const FileUpload = Object.assign(_FileUpload, {
defaultAvatars() {
return {
collection: Models.Avatars.model,
collection: Avatars.model,
// filter: new UploadFS.Filter({
// onCheck: FileUpload.validateFileUpload
// }),
@ -66,7 +126,7 @@ export const FileUpload = Object.assign(_FileUpload, {
defaultUserDataFiles() {
return {
collection: Models.UserDataFiles.model,
collection: UserDataFiles.model,
getPath(file) {
return `${ settings.get('uniqueID') }/uploads/userData/${ file.userId }`;
},
@ -140,7 +200,7 @@ export const FileUpload = Object.assign(_FileUpload, {
},
resizeImagePreview(file) {
file = Models.Uploads.findOneById(file._id);
file = Uploads.findOneById(file._id);
file = FileUpload.addExtensionTo(file);
const image = FileUpload.getStore('Uploads')._store.getReadStream(file._id, file);
@ -215,12 +275,12 @@ export const FileUpload = Object.assign(_FileUpload, {
throw new Meteor.Error('error-not-allowed', 'Change avatar is not allowed');
}
// update file record to match user's username
const user = Models.Users.findOneById(file.userId);
const oldAvatar = Models.Avatars.findOneByName(user.username);
const user = Users.findOneById(file.userId);
const oldAvatar = Avatars.findOneByName(user.username);
if (oldAvatar) {
Models.Avatars.deleteFile(oldAvatar._id);
Avatars.deleteFile(oldAvatar._id);
}
Models.Avatars.updateFileNameById(file._id, user.username);
Avatars.updateFileNameById(file._id, user.username);
// console.log('upload finished ->', file);
},
@ -238,8 +298,8 @@ export const FileUpload = Object.assign(_FileUpload, {
rc_room_type = cookie.get('rc_room_type', headers.cookie);
}
const isAuthorizedByCookies = rc_uid && rc_token && Models.Users.findOneByIdAndLoginToken(rc_uid, rc_token);
const isAuthorizedByHeaders = headers['x-user-id'] && headers['x-auth-token'] && Models.Users.findOneByIdAndLoginToken(headers['x-user-id'], headers['x-auth-token']);
const isAuthorizedByCookies = rc_uid && rc_token && Users.findOneByIdAndLoginToken(rc_uid, rc_token);
const isAuthorizedByHeaders = headers['x-user-id'] && headers['x-auth-token'] && Users.findOneByIdAndLoginToken(headers['x-user-id'], headers['x-auth-token']);
const isAuthorizedByRoom = rc_room_type && roomTypes.getConfig(rc_room_type).canAccessUploadedFile({ rc_uid, rc_rid, rc_token });
return isAuthorizedByCookies || isAuthorizedByHeaders || isAuthorizedByRoom;
},
@ -311,7 +371,7 @@ export const FileUpload = Object.assign(_FileUpload, {
return false;
},
});
};
export class FileUploadClass {
constructor({ name, model, store, get, insert, getStore, copy }) {
@ -345,7 +405,16 @@ export class FileUploadClass {
}
getModelFromName() {
return Models[this.name.split(':')[1]];
const modelsAvailable = {
Avatars,
Uploads,
UserDataFiles,
};
const modelName = this.name.split(':')[1];
if (!modelsAvailable[modelName]) {
throw new Error('Invalid Model for FileUpload');
}
return modelsAvailable[modelName];
}
delete(fileId) {

@ -4,6 +4,7 @@ import { Base } from './_Base';
import Rooms from './Rooms';
import Users from './Users';
import { settings } from '../../../settings/server/functions/settings';
import { FileUpload } from '../../../file-upload/server/lib/FileUpload';
import _ from 'underscore';
export class Messages extends Base {
@ -903,10 +904,6 @@ export class Messages extends Base {
}
async removeFilesByRoomId(roomId) {
if (!this.FileUpload) {
const { FileUpload } = await import('../../../file-upload');
this.FileUpload = FileUpload;
}
this.find({
rid: roomId,
'file._id': {
@ -916,7 +913,7 @@ export class Messages extends Base {
fields: {
'file._id': 1,
},
}).fetch().forEach((document) => this.FileUpload.getStore('Uploads').deleteById(document.file._id));
}).fetch().forEach((document) => FileUpload.getStore('Uploads').deleteById(document.file._id));
}
getMessageByFileId(fileID) {

@ -1,6 +1,6 @@
import { Meteor } from 'meteor/meteor';
import { settings } from '../../lib/settings';
import { Settings } from '../../../models';
import Settings from '../../../models/server/models/Settings';
import _ from 'underscore';
const blockedSettings = {};

@ -1,8 +1,12 @@
import { Meteor } from 'meteor/meteor';
import { Random } from 'meteor/random';
import { Users } from '../../models';
import { settings } from '../../settings';
let Users;
if (Meteor.isServer) {
Users = require('../../models/server/models/Users').default;
}
export const RoomSettingsEnum = {
NAME: 'roomName',
TOPIC: 'roomTopic',
@ -232,7 +236,10 @@ export class RoomTypeConfig {
* @return {object} Sender's object from db
*/
getMsgSender(senderId) {
return Meteor.isServer ? Users.findOneById(senderId) : {};
if (Meteor.isServer && Users) {
return Users.findOneById(senderId);
}
return {};
}
/**

Loading…
Cancel
Save