Browse Source

Merge branch 'mayjs-rest-api-pr' into devel

Lauri Ojansivu 8 years ago
parent
commit
1ed7756d6c
5 changed files with 70 additions and 6 deletions
  1. 24 2
      models/boards.js
  2. 2 2
      models/cards.js
  3. 3 2
      models/lists.js
  4. 10 0
      models/users.js
  5. 31 0
      server/authentication.js

+ 24 - 2
models/boards.js

@@ -556,6 +556,28 @@ if (Meteor.isServer) {
 
 //BOARDS REST API
 if (Meteor.isServer) {
+  JsonRoutes.add('GET', '/api/users/:userId/boards', function (req, res, next) {
+    Authentication.checkLoggedIn(req.userId);
+    const paramUserId = req.params.userId;
+    // A normal user should be able to see their own boards,
+    // admins can access boards of any user
+    Authentication.checkAdminOrCondition(req.userId, req.userId === paramUserId);
+
+    const data = Boards.find({
+      archived: false,
+      'members.userId': req.userId,
+    }, {
+      sort: ['title'],
+    }).map(function(board) {
+      return {
+        _id: board._id,
+        title: board.title,
+      };
+    });
+
+    JsonRoutes.sendResult(res, {code: 200, data});
+  });
+
   JsonRoutes.add('GET', '/api/boards', function (req, res, next) {
     Authentication.checkUserId(req.userId);
     JsonRoutes.sendResult(res, {
@@ -570,8 +592,9 @@ if (Meteor.isServer) {
   });
 
   JsonRoutes.add('GET', '/api/boards/:id', function (req, res, next) {
-    Authentication.checkUserId( req.userId);
     const id = req.params.id;
+    Authentication.checkBoardAccess( req.userId, id);
+
     JsonRoutes.sendResult(res, {
       code: 200,
       data: Boards.findOne({ _id: id }),
@@ -612,5 +635,4 @@ if (Meteor.isServer) {
       },
     });
   });
-
 }

+ 2 - 2
models/cards.js

@@ -373,9 +373,9 @@ if (Meteor.isServer) {
 //LISTS REST API
 if (Meteor.isServer) {
   JsonRoutes.add('GET', '/api/boards/:boardId/lists/:listId/cards', function (req, res, next) {
-    Authentication.checkUserId( req.userId);
     const paramBoardId = req.params.boardId;
     const paramListId = req.params.listId;
+    Authentication.checkBoardAccess( req.userId, paramBoardId);
     JsonRoutes.sendResult(res, {
       code: 200,
       data: Cards.find({ boardId: paramBoardId, listId: paramListId, archived: false }).map(function (doc) {
@@ -389,10 +389,10 @@ if (Meteor.isServer) {
   });
 
   JsonRoutes.add('GET', '/api/boards/:boardId/lists/:listId/cards/:cardId', function (req, res, next) {
-    Authentication.checkUserId( req.userId);
     const paramBoardId = req.params.boardId;
     const paramListId = req.params.listId;
     const paramCardId = req.params.cardId;
+    Authentication.checkBoardAccess( req.userId, paramBoardId);
     JsonRoutes.sendResult(res, {
       code: 200,
       data: Cards.findOne({ _id: paramCardId, listId: paramListId, boardId: paramBoardId, archived: false }),

+ 3 - 2
models/lists.js

@@ -132,8 +132,9 @@ if (Meteor.isServer) {
 //LISTS REST API
 if (Meteor.isServer) {
   JsonRoutes.add('GET', '/api/boards/:boardId/lists', function (req, res, next) {
-    Authentication.checkUserId( req.userId);
     const paramBoardId = req.params.boardId;
+    Authentication.checkBoardAccess( req.userId, paramBoardId);
+
     JsonRoutes.sendResult(res, {
       code: 200,
       data: Lists.find({ boardId: paramBoardId, archived: false }).map(function (doc) {
@@ -146,9 +147,9 @@ if (Meteor.isServer) {
   });
 
   JsonRoutes.add('GET', '/api/boards/:boardId/lists/:listId', function (req, res, next) {
-    Authentication.checkUserId( req.userId);
     const paramBoardId = req.params.boardId;
     const paramListId = req.params.listId;
+    Authentication.checkBoardAccess( req.userId, paramBoardId);
     JsonRoutes.sendResult(res, {
       code: 200,
       data: Lists.findOne({ _id: paramListId, boardId: paramBoardId, archived: false }),

+ 10 - 0
models/users.js

@@ -527,6 +527,16 @@ if (Meteor.isServer) {
 
 // USERS REST API
 if (Meteor.isServer) {
+  JsonRoutes.add('GET', '/api/user', function(req, res, next) {
+    Authentication.checkLoggedIn(req.userId);
+    const data = Meteor.users.findOne({ _id: req.userId});
+    delete data.services;
+    JsonRoutes.sendResult(res, {
+      code: 200,
+      data,
+    });
+  });
+
   JsonRoutes.add('GET', '/api/users', function (req, res, next) {
     Authentication.checkUserId( req.userId);
     JsonRoutes.sendResult(res, {

+ 31 - 0
server/authentication.js

@@ -17,5 +17,36 @@ Meteor.startup(() => {
 
   };
 
+  // This will only check if the user is logged in.
+  // The authorization checks for the user will have to be done inside each API endpoint
+  Authentication.checkLoggedIn = function(userId) {
+    if(userId === undefined) {
+      const error = new Meteor.Error('Unauthorized', 'Unauthorized');
+      error.statusCode = 401;
+      throw error;
+    }
+  };
+
+  // An admin should be authorized to access everything, so we use a separate check for admins
+  // This throws an error if otherReq is false and the user is not an admin
+  Authentication.checkAdminOrCondition = function(userId, otherReq) {
+    if(otherReq) return;
+    const admin = Users.findOne({ _id: userId, isAdmin: true });
+    if (admin === undefined) {
+      const error = new Meteor.Error('Forbidden', 'Forbidden');
+      error.statusCode = 403;
+      throw error;
+    }
+  };
+
+  // Helper function. Will throw an error if the user does not have read only access to the given board
+  Authentication.checkBoardAccess = function(userId, boardId) {
+    Authentication.checkLoggedIn(userId);
+
+    const board = Boards.findOne({ _id: boardId });
+    const normalAccess = board.permission === 'public' || board.members.some((e) => e.userId === userId);
+    Authentication.checkAdminOrCondition(userId, normalAccess);
+  };
+
 });