mirror of
https://github.com/wekan/wekan.git
synced 2025-04-23 13:37:09 -04:00
Merge branch 'GhassenRjab-feature/manual-attachments-activities' into devel
Import attachments related activities from Wekan and Trello. Thanks to GhassenRjab ! Closes #1157
This commit is contained in:
commit
a3d4a94890
5 changed files with 89 additions and 65 deletions
|
@ -1,3 +1,12 @@
|
|||
# Upcoming Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
* [Import attachments related activities from Wekan and
|
||||
Trello](https://github.com/wekan/wekan/pull/1202).
|
||||
|
||||
Thanks to GitHub user GhassenRjab for contributions.
|
||||
|
||||
# v0.35 2017-09-02 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
|
|
@ -62,7 +62,7 @@ Template.cardAttachmentsPopup.events({
|
|||
const file = new FS.File(f);
|
||||
file.boardId = card.boardId;
|
||||
file.cardId = card._id;
|
||||
|
||||
file.userId = Meteor.userId();
|
||||
Attachments.insert(file);
|
||||
Popup.close();
|
||||
});
|
||||
|
@ -109,6 +109,7 @@ Template.previewClipboardImagePopup.events({
|
|||
file.updatedAt(new Date());
|
||||
file.boardId = card.boardId;
|
||||
file.cardId = card._id;
|
||||
file.userId = Meteor.userId();
|
||||
Attachments.insert(file);
|
||||
pastedResults = null;
|
||||
$(document.body).pasteImageReader(() => {});
|
||||
|
|
|
@ -3,7 +3,25 @@ Attachments = new FS.Collection('attachments', {
|
|||
|
||||
// XXX Add a new store for cover thumbnails so we don't load big images in
|
||||
// the general board view
|
||||
new FS.Store.GridFS('attachments'),
|
||||
new FS.Store.GridFS('attachments', {
|
||||
// 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`.
|
||||
beforeWrite: (fileObj) => {
|
||||
if (!fileObj.isImage()) {
|
||||
return {
|
||||
type: 'application/octet-stream',
|
||||
};
|
||||
}
|
||||
return {};
|
||||
},
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
|
@ -36,33 +54,25 @@ if (Meteor.isServer) {
|
|||
|
||||
// XXX Enforce a schema for the Attachments CollectionFS
|
||||
|
||||
Attachments.files.before.insert((userId, doc) => {
|
||||
const file = new FS.File(doc);
|
||||
doc.userId = userId;
|
||||
|
||||
// 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?
|
||||
if (!file.isImage()) {
|
||||
file.original.type = 'application/octet-stream';
|
||||
}
|
||||
});
|
||||
|
||||
if (Meteor.isServer) {
|
||||
Attachments.files.after.insert((userId, doc) => {
|
||||
Activities.insert({
|
||||
userId,
|
||||
type: 'card',
|
||||
activityType: 'addAttachment',
|
||||
attachmentId: doc._id,
|
||||
boardId: doc.boardId,
|
||||
cardId: doc.cardId,
|
||||
});
|
||||
// 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,
|
||||
boardId: doc.boardId,
|
||||
cardId: doc.cardId,
|
||||
});
|
||||
} else {
|
||||
// Don't add activity about adding the attachment as the activity
|
||||
// be imported and delete source field
|
||||
Attachments.update( {_id: doc._id}, {$unset: { source : '' } } );
|
||||
}
|
||||
});
|
||||
|
||||
Attachments.files.after.remove((userId, doc) => {
|
||||
|
|
|
@ -318,17 +318,22 @@ export class TrelloCreator {
|
|||
// - HEAD returns null, which causes exception down the line
|
||||
// - the template then tries to display the url to the attachment which causes other errors
|
||||
// so we make it server only, and let UI catch up once it is done, forget about latency comp.
|
||||
const self = this;
|
||||
if(Meteor.isServer) {
|
||||
file.attachData(att.url, function (error) {
|
||||
file.boardId = boardId;
|
||||
file.cardId = cardId;
|
||||
file.userId = self._user(att.idMemberCreator);
|
||||
// The field source will only be used to prevent adding
|
||||
// attachments' related activities automatically
|
||||
file.source = 'import';
|
||||
if (error) {
|
||||
throw(error);
|
||||
} else {
|
||||
const wekanAtt = Attachments.insert(file, () => {
|
||||
// we do nothing
|
||||
});
|
||||
this.attachmentIds[att.id] = wekanAtt._id;
|
||||
self.attachmentIds[att.id] = wekanAtt._id;
|
||||
//
|
||||
if(trelloCoverId === att.id) {
|
||||
Cards.direct.update(cardId, { $set: {coverId: wekanAtt._id}});
|
||||
|
@ -452,6 +457,8 @@ export class TrelloCreator {
|
|||
// In that case Trello still reports its addition, but removes its 'url' field.
|
||||
// So we test for that
|
||||
const trelloAttachment = action.data.attachment;
|
||||
// We need the idMemberCreator
|
||||
trelloAttachment.idMemberCreator = action.idMemberCreator;
|
||||
if(trelloAttachment.url) {
|
||||
// we cannot actually create the Wekan attachment, because we don't yet
|
||||
// have the cards to attach it to, so we store it in the instance variable.
|
||||
|
@ -540,24 +547,18 @@ export class TrelloCreator {
|
|||
// Comment related activities
|
||||
// Trello doesn't export the comment id
|
||||
// Attachment related activities
|
||||
// TODO: We can't add activities related to adding attachments
|
||||
// because when we import an attachment, an activity is
|
||||
// autmatically created. We need to directly insert the attachment
|
||||
// without calling the "Attachments.files.after.insert" hook first,
|
||||
// then we can uncomment the code below
|
||||
// case 'addAttachment': {
|
||||
// console.log(this.attachmentIds);
|
||||
// Activities.direct.insert({
|
||||
// userId: this._user(activity.userId),
|
||||
// type: 'card',
|
||||
// activityType: activity.activityType,
|
||||
// attachmentId: this.attachmentIds[activity.attachmentId],
|
||||
// cardId: this.cards[activity.cardId],
|
||||
// boardId,
|
||||
// createdAt: this._now(activity.createdAt),
|
||||
// });
|
||||
// break;
|
||||
// }
|
||||
case 'addAttachmentToCard': {
|
||||
Activities.direct.insert({
|
||||
userId: this._user(action.idMemberCreator),
|
||||
type: 'card',
|
||||
activityType: 'addAttachment',
|
||||
attachmentId: this.attachmentIds[action.data.attachment.id],
|
||||
cardId: this.cards[action.data.card.id],
|
||||
boardId,
|
||||
createdAt: this._now(action.date),
|
||||
});
|
||||
break;
|
||||
}
|
||||
// Checklist related activities
|
||||
case 'addChecklistToCard': {
|
||||
Activities.direct.insert({
|
||||
|
|
|
@ -307,18 +307,23 @@ export class WekanCreator {
|
|||
// - HEAD returns null, which causes exception down the line
|
||||
// - the template then tries to display the url to the attachment which causes other errors
|
||||
// so we make it server only, and let UI catch up once it is done, forget about latency comp.
|
||||
const self = this;
|
||||
if(Meteor.isServer) {
|
||||
if (att.url) {
|
||||
file.attachData(att.url, function (error) {
|
||||
file.boardId = boardId;
|
||||
file.cardId = cardId;
|
||||
file.userId = self._user(att.userId);
|
||||
// The field source will only be used to prevent adding
|
||||
// attachments' related activities automatically
|
||||
file.source = 'import';
|
||||
if (error) {
|
||||
throw(error);
|
||||
} else {
|
||||
const wekanAtt = Attachments.insert(file, () => {
|
||||
// we do nothing
|
||||
});
|
||||
this.attachmentIds[att._id] = wekanAtt._id;
|
||||
self.attachmentIds[att._id] = wekanAtt._id;
|
||||
//
|
||||
if(wekanCoverId === att._id) {
|
||||
Cards.direct.update(cardId, { $set: {coverId: wekanAtt._id}});
|
||||
|
@ -330,6 +335,10 @@ export class WekanCreator {
|
|||
file.name(att.name);
|
||||
file.boardId = boardId;
|
||||
file.cardId = cardId;
|
||||
file.userId = self._user(att.userId);
|
||||
// The field source will only be used to prevent adding
|
||||
// attachments' related activities automatically
|
||||
file.source = 'import';
|
||||
if (error) {
|
||||
throw(error);
|
||||
} else {
|
||||
|
@ -541,24 +550,18 @@ export class WekanCreator {
|
|||
break;
|
||||
}
|
||||
// Attachment related activities
|
||||
// TODO: We can't add activities related to adding attachments
|
||||
// because when we import an attachment, an activity is
|
||||
// autmatically created. We need to directly insert the attachment
|
||||
// without calling the "Attachments.files.after.insert" hook first,
|
||||
// then we can uncomment the code below
|
||||
// case 'addAttachment': {
|
||||
// console.log(this.attachmentIds);
|
||||
// Activities.direct.insert({
|
||||
// userId: this._user(activity.userId),
|
||||
// type: 'card',
|
||||
// activityType: activity.activityType,
|
||||
// attachmentId: this.attachmentIds[activity.attachmentId],
|
||||
// cardId: this.cards[activity.cardId],
|
||||
// boardId,
|
||||
// createdAt: this._now(activity.createdAt),
|
||||
// });
|
||||
// break;
|
||||
// }
|
||||
case 'addAttachment': {
|
||||
Activities.direct.insert({
|
||||
userId: this._user(activity.userId),
|
||||
type: 'card',
|
||||
activityType: activity.activityType,
|
||||
attachmentId: this.attachmentIds[activity.attachmentId],
|
||||
cardId: this.cards[activity.cardId],
|
||||
boardId,
|
||||
createdAt: this._now(activity.createdAt),
|
||||
});
|
||||
break;
|
||||
}
|
||||
// Checklist related activities
|
||||
case 'addChecklist': {
|
||||
Activities.direct.insert({
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue