mirror of https://github.com/wekan/wekan
parent
75d524f615
commit
3b936ff6e7
@ -1,118 +0,0 @@ |
||||
import { ReactiveCache } from '/imports/reactiveCache'; |
||||
|
||||
const storeName = 'attachments'; |
||||
const defaultStoreOptions = { |
||||
beforeWrite: fileObj => { |
||||
if (!fileObj.isImage()) { |
||||
return { |
||||
type: 'application/octet-stream', |
||||
}; |
||||
} |
||||
return {}; |
||||
}, |
||||
}; |
||||
let store; |
||||
store = new FS.Store.GridFS(storeName, { |
||||
// XXX Add a new store for cover thumbnails so we don't load big images in
|
||||
// the general board view
|
||||
// If the uploaded document is not an image we need to enforce browser
|
||||
// download instead of execution. This is particularly important for HTML
|
||||
// files that the browser will just execute if we don't serve them with the
|
||||
// appropriate `application/octet-stream` MIME header which can lead to user
|
||||
// data leaks. I imagine other formats (like PDF) can also be attack vectors.
|
||||
// See https://github.com/wekan/wekan/issues/99
|
||||
// XXX Should we use `beforeWrite` option of CollectionFS instead of
|
||||
// collection-hooks?
|
||||
// We should use `beforeWrite`.
|
||||
...defaultStoreOptions, |
||||
}); |
||||
AttachmentsOld = new FS.Collection('attachments', { |
||||
stores: [store], |
||||
}); |
||||
|
||||
if (Meteor.isServer) { |
||||
Meteor.startup(() => { |
||||
AttachmentsOld.files._ensureIndex({ cardId: 1 }); |
||||
}); |
||||
|
||||
AttachmentsOld.allow({ |
||||
insert(userId, doc) { |
||||
return allowIsBoardMember(userId, ReactiveCache.getBoard(doc.boardId)); |
||||
}, |
||||
update(userId, doc) { |
||||
return allowIsBoardMember(userId, ReactiveCache.getBoard(doc.boardId)); |
||||
}, |
||||
remove(userId, doc) { |
||||
return allowIsBoardMember(userId, ReactiveCache.getBoard(doc.boardId)); |
||||
}, |
||||
// We authorize the attachment download either:
|
||||
// - if the board is public, everyone (even unconnected) can download it
|
||||
// - if the board is private, only board members can download it
|
||||
download(userId, doc) { |
||||
const board = ReactiveCache.getBoard(doc.boardId); |
||||
if (board.isPublic()) { |
||||
return true; |
||||
} else { |
||||
return board.hasMember(userId); |
||||
} |
||||
}, |
||||
|
||||
fetch: ['boardId'], |
||||
}); |
||||
} |
||||
|
||||
// XXX Enforce a schema for the AttachmentsOld CollectionFS
|
||||
|
||||
if (Meteor.isServer) { |
||||
AttachmentsOld.files.after.insert((userId, doc) => { |
||||
// If the attachment doesn't have a source field
|
||||
// or its source is different than import
|
||||
if (!doc.source || doc.source !== 'import') { |
||||
// Add activity about adding the attachment
|
||||
Activities.insert({ |
||||
userId, |
||||
type: 'card', |
||||
activityType: 'addAttachment', |
||||
attachmentId: doc._id, |
||||
// this preserves the name so that notifications can be meaningful after
|
||||
// this file is removed
|
||||
attachmentName: doc.original.name, |
||||
boardId: doc.boardId, |
||||
cardId: doc.cardId, |
||||
listId: doc.listId, |
||||
swimlaneId: doc.swimlaneId, |
||||
}); |
||||
} else { |
||||
// Don't add activity about adding the attachment as the activity
|
||||
// be imported and delete source field
|
||||
AttachmentsOld.update( |
||||
{ |
||||
_id: doc._id, |
||||
}, |
||||
{ |
||||
$unset: { |
||||
source: '', |
||||
}, |
||||
}, |
||||
); |
||||
} |
||||
}); |
||||
|
||||
AttachmentsOld.files.before.remove((userId, doc) => { |
||||
Activities.insert({ |
||||
userId, |
||||
type: 'card', |
||||
activityType: 'deleteAttachment', |
||||
attachmentId: doc._id, |
||||
// this preserves the name so that notifications can be meaningful after
|
||||
// this file is removed
|
||||
attachmentName: doc.original.name, |
||||
boardId: doc.boardId, |
||||
cardId: doc.cardId, |
||||
listId: doc.listId, |
||||
swimlaneId: doc.swimlaneId, |
||||
}); |
||||
}); |
||||
} |
||||
|
||||
export default AttachmentsOld; |
@ -1,29 +0,0 @@ |
||||
AvatarsOld = new FS.Collection('avatars', { |
||||
stores: [new FS.Store.GridFS('avatars')], |
||||
filter: { |
||||
maxSize: 72000, |
||||
allow: { |
||||
contentTypes: ['image/*'], |
||||
}, |
||||
}, |
||||
}); |
||||
|
||||
function isOwner(userId, file) { |
||||
return userId && userId === file.userId; |
||||
} |
||||
|
||||
AvatarsOld.allow({ |
||||
insert: isOwner, |
||||
update: isOwner, |
||||
remove: isOwner, |
||||
download() { |
||||
return true; |
||||
}, |
||||
fetch: ['userId'], |
||||
}); |
||||
|
||||
AvatarsOld.files.before.insert((userId, doc) => { |
||||
doc.userId = userId; |
||||
}); |
||||
|
||||
export default AvatarsOld; |
Loading…
Reference in new issue