mirror of
https://github.com/wekan/wekan.git
synced 2025-12-18 00:10:13 +01: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
|
seriousm:emoji-continued
|
||||||
templates:tabs
|
templates:tabs
|
||||||
verron:autosize
|
verron:autosize
|
||||||
pfafman:filesaver
|
simple:json-routes
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,6 @@ peerlibrary:blaze-components@0.15.1
|
||||||
peerlibrary:computed-field@0.3.1
|
peerlibrary:computed-field@0.3.1
|
||||||
peerlibrary:reactive-field@0.1.0
|
peerlibrary:reactive-field@0.1.0
|
||||||
perak:markdown@1.0.5
|
perak:markdown@1.0.5
|
||||||
pfafman:filesaver@0.2.2
|
|
||||||
promise@0.5.1
|
promise@0.5.1
|
||||||
raix:eventemitter@0.1.3
|
raix:eventemitter@0.1.3
|
||||||
raix:handlebar-helpers@0.2.5
|
raix:handlebar-helpers@0.2.5
|
||||||
|
|
@ -126,6 +125,7 @@ seriousm:emoji-continued@1.4.0
|
||||||
service-configuration@1.0.5
|
service-configuration@1.0.5
|
||||||
session@1.1.1
|
session@1.1.1
|
||||||
sha@1.0.4
|
sha@1.0.4
|
||||||
|
simple:json-routes@1.0.4
|
||||||
softwarerero:accounts-t9n@1.1.7
|
softwarerero:accounts-t9n@1.1.7
|
||||||
spacebars@1.0.7
|
spacebars@1.0.7
|
||||||
spacebars-compiler@1.0.7
|
spacebars-compiler@1.0.7
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ template(name="boardMenuPopup")
|
||||||
if currentUser.isBoardAdmin
|
if currentUser.isBoardAdmin
|
||||||
hr
|
hr
|
||||||
ul.pop-over-list
|
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'}}
|
li: a.js-archive-board {{_ 'archive-board'}}
|
||||||
|
|
||||||
template(name="boardVisibilityList")
|
template(name="boardVisibilityList")
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
/* global saveAs */
|
|
||||||
Template.boardMenuPopup.events({
|
Template.boardMenuPopup.events({
|
||||||
'click .js-rename-board': Popup.open('boardChangeTitle'),
|
'click .js-rename-board': Popup.open('boardChangeTitle'),
|
||||||
'click .js-open-archives'() {
|
'click .js-open-archives'() {
|
||||||
|
|
@ -14,25 +13,18 @@ Template.boardMenuPopup.events({
|
||||||
// confirm that the board was successfully archived.
|
// confirm that the board was successfully archived.
|
||||||
FlowRouter.go('home');
|
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({
|
Template.boardMenuPopup.helpers({
|
||||||
urlExport() {
|
exportUrl() {
|
||||||
return Meteor.absoluteUrl(`api/b/${Session.get('currentBoard')}`);
|
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({
|
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()) {
|
if(this.isPublic()) {
|
||||||
// public boards are visible to everyone
|
// public boards are visible to everyone
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
// otherwise you have to be logged-in and active member
|
// 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({
|
Meteor.methods({
|
||||||
exportBoard(boardId) {
|
exportBoard(boardId) {
|
||||||
check(boardId, String);
|
check(boardId, String);
|
||||||
const board = Boards.findOne(boardId);
|
const exporter = new Exporter(boardId);
|
||||||
if(board.isVisibleByUser()) {
|
if(exporter.canExport(Meteor.user())) {
|
||||||
const exporter = new Exporter(boardId);
|
|
||||||
return exporter.build();
|
return exporter.build();
|
||||||
} else {
|
} else {
|
||||||
throw new Meteor.Error('error-board-notAMember');
|
throw new Meteor.Error('error-board-notAMember');
|
||||||
|
|
@ -56,4 +75,9 @@ class Exporter {
|
||||||
result.users = Users.find(byUserIds, userFields).fetch();
|
result.users = Users.find(byUserIds, userFields).fetch();
|
||||||
return result;
|
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