diff --git a/app.js b/app.js index 41a2eb0..a5aaf96 100644 --- a/app.js +++ b/app.js @@ -1,24 +1,44 @@ +GLOBAL._ = require('underscore'); +GLOBAL.sha1 = require('sha1'); +GLOBAL.ObjectID = require('mongodb').ObjectID; +GLOBAL.async = require('async'); + var express = require('express'); var bodyParser = require('body-parser'); -GLOBAL._ = require('underscore'); -var fs= require('fs') +var fs = require('fs') var app = express(); -GLOBAL.DB = { - save:function(){ - fs.writeFileSync('./db.json',JSON.stringify(this)) - }, - restore: function(){ - GLOBAL.DB = _.extend(GLOBAL.DB,JSON.parse(fs.readFileSync('./db.json','utf-8'))) - } -} -GLOBAL.DB.restore(); -DB.users = DB.users || []; -DB.posts = DB.posts || []; +var MongoClient = require('mongodb').MongoClient +var url = 'mongodb://localhost:27017/socialNetwork'; + +MongoClient.connect(url, function(err, db){ + + console.log("Connected corretly to server"); + + GLOBAL.DB = db; + GLOBAL.UsersCollection = DB.collection('users'); + GLOBAL.PostsCollection = DB.collection('posts'); + + app.listen(100) +}) +console.log("run"); + +app.use(function(req, res, next) { + res.header('Access-Control-Allow-Origin', '*'); + res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS'); + res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With'); + + // intercept OPTIONS method + if ('OPTIONS' == req.method) { + res.send(200); + } + else { + next(); + } +}); app.use(bodyParser.json()) app.use(function (req, res, next) { - console.log(req.originalUrl) if(req.originalUrl =='/register'){ next(null); return; @@ -30,18 +50,29 @@ app.use(function (req, res, next) { var parts = req.headers['authorization'].split(":") var nick = parts[0]; var pwd = parts[1]; - var user = _.find(DB.users, function (usr) { - return usr.nick == nick && pwd == usr.pwd; - }) - if (!user) { + DB.collection('users').findOne({nick:nick,pwd:sha1(pwd)}, function(err,data){ + if (data) { + req.currentUser = data; + next(null); + return + } res.status(401).send({message: "invalid user or password"}) - return; - } - req.currentUser =user; - next(null); + }) }) -require('./controllers/user')(app) -require('./controllers/post')(app) +require('./controllers/user')(app); +require('./controllers/post')(app); -app.listen(100) \ No newline at end of file +GLOBAL.deletePwd = function(users){ + if (_.isArray(users)){ + return _.map(users, function(user){ + var userCopy = _.clone(user) + delete userCopy.pwd; + return userCopy; + }) + } else { + var userCopy = _.clone(users) + delete userCopy.pwd; + return userCopy; + } +} \ No newline at end of file diff --git a/controllers/post.js b/controllers/post.js index 48c5b69..d818608 100644 --- a/controllers/post.js +++ b/controllers/post.js @@ -1,18 +1,112 @@ -module.exports=function(app){ - app.post('/user/:id/wall',function(req,res){ +module.exports = function(app){ + + app.post('/user/:id/wall', function(req, res){ + if(!req.body.content){ res.status(400).send({message:'content required'}) return; } var post = { - content:req.body.content, - id:Date.now(), - authorId:req.currentUser.id, - ownerId:req.params.id + content: req.body.content, + authorId: {$ref: "users", $id: req.currentUser._id}, + ownerId: {$ref: "users", $id: new ObjectID(req.params.id)} }; - DB.posts.push(post) - DB.save(); - res.send(post); + + PostsCollection.insert(post, function(err, data){ + res.send(post); + }) + }) + + app.get('/posts', function(req, res){ + + PostsCollection + .find({}) + .toArray(function(err, posts){ + async.mapLimit( + posts, + 5, + function(post, next){ + UsersCollection.findOne({_id: post.authorId.oid}, function(err, data){ + + post.author = deletePwd(data); + + UsersCollection.findOne({_id: post.ownerId.oid}, function(err, data){ + post.owner = deletePwd(data); + delete post.authorId; + delete post.ownerId; + next(null, post); + }) + }) + }, + function(err, data){ + res.send(data); + } + ) + }) + }) + + app.get('/posts/:id', function(req, res){ + PostsCollection.findOne({_id: new ObjectID(req.params.id)}, function(err, post){ + if(!post){ + res.status(404).send({message:"not found"}) + return; + } + UsersCollection.findOne({_id: post.authorId.oid}, function(err, data){ + post.author = deletePwd(data); + + UsersCollection.findOne({_id: post.ownerId.oid}, function(err, data){ + post.owner = deletePwd(data); + delete post.authorId; + delete post.ownerId; + res.send(post) + }) + }) + + }) + }) + + app.put('/posts/:id', function(req,res){ + PostsCollection.findOne({_id: new ObjectID(req.params.id)}, function(err, post){ + if(!post){ + res.status(404).send({message:"not found"}) + return; + } + if(req.currentUser._id.toString() != post.authorId.oid.toString()){ + res.status(405).send({message: "Not Allowed"}) + return; + } + if(!req.body.content){ + res.status(400).send({message:'content required'}) + return; + } + + PostsCollection.update( + {_id: post._id}, + {$set: {content: req.body.content}}, + function(err, data){ + post.content = req.body.content + res.send(post) + } + ) + }) + }) + + app.delete('/posts/:id', function(req, res){ + PostsCollection.findOne({_id: new ObjectID(req.params.id)}, function(err, post){ + if(!post){ + res.status(404).send({message:"not found"}) + return; + } + if(!(req.currentUser._id.toString() == post.authorId.oid.toString() || req.currentUser._id.toString() == post.ownerId.oid.toString())){ + res.status(405).send({message: "Not Allowed"}) + return; + } + PostsCollection.remove({_id: new ObjectID(req.params.id)}, function(err, post){ + res.send("deleted") + }) + + }) + }) } \ No newline at end of file diff --git a/controllers/user.js b/controllers/user.js index f543dd0..2dbf6a2 100644 --- a/controllers/user.js +++ b/controllers/user.js @@ -1,47 +1,257 @@ -var uniqueId = Date.now(); + module.exports = function(app){ app.get('/me',function(req,res){ - res.send(req.currentUser); - }) - app.get('/user', function (req, res) { - res.send(DB.users); - }) - app.get('/user/:id',function(req,res){ - var user = _.clone(_.find(DB.users,function(usr){ - return usr.id ==req.params.id; - })); - delete user.pwd; - if(!user){ - res.status(404).send({message:"not found"}) + res.send(deletePwd(req.currentUser)); + }) + + app.put('/me',function(req, res){ + + if (req.body.email && req.body.email=="") { + res.status(400).send({message: "Email is required"}) + return; + } else if (req.body.nick && req.body.nick=="") { + res.status(400).send({message: "Nick is required"}) + return; + } else if ((req.body.pwd)&&(!req.body.repeatPwd || req.body.pwd != req.body.repeatPwd)){ + res.status(400).send({message: "Passwords do not match"}) return; } - res.send(user) + + var user = req.currentUser; + + async.parallel( + [ + function(callback){ + UsersCollection.findOne({email: req.body.email}, function(err,data){ + callback(err, data) + }) + }, + function(callback){ + UsersCollection.findOne({nick: req.body.nick}, function(err,data){ + callback(err, data) + }) + } + ], + function(err, data){ + var userWithEmail = data[0]; + var userWithNick = data[1]; + + + if (req.body.email && userWithEmail && userWithEmail._id.toString() != user._id.toString()){ + res.status(400).send({message: "This Email is not available"}) + return; + } else if (req.body.nick && userWithNick && userWithNick._id.toString() != user._id.toString()){ + res.status(400).send({message: "This Nick is not available"}) + return; + } else { + + if (req.body.email){ + user.email = req.body.email; + } + if (req.body.nick){ + user.nick = req.body.nick; + } + if (req.body.pwd){ + user.pwd = sha1(req.body.pwd); + } + + UsersCollection.update( + {_id: user._id}, + user, + function(err, data){ + res.send(deletePwd(user)); + } + ) + + } + + } + ) + }) + + app.get('/user', function(req, res) { + UsersCollection.find({}).toArray(function(err,data){ + res.send(deletePwd(data)); + }) + }) + + app.get('/user/:id', function(req, res){ + + UsersCollection.findOne({_id: new ObjectID(req.params.id)}, function(err, user){ + if(!user){ + res.status(404).send({message:"not found"}) + return; + } + res.send(deletePwd(user)) + }) }) + app.get('/user/:id/wall',function(req,res){ - res.send(_.where( DB.posts,{ownerId:req.params.id})); + + PostsCollection + .find({"ownerId.$id": new ObjectID(req.params.id)}) + .toArray(function(err, posts){ + async.mapLimit( + posts, + 5, + function(post, next){ + UsersCollection.findOne({_id: post.authorId.oid}, function(err, data){ + + post.author = deletePwd(data); + + UsersCollection.findOne({_id: post.ownerId.oid}, function(err, data){ + post.owner = deletePwd(data); + delete post.authorId; + delete post.ownerId; + next(null, post); + }) + }) + }, + function(err, data){ + res.send(data); + } + ) + }) }) - app.post('/register', function (req, res) { - //проверить свободен ли ник и имейл + + app.get('/user/:id/following', function(req, res){ + + UsersCollection.findOne({_id: new ObjectID(req.params.id)}, function(err, user){ + if(!user){ + res.status(404).send({message:"not found"}) + return; + } + + UsersCollection.find({_id: {$in: user.follow}}).toArray(function(err, data){ + + res.send(deletePwd(data)) + }) + + }) + }) + + app.get('/user/:id/followers', function(req, res){ + + UsersCollection.findOne({_id: new ObjectID(req.params.id)}, function(err, user){ + if(!user){ + res.status(404).send({message:"not found"}) + return; + } + + UsersCollection.find({follow: new ObjectID(req.params.id)}).toArray(function(err,data){ + res.send(deletePwd(data)) + }) + }) + + + }) + + app.post('/user/:id/follow', function(req, res){ + + UsersCollection.findOne({_id: new ObjectID(req.params.id)}, function(err, user){ + if(!user){ + res.status(404).send({message:"not found"}) + return; + } + + var user = req.currentUser; + user.follow = user.follow || []; + var follower = _.find(user.follow, function(userId){ + return userId.toString() == req.params.id; + }) + if (follower) { + res.send("already following " + req.params.id) + return + } + + user.follow.push(new ObjectID(req.params.id)); + + UsersCollection.update( + {_id: user._id}, + {$set: { + follow: user.follow + } + }, + function(err, data){ + res.send("following " + req.params.id) + } + ) + }) + }) + + app.delete('/user/:id/follow', function(req, res){ + var user = req.currentUser; + user.follow = user.follow || []; + user.follow = _.filter(user.follow, function(userId){ + return userId.toString() != req.params.id; + }) + + UsersCollection.update( + {_id: user._id}, + {$set: { + follow: user.follow + } + }, + function(err,data){ + res.send("not following " + req.params.id) + } + ) + + }) + + app.post('/register', function(req, res) { + if (!req.body.email) { res.status(400).send({message: "Email is required"}) return; - } else if (!req.body.nick) { + } else if(req.body.email.indexOf("@") == -1){ + res.status(400).send({message: "Invalid Email"}) + return; + } else if (!req.body.nick || req.body.nick == "") { res.status(400).send({message: "Nick is required"}) return; } else if (!req.body.pwd || !req.body.repeatPwd || req.body.pwd != req.body.repeatPwd) { res.status(400).send({message: "Passwords do not match"}) return; } - var user = { - email: req.body.email, - nick: req.body.nick, - pwd: req.body.pwd, - id: ++uniqueId - }; - - DB.users.push(_.clone(user)) - DB.save(); - delete user.pwd; - res.send(user) + + async.parallel( + [ + function(callback){ + UsersCollection.findOne({email: req.body.email}, function(err,data){ + callback(err, data) + }) + }, + function(callback){ + UsersCollection.findOne({nick: req.body.nick}, function(err,data){ + callback(err, data) + }) + } + ], + function(err, data){ + var userWithEmail = data[0]; + var userWithNick = data[1]; + + + if (userWithEmail){ + res.status(400).send({message: "This Email is not available"}) + return; + } else if (userWithNick){ + res.status(400).send({message: "This Nick is not available"}) + return; + } else { + var user = { + email: req.body.email, + nick: req.body.nick, + pwd: sha1(req.body.pwd) + }; + + UsersCollection.insert(user, function(err, data){ + res.send(deletePwd(user)); + }) + } + } + ) }) + } \ No newline at end of file diff --git a/db.json b/db.json deleted file mode 100644 index d7084f4..0000000 --- a/db.json +++ /dev/null @@ -1 +0,0 @@ -{"users":[{"email":"gg@gg.gg","nick":"second","pwd":"123","id":1439224467621},{"email":"gg@gg.gg","nick":"second","pwd":"123","id":1439224467622},{"email":"gg@gg.gg","nick":"gena","pwd":"123","id":1439225345875}],"posts":[{"content":"Hellofrom gena","id":1439225509193,"authorId":1439225345875,"ownerId":"1439224467621"}]} \ No newline at end of file diff --git a/package.json b/package.json index 0d8bcba..2e4e4c1 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "dependencies": { "body-parser": "^1.13.3", "express": "^4.13.3", + "mongodb": "^2.0.42", "underscore": "^1.8.3" } }