Merge branch 'huneau-meteor-1.4-RESTAPI' into devel

This commit is contained in:
Lauri Ojansivu 2017-05-13 12:51:44 +03:00
commit 1c3551201a
11 changed files with 207 additions and 25 deletions

View file

@ -126,6 +126,7 @@
"Settings": true,
"InvitationCodes": true,
"Winston":true,
"JsonRoutes": true
"JsonRoutes": true,
"Authentication": true
}
}

View file

@ -77,3 +77,4 @@ simple:json-routes
rajit:bootstrap3-datepicker
kadira:flow-router
shell-server@0.2.3
simple:rest-accounts-password

View file

@ -134,7 +134,11 @@ service-configuration@1.0.11
session@1.1.7
sha@1.0.9
shell-server@0.2.3
simple:authenticate-user-by-token@1.0.1
simple:json-routes@2.1.0
simple:rest-accounts-password@1.1.2
simple:rest-bearer-token-parser@1.0.1
simple:rest-json-error-handler@1.0.1
softwarerero:accounts-t9n@1.3.9
spacebars@1.0.15
spacebars-compiler@1.1.2

View file

@ -557,6 +557,7 @@ if (Meteor.isServer) {
//BOARDS REST API
if (Meteor.isServer) {
JsonRoutes.add('GET', '/api/boards', function (req, res, next) {
Authentication.checkUserId(req.userId);
JsonRoutes.sendResult(res, {
code: 200,
data: Boards.find({ permission: 'public' }).map(function (doc) {
@ -569,6 +570,7 @@ if (Meteor.isServer) {
});
JsonRoutes.add('GET', '/api/boards/:id', function (req, res, next) {
Authentication.checkUserId( req.userId);
const id = req.params.id;
JsonRoutes.sendResult(res, {
code: 200,
@ -577,6 +579,7 @@ if (Meteor.isServer) {
});
JsonRoutes.add('POST', '/api/boards', function (req, res, next) {
Authentication.checkUserId( req.userId);
const id = Boards.insert({
title: req.body.title,
members: [
@ -599,6 +602,7 @@ if (Meteor.isServer) {
});
JsonRoutes.add('DELETE', '/api/boards/:id', function (req, res, next) {
Authentication.checkUserId( req.userId);
const id = req.params.id;
Boards.remove({ _id: id });
JsonRoutes.sendResult(res, {

View file

@ -80,3 +80,65 @@ if (Meteor.isServer) {
}
});
}
//CARD COMMENT REST API
if (Meteor.isServer) {
JsonRoutes.add('GET', '/api/boards/:boardId/cards/:cardId/comments', function (req, res, next) {
Authentication.checkUserId( req.userId);
const paramBoardId = req.params.boardId;
const paramCardId = req.params.cardId;
JsonRoutes.sendResult(res, {
code: 200,
data: CardComments.find({ boardId: paramBoardId, cardId: paramCardId}).map(function (doc) {
return {
_id: doc._id,
comment: doc.text,
authorId: doc.userId,
};
}),
});
});
JsonRoutes.add('GET', '/api/boards/:boardId/cards/:cardId/comments/:commentId', function (req, res, next) {
Authentication.checkUserId( req.userId);
const paramBoardId = req.params.boardId;
const paramCommentId = req.params.commentId;
const paramCardId = req.params.cardId;
JsonRoutes.sendResult(res, {
code: 200,
data: CardComments.findOne({ _id: paramCommentId, cardId: paramCardId, boardId: paramBoardId }),
});
});
JsonRoutes.add('POST', '/api/boards/:boardId/cards/:cardId/comments', function (req, res, next) {
Authentication.checkUserId( req.userId);
const paramBoardId = req.params.boardId;
const paramCardId = req.params.cardId;
const id = CardComments.insert({
userId: req.body.authorId,
text: req.body.comment,
cardId: paramCardId,
boardId: paramBoardId,
});
JsonRoutes.sendResult(res, {
code: 200,
data: {
_id: id,
},
});
});
JsonRoutes.add('DELETE', '/api/boards/:boardId/cards/:cardId/comments/:commentId', function (req, res, next) {
Authentication.checkUserId( req.userId);
const paramBoardId = req.params.boardId;
const paramCommentId = req.params.commentId;
const paramCardId = req.params.cardId;
CardComments.remove({ _id: paramCommentId, cardId: paramCardId, boardId: paramBoardId });
JsonRoutes.sendResult(res, {
code: 200,
data: {
_id: paramCardId,
},
});
});
}

View file

@ -373,6 +373,7 @@ 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;
JsonRoutes.sendResult(res, {
@ -388,6 +389,7 @@ 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;
@ -398,6 +400,7 @@ if (Meteor.isServer) {
});
JsonRoutes.add('POST', '/api/boards/:boardId/lists/:listId/cards', function (req, res, next) {
Authentication.checkUserId( req.userId);
const paramBoardId = req.params.boardId;
const paramListId = req.params.listId;
const id = Cards.insert({
@ -418,6 +421,7 @@ if (Meteor.isServer) {
});
JsonRoutes.add('DELETE', '/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;

View file

@ -28,22 +28,29 @@ Checklists.attachSchema(new SimpleSchema({
createdAt: {
type: Date,
denyUpdate: false,
autoValue() { // eslint-disable-line consistent-return
if (this.isInsert) {
return new Date();
} else {
this.unset();
}
},
},
}));
Checklists.helpers({
itemCount () {
itemCount() {
return this.items.length;
},
finishedCount () {
finishedCount() {
return this.items.filter((item) => {
return item.isFinished;
}).length;
},
isFinished () {
isFinished() {
return 0 !== this.itemCount() && this.itemCount() === this.finishedCount();
},
getItem (_id) {
getItem(_id) {
return _.findWhere(this.items, { _id });
},
itemIndex(itemId) {
@ -73,17 +80,17 @@ Checklists.before.insert((userId, doc) => {
Checklists.mutations({
//for checklist itself
setTitle(title){
return { $set: { title }};
setTitle(title) {
return { $set: { title } };
},
//for items in checklist
addItem(title) {
const itemCount = this.itemCount();
const _id = `${this._id}${itemCount}`;
return { $addToSet: {items: {_id, title, isFinished: false}} };
return { $addToSet: { items: { _id, title, isFinished: false } } };
},
removeItem(itemId) {
return {$pull: {items: {_id : itemId}}};
return { $pull: { items: { _id: itemId } } };
},
editItem(itemId, title) {
if (this.getItem(itemId)) {
@ -150,13 +157,13 @@ if (Meteor.isServer) {
//TODO: so there will be no activity for adding item into checklist, maybe will be implemented in the future.
// Checklists.after.update((userId, doc) => {
// console.log('update:', doc)
// Activities.insert({
// userId,
// activityType: 'addChecklist',
// boardId: doc.boardId,
// cardId: doc.cardId,
// checklistId: doc._id,
// });
// Activities.insert({
// userId,
// activityType: 'addChecklist',
// boardId: doc.boardId,
// cardId: doc.cardId,
// checklistId: doc._id,
// });
// });
Checklists.before.remove((userId, doc) => {
@ -166,3 +173,66 @@ if (Meteor.isServer) {
}
});
}
//CARD COMMENT REST API
if (Meteor.isServer) {
JsonRoutes.add('GET', '/api/boards/:boardId/cards/:cardId/checklists', function (req, res, next) {
Authentication.checkUserId( req.userId);
const paramCardId = req.params.cardId;
JsonRoutes.sendResult(res, {
code: 200,
data: Checklists.find({ cardId: paramCardId }).map(function (doc) {
return {
_id: doc._id,
title: doc.title,
};
}),
});
});
JsonRoutes.add('GET', '/api/boards/:boardId/cards/:cardId/checklists/:checklistId', function (req, res, next) {
Authentication.checkUserId( req.userId);
const paramChecklistId = req.params.checklistId;
const paramCardId = req.params.cardId;
JsonRoutes.sendResult(res, {
code: 200,
data: Checklists.findOne({ _id: paramChecklistId, cardId: paramCardId }),
});
});
JsonRoutes.add('POST', '/api/boards/:boardId/cards/:cardId/checklists', function (req, res, next) {
Authentication.checkUserId( req.userId);
const paramCardId = req.params.cardId;
const checklistToSend = {};
checklistToSend.cardId = paramCardId;
checklistToSend.title = req.body.title;
checklistToSend.items = [];
const id = Checklists.insert(checklistToSend);
const checklist = Checklists.findOne({_id: id});
req.body.items.forEach(function (item) {
checklist.addItem(item);
}, this);
JsonRoutes.sendResult(res, {
code: 200,
data: {
_id: id,
},
});
});
JsonRoutes.add('DELETE', '/api/boards/:boardId/cards/:cardId/checklists/:checklistId', function (req, res, next) {
Authentication.checkUserId( req.userId);
const paramCommentId = req.params.commentId;
const paramCardId = req.params.cardId;
Checklists.remove({ _id: paramCommentId, cardId: paramCardId });
JsonRoutes.sendResult(res, {
code: 200,
data: {
_id: paramCardId,
},
});
});
}

View file

@ -132,6 +132,7 @@ 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;
JsonRoutes.sendResult(res, {
code: 200,
@ -145,6 +146,7 @@ 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;
JsonRoutes.sendResult(res, {
@ -154,6 +156,7 @@ if (Meteor.isServer) {
});
JsonRoutes.add('POST', '/api/boards/:boardId/lists', function (req, res, next) {
Authentication.checkUserId( req.userId);
const paramBoardId = req.params.boardId;
const id = Lists.insert({
title: req.body.title,
@ -168,6 +171,7 @@ if (Meteor.isServer) {
});
JsonRoutes.add('DELETE', '/api/boards/:boardId/lists/:listId', function (req, res, next) {
Authentication.checkUserId( req.userId);
const paramBoardId = req.params.boardId;
const paramListId = req.params.listId;
Lists.remove({ _id: paramListId, boardId: paramBoardId });

View file

@ -528,6 +528,7 @@ if (Meteor.isServer) {
// USERS REST API
if (Meteor.isServer) {
JsonRoutes.add('GET', '/api/users', function (req, res, next) {
Authentication.checkUserId( req.userId);
JsonRoutes.sendResult(res, {
code: 200,
data: Meteor.users.find({}).map(function (doc) {
@ -536,6 +537,7 @@ if (Meteor.isServer) {
});
});
JsonRoutes.add('GET', '/api/users/:id', function (req, res, next) {
Authentication.checkUserId( req.userId);
const id = req.params.id;
JsonRoutes.sendResult(res, {
code: 200,
@ -543,6 +545,7 @@ if (Meteor.isServer) {
});
});
JsonRoutes.add('POST', '/api/users/', function (req, res, next) {
Authentication.checkUserId( req.userId);
const id = Accounts.createUser({
username: req.body.username,
email: req.body.email,
@ -558,6 +561,7 @@ if (Meteor.isServer) {
});
JsonRoutes.add('DELETE', '/api/users/:id', function (req, res, next) {
Authentication.checkUserId( req.userId);
const id = req.params.id;
Meteor.users.remove({ _id: id });
JsonRoutes.sendResult(res, {

21
server/authentication.js Normal file
View file

@ -0,0 +1,21 @@
Meteor.startup(() => {
Authentication = {};
Authentication.checkUserId = function (userId) {
if (userId === undefined) {
const error = new Meteor.Error('Unauthorized', 'Unauthorized');
error.statusCode = 401;
throw error;
}
const admin = Users.findOne({ _id: userId, isAdmin: true });
if (admin === undefined) {
const error = new Meteor.Error('Forbidden', 'Forbidden');
error.statusCode = 403;
throw error;
}
};
});

View file

@ -3,22 +3,21 @@ Meteor.startup(() => {
require('winston-zulip');
const fs = require('fs');
//remove default logger
Winston.remove(Winston.transports.Console);
const loggerEnable = process.env.LOGGER_ENABLE || false;
console.log('here1');
console.log(loggerEnable);
if (loggerEnable) {
console.log('here2');
Winston.log('info', 'logger is enable');
const loggers = process.env.LOGGERS.split(',') || 'console';
Winston.log('info', `Loggers selected : ${ process.env.LOGGERS }, if empty default is console`);
if (loggers.includes('console')) {
Winston.add(Winston.transports.Console, {
json: true,
timestamp: true,
});
} else {
//remove default logger
Winston.remove(Winston.transports.Console);
}
if (loggers.includes('file')) {
@ -45,15 +44,23 @@ Meteor.startup(() => {
const loggerZulipTo = process.env.LOGGER_ZULIP_TO || 'logs';
const loggerZulipSubject = process.env.LOGGER_ZULIP_SUBJECT || 'wekan';
Winston.add(Winston.transports.Zulip, {
const zulipConfig = {
zulipUsername: loggerZulipUsername,
zulipApikey: loggerZulipApikey,
zulipRealm: loggerZulipRealm,
zulipTo: loggerZulipTo,
zulipSubject: loggerZulipSubject,
});
};
Winston.add(Winston.transports.Zulip, zulipConfig);
Winston.log('info', `zulipconfig ${zulipConfig}`);
}
} else {
//remove default logger
Winston.remove(Winston.transports.Console);
}
Winston.log('info', 'Logger is completly instanciate');
});