Browse Source

board export now checks authentication

Xavier Priour 9 years ago
parent
commit
18697d45f6

+ 1 - 1
.meteor/packages

@@ -73,4 +73,4 @@ perak:markdown
 seriousm:emoji-continued
 templates:tabs
 verron:autosize
-simple:json-routes
+pfafman:filesaver

+ 1 - 1
.meteor/versions

@@ -110,6 +110,7 @@ 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
@@ -125,7 +126,6 @@ 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

+ 1 - 1
client/components/boards/boardHeader.jade

@@ -56,7 +56,7 @@ template(name="boardMenuPopup")
     if currentUser.isBoardAdmin
       hr
       ul.pop-over-list
-        li: a.js-export-board(href="{{urlExport}}", download) {{_ 'export-board'}}
+        li: a.js-export-board {{_ 'export-board'}}
         li: a.js-archive-board {{_ 'archive-board'}}
 
 template(name="boardVisibilityList")

+ 14 - 0
client/components/boards/boardHeader.js

@@ -13,6 +13,20 @@ 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({

+ 27 - 0
models/boards.js

@@ -79,6 +79,33 @@ Boards.attachSchema(new SimpleSchema({
 
 
 Boards.helpers({
+  /**
+   * Is current logged-in user authorized to view this board?
+   */
+  isVisibleByUser() {
+    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());
+    }
+  },
+
+  /**
+   * Is the user one of the active members of the board?
+   *
+   * @param userId
+   * @returns {boolean} the member that matches, or undefined/false
+   */
+  isActiveMember(userId) {
+    if(userId) {
+      return this.members.find((member) => (member.userId === userId && member.isActive));
+    } else {
+      return false;
+    }
+  },
+
   isPublic() {
     return this.permission === 'public';
   },

+ 8 - 18
models/export.js

@@ -1,25 +1,15 @@
-/* global JsonRoutes */
-if(Meteor.isServer) {
-  console.log(`userId is ${this.userId}`);
-  JsonRoutes.add('get', '/api/b/:id', function (req, res) {
-    const id = req.params.id;
-    const board = Boards.findOne(id);
-    //if(Meteor.userId() && allowIsBoardMember(Meteor.userId(), board)) {
-    const exporter = new Exporter(id);
-    JsonRoutes.sendResult(res, 200, exporter.build());
-    //} else {
-    //  // 403 = forbidden
-    //  JsonRoutes.sendError(res, 403);
-    //}
-  });
-}
+
 
 Meteor.methods({
   exportBoard(boardId) {
+    check(boardId, String);
     const board = Boards.findOne(boardId);
-//    //if(Meteor.userId() && allowIsBoardMember(Meteor.userId(), board)) {
-    const exporter = new Exporter(boardId);
-    return exporter.build();
+    if(board.isVisibleByUser()) {
+      const exporter = new Exporter(boardId);
+      return exporter.build();
+    } else {
+      throw new Meteor.Error('error-board-notAMember');
+    }
   }
 });