mirror of
https://github.com/wekan/wekan.git
synced 2025-09-22 01:50:48 +02:00
Export Wekan now server-based with proper auth
This commit is contained in:
parent
efe7c21d57
commit
d08e1cc45b
6 changed files with 42 additions and 26 deletions
|
@ -73,4 +73,4 @@ perak:markdown
|
|||
seriousm:emoji-continued
|
||||
templates:tabs
|
||||
verron:autosize
|
||||
pfafman:filesaver
|
||||
simple:json-routes
|
||||
|
|
|
@ -111,7 +111,6 @@ peerlibrary:blaze-components@0.15.1
|
|||
peerlibrary:computed-field@0.3.1
|
||||
peerlibrary:reactive-field@0.1.0
|
||||
perak:markdown@1.0.5
|
||||
pfafman:filesaver@0.2.2
|
||||
promise@0.5.1
|
||||
raix:eventemitter@0.1.3
|
||||
raix:handlebar-helpers@0.2.5
|
||||
|
@ -126,6 +125,7 @@ seriousm:emoji-continued@1.4.0
|
|||
service-configuration@1.0.5
|
||||
session@1.1.1
|
||||
sha@1.0.4
|
||||
simple:json-routes@1.0.4
|
||||
softwarerero:accounts-t9n@1.1.7
|
||||
spacebars@1.0.7
|
||||
spacebars-compiler@1.0.7
|
||||
|
|
|
@ -56,7 +56,7 @@ template(name="boardMenuPopup")
|
|||
if currentUser.isBoardAdmin
|
||||
hr
|
||||
ul.pop-over-list
|
||||
li: a.js-export-board {{_ 'export-board'}}
|
||||
li: a(href="{{exportUrl}}", download="{{exportFilename}}") {{_ 'export-board'}}
|
||||
li: a.js-archive-board {{_ 'archive-board'}}
|
||||
|
||||
template(name="boardVisibilityList")
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
/* global saveAs */
|
||||
Template.boardMenuPopup.events({
|
||||
'click .js-rename-board': Popup.open('boardChangeTitle'),
|
||||
'click .js-open-archives'() {
|
||||
|
@ -14,25 +13,18 @@ Template.boardMenuPopup.events({
|
|||
// confirm that the board was successfully archived.
|
||||
FlowRouter.go('home');
|
||||
}),
|
||||
'click .js-export-board'() {
|
||||
const boardId = Session.get('currentBoard');
|
||||
Meteor.call('exportBoard', boardId, (error, response) => {
|
||||
if(error) {
|
||||
// the only error we can anticipate is accessing a non-authorized board
|
||||
// and this should have been caugh by UI before.
|
||||
// So no treatment here for the time being.
|
||||
} else {
|
||||
const dataToSave = new Blob([JSON.stringify(response)], {type: 'application/json;charset=utf-8'});
|
||||
const filename = `wekan-export-board-${boardId}.json`;
|
||||
saveAs(dataToSave, filename);
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
Template.boardMenuPopup.helpers({
|
||||
urlExport() {
|
||||
return Meteor.absoluteUrl(`api/b/${Session.get('currentBoard')}`);
|
||||
exportUrl() {
|
||||
const boardId = Session.get('currentBoard');
|
||||
const userId = Meteor.userId();
|
||||
const loginToken = Accounts._storedLoginToken();
|
||||
return Meteor.absoluteUrl(`api/b/${boardId}/${userId}/${loginToken}`);
|
||||
},
|
||||
exportFilename() {
|
||||
const boardId = Session.get('currentBoard');
|
||||
return `wekan-export-board-${boardId}.json`;
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -80,15 +80,15 @@ Boards.attachSchema(new SimpleSchema({
|
|||
|
||||
Boards.helpers({
|
||||
/**
|
||||
* Is current logged-in user authorized to view this board?
|
||||
* Is supplied user authorized to view this board?
|
||||
*/
|
||||
isVisibleByUser() {
|
||||
isVisibleBy(user) {
|
||||
if(this.isPublic()) {
|
||||
// public boards are visible to everyone
|
||||
return true;
|
||||
} else {
|
||||
// otherwise you have to be logged-in and active member
|
||||
return this.isActiveMember(Meteor.userId());
|
||||
return this.isActiveMember(user._id);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -1,11 +1,30 @@
|
|||
/* global JsonRoutes */
|
||||
if(Meteor.isServer) {
|
||||
JsonRoutes.add('get', '/api/b/:boardId/:userId/:loginToken', function (req, res) {
|
||||
const { userId, loginToken, boardId } = req.params;
|
||||
const hashToken = Accounts._hashLoginToken(loginToken);
|
||||
const user = Meteor.users.findOne({
|
||||
_id: userId,
|
||||
'services.resume.loginTokens.hashedToken': hashToken,
|
||||
});
|
||||
|
||||
const exporter = new Exporter(boardId);
|
||||
if(user && exporter.canExport(user)) {
|
||||
JsonRoutes.sendResult(res, 200, exporter.build());
|
||||
} else {
|
||||
// we could send an explicit error message, but on the other
|
||||
// hand the only way to get there is by hacking the UI so...
|
||||
JsonRoutes.sendResult(res, 403);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Meteor.methods({
|
||||
exportBoard(boardId) {
|
||||
check(boardId, String);
|
||||
const board = Boards.findOne(boardId);
|
||||
if(board.isVisibleByUser()) {
|
||||
const exporter = new Exporter(boardId);
|
||||
const exporter = new Exporter(boardId);
|
||||
if(exporter.canExport(Meteor.user())) {
|
||||
return exporter.build();
|
||||
} else {
|
||||
throw new Meteor.Error('error-board-notAMember');
|
||||
|
@ -56,4 +75,9 @@ class Exporter {
|
|||
result.users = Users.find(byUserIds, userFields).fetch();
|
||||
return result;
|
||||
}
|
||||
|
||||
canExport(user) {
|
||||
const board = Boards.findOne(this._boardId);
|
||||
return board && board.isVisibleBy(user);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue