Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,17 @@
node_modules
lib-cov
*.seed
*.log
*.csv
*.dat
*.out
*.pid
*.gz
*.sublime-*
.directory

pids
logs
results

npm-debug.log
node_modules
34 changes: 34 additions & 0 deletions models/server/Activity.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"use strict";

var Message = require("./Message");
var Share = require("./Share");

module.exports.share = function (message, done) {
Message.create(message, function (err, msg) {
if (err) return done(err);
module.exports.reshare({ message: msg._id, author: message.author }, done);
});
};

module.exports.reshare = function (share, done) {
Share.create(share, done);
};

module.exports.list = function (conditions, done) {
var results = {};
Share.find(conditions).sort("-date").exec(function (err, shares) {
if (err) return done(err);
results.shares = shares;
Share.find(conditions).distinct("message", function (err, messageIds) {
if (err) return done(err);
Message.find({ _id:{ $in:messageIds } }, function (err, messages) {
if (err) return done(err);
results.messages = {};
for (var i = 0; i < messages.length; i ++) {
results.messages[messages[i].id] = messages[i];
}
done(false, results);
});
});
});
};
5 changes: 3 additions & 2 deletions models/server/Message.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
var mongoose = require("mongoose");

var Message = new mongoose.Schema({
author: { type: mongoose.Schema.Types.ObjectId, required: true },
body: { type: String, unique: true, required: true }
})
});

module.exports = mongoose.model("Message", Message)
module.exports = mongoose.model("Message", Message);
12 changes: 12 additions & 0 deletions models/server/Share.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
var mongoose = require("mongoose");

var Share = new mongoose.Schema({
//parent is the User._id of the user whoose post was reshared. For original posts it is empty
parent: { type: mongoose.Schema.Types.ObjectId, required: false },
author: { type: mongoose.Schema.Types.ObjectId, required: true },
message: { type: mongoose.Schema.Types.ObjectId, required: true },
date: { type: Date, default: Date.now }
});
Share.index({author: 1, message: 1}, {unique: true}); //each message can be shared only one by a user

module.exports = mongoose.model("Share", Share);
98 changes: 60 additions & 38 deletions models/server/User.js
Original file line number Diff line number Diff line change
@@ -1,50 +1,72 @@
"use strict";
var mongoose = require("mongoose");
var crypto = require("crypto");
var pw = require("credential");

var User = new mongoose.Schema({
username: { type: String, unique: true, required: true },
password: { type: String, required: true, select: false },
messages: [{ type: mongoose.Schema.Types.ObjectId }]
})
// add Twitter/Facebook authentication in the future?
authType: { type: String, default: "local" },
credentials: String
});

var hashPassword = function(value) {
var md5sum;
md5sum = crypto.createHash('md5');
md5sum.update(value);
return md5sum.digest('hex');
}

User.pre("save", function(next) {
if (!this.isModified('password'))
return next();
this.password = hashPassword(this.password);
return next();
})

User.static("hashPassword", hashPassword)
/*
{
hash: String,
salt: String,
keyLength: Number,
hashMethod: String,
workUnits: Number
}
*/

User.static("available", function(email, username, callback) {
this.findOne({ username: username }, callback);
})
User.static("register", function (credentials, done) {
if (typeof credentials.username !== "string" || !credentials.username) {
done(new Error("user must have unique not-empty username"));
return;
}
module.exports.available(credentials.username, function (err, isAvailable) {
if (err) return done(err);
if (!isAvailable) return done(new Error("Username not available"));
//if authType === "local"
credentials.authType = "local";
registerLocal(credentials, function (err, user) {
if (err) return done(err);
module.exports.create(user, done);
});
});
});

User.static("findOneByUsernamePassword", function(username, password, callback) {
var pattern = {
username: username,
password: this.hashPassword(password)
var registerLocal = function (user, done) {
if (typeof user.password !== "string" || !user.password) {
done(new Error("user must have not-empty password"));
return;
}
this.findOne(pattern).exec(callback);
})
pw.hash(user.password, function (err, hash) {
if (err) return done(err);
delete user.password;
user.credentials = hash;
done(false, user);
});
};

User.method("sendMessage", function(message, callback){
// ToDo

// 1. check is message already stored in DB (has _id property)
// 1.1 create the message if not stored yet
User.static("authenticate", function (input, done) {
module.exports.findOne({"username": input.username}, function (err, user) {
if (err) return done(err);
if (!user) return done(false, false);
//if authType === "local"
pw.verify(user.credentials, input.password, function (err, success) {
if (err) return done(err);
if (!success) return done(false, false);
done(false, user._id);
});
});
});

// 2. use message._id to find users who send the message before
// 2.1. increment those users points
//
// 3. add the message._id to current user's messages
})
User.static("available", function (username, callback) {
this.findOne({ "username": username }, function (err, user) {
if (err) callback(err);
callback(false, !user);
});
});

module.exports = mongoose.model("User", User);
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,12 @@
"mongoose": "~3.8.4",
"connect-mongo": "~0.4.0",
"express": "~3.4.7",
"request": "~2.31.0"
"request": "~2.31.0",
"credential": "~0.2.5"
},
"devDependencies": {
"jasmine-node": "~1.12.0"
},
"devDependencies": {},
"engines": {
"node": ">=0.10.24"
}
Expand Down
34 changes: 34 additions & 0 deletions routes/api/activity.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"use strict";
var Activity = require("../../models/server/Activity");
module.exports = {
list: function (req, res) {
Activity.list(req.body /* conditions */, function (err, activity) {
if (err) {
res.send(500, {result: err});
}
res.send(200, activity);
});
},
share: function(req, res) {
var message = {
author: req.session.userId,
body: req.body.body // String
};
Activity.share(message, function (err, share) {
if (err) {
res.send(500, {result: err});
}
res.send(200, share);
});
},
reshare: function (req, res) {
var share = req.body; // { parent: id, message: id, [date: Date]}
share.author = req.session.userId;
Activity.reshare(share, function (err, share) {
if (err) {
res.send(500, {result: err});
}
res.send(200, share);
});
}
};
11 changes: 0 additions & 11 deletions routes/api/messages.js

This file was deleted.

28 changes: 16 additions & 12 deletions routes/api/users.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,30 @@ var User = require("../../models/server/User");
module.exports = {
logout: function(req, res) {
req.session.destroy();
res.send({result: true})
res.send({result: true});
},
login: function(req, res) {
if(!req.body.username || !req.body.password) return res.send(400)
User.findOneByUsernamePassword(req.body.username, req.body.password, function(err, user){
if(!req.body.username || !req.body.password) return res.send(400);
User.authenticate(req.body, function(err, userId){
if(!err) {
if(user)
req.session.userId = user.id;
res.send({result: user})
if(userId) {
req.session.userId = userId;
res.send({result: { "_id": userId, "username": req.body.username } });
} else {
//TODO: send redirect to login page
res.send(403, {result: "Invalid username or password"});
}
} else
res.send(500, {result: err})
res.send(500, {result: err});
});
},
register: function(req, res) {
User.create(req.body, function(err, user){
User.register(req.body, function(err, user){
if(!err) {
req.session.userId = user.id;
res.send({result: user})
res.send({result: user});
} else
res.send(500, {result: err})
})
res.send(500, {result: err});
});
}
}
};
9 changes: 6 additions & 3 deletions routes/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
module.exports.mount = function(app){
app.get("/users/me/logout", require("./api/users").logout)
app.get("/users/me/login", require("./api/users").login)
app.post("/users/register", require("./api/users").register)
app.get("/users/me/logout", require("./api/users").logout);
app.get("/users/me/login", require("./api/users").login);
app.post("/users/register", require("./api/users").register);
app.get("/activity/list", require("./api/activity").list);
app.post("/activity/share", require("./api/activity").share);
app.post("/activity/reshare", require("./api/activity").reshare);
}
Loading