diff --git a/collections/notifications.js b/collections/notifications.js
index 06e3aa963..a4722c8f8 100644
--- a/collections/notifications.js
+++ b/collections/notifications.js
@@ -9,44 +9,71 @@ Notifications.allow({
, remove: canEditById
});
-getNotification = function(event, properties, context){
- var notification = {};
- // the default context to display notifications is the notification sidebar
- var context = typeof context === 'undefined' ? 'sidebar' : context;
- var p = properties;
+getNotificationContents = function(notification, context){
+ // the same notifications can be displayed in multiple contexts: on-site in the sidebar, sent by email, etc.
+ var event = notification.event,
+ p = notification.properties,
+ context = typeof context === 'undefined' ? 'sidebar' : context,
+ userToNotify = Meteor.users.findOne(notification.userId);
+
+
switch(event){
case 'newReply':
- notification.subject = 'Someone replied to your comment on "'+p.postHeadline+'"';
- notification.text = p.commentAuthorName+' has replied to your comment on "'+p.postHeadline+'": '+getPostCommentUrl(p.postId, p.commentId);
- notification.html = '
Read more';
- break;
+ var n = {
+ subject: 'Someone replied to your comment on "'+p.postHeadline+'"',
+ text: p.commentAuthorName+' has replied to your comment on "'+p.postHeadline+'": '+getPostCommentUrl(p.postId, p.commentId),
+ html: '
Read more';
+ break;
case 'newComment':
- notification.subject = 'A new comment on your post "'+p.postHeadline+'"';
- notification.text = 'You have a new comment by '+p.commentAuthorName+' on your post "'+p.postHeadline+'": '+getPostCommentUrl(p.postId, p.commentId);
- notification.html = '
Read more';
- break;
+ var n = {
+ subject: 'A new comment on your post "'+p.postHeadline+'"',
+ text: 'You have a new comment by '+p.commentAuthorName+' on your post "'+p.postHeadline+'": '+getPostCommentUrl(p.postId, p.commentId),
+ html: '
Read more';
+ break;
case 'newPost':
- notification.subject = p.postAuthorName+' has created a new post: "'+p.postHeadline+'"';
- notification.text = p.postAuthorName+' has created a new post: "'+p.postHeadline+'" '+getPostUrl(p.postId);
- notification.html = ''+p.postAuthorName+' has created a new post: "'+p.postHeadline+'".';
- break;
+ var n = {
+ subject: p.postAuthorName+' has created a new post: "'+p.postHeadline+'"',
+ text: p.postAuthorName+' has created a new post: "'+p.postHeadline+'" '+getPostUrl(p.postId),
+ html: ''+p.postAuthorName+' has created a new post: "'+p.postHeadline+'".'
+ }
+ break;
case 'accountApproved':
- notification.subject = 'Your account has been approved.';
- notification.text = 'Welcome to '+getSetting('title')+'! Your account has just been approved.';
- notification.html = 'Welcome to '+getSetting('title')+'! Your account has just been approved. Start posting.';
- break;
+ var n = {
+ subject: 'Your account has been approved.',
+ text: 'Welcome to '+getSetting('title')+'! Your account has just been approved.',
+ html: 'Welcome to '+getSetting('title')+'! Your account has just been approved. Start posting.'
+ }
+ break;
+
+ case 'newUser':
+ var n = {
+ subject: 'New user: '+p.username,
+ text: 'A new user account has been created: '+p.profileUrl,
+ html: 'A new user account has been created: '+p.username+''
+ }
+ break;
default:
break;
}
- return notification;
+
+ // if context is email, append unsubscribe link to all outgoing notifications
+ if(context == 'email'){
+ n.to = getEmail(userToNotify);
+ n.text = n.text + '\n\n Unsubscribe from all notifications: '+getUnsubscribeLink(userToNotify);
+ n.html = n.html + '
Unsubscribe from all notifications';
+ }
+
+ return n;
}
Meteor.methods({
diff --git a/collections/posts.js b/collections/posts.js
index 4505f6597..de605ac58 100644
--- a/collections/posts.js
+++ b/collections/posts.js
@@ -97,15 +97,17 @@ Meteor.methods({
if(getSetting('emailNotifications', false)){
// notify users of new posts
- var properties = {
- postAuthorName : getDisplayName(postAuthor),
- postAuthorId : post.userId,
- postHeadline : headline,
- postId : postId
+ var notification = {
+ event: 'newPost',
+ properties: {
+ postAuthorName : getDisplayName(postAuthor),
+ postAuthorId : post.userId,
+ postHeadline : headline,
+ postId : postId
+ }
}
- var notification = getNotification('newPost', properties);
- // call a server method because we do not have access to admin users' info on the client
- Meteor.call('notifyUsers', notification, Meteor.user(), function(error, result){
+ // call a server method because we do not have access to users' info on the client
+ Meteor.call('newPostNotify', notification, function(error, result){
//run asynchronously
});
}
diff --git a/lib/helpers.js b/lib/helpers.js
index 179198699..6e64d0de2 100644
--- a/lib/helpers.js
+++ b/lib/helpers.js
@@ -71,18 +71,18 @@ getPostCommentUrl = function(postId, commentId){
// get link to a comment on a post page
return Meteor.absoluteUrl()+'posts/'+postId+'/comment/'+commentId;
}
-getUserUrl = function(id){
- return Meteor.absoluteUrl()+'users/'+id;
-}
getCategoryUrl = function(slug){
return Meteor.absoluteUrl()+'category/'+slug;
}
slugify = function(text) {
- text = text.replace(/[^-a-zA-Z0-9,&\s]+/ig, '');
- text = text.replace(/-/gi, "_");
- text = text.replace(/\s/gi, "-");
- text = text.toLowerCase();
+ if(text){
+ text = text.replace(/[^-a-zA-Z0-9,&\s]+/ig, '');
+ text = text.replace(/-/gi, "_");
+ text = text.replace(/\s/gi, "-");
+ text = text.toLowerCase();
+ }
return text;
+
}
getShortUrl = function(post){
return post.shortUrl ? post.shortUrl : post.url;
diff --git a/lib/users.js b/lib/users.js
index 7e53c2e58..3ab1019e1 100644
--- a/lib/users.js
+++ b/lib/users.js
@@ -24,7 +24,13 @@ getDisplayNameById = function(userId){
return getDisplayName(Meteor.users.findOne(userId));
}
getProfileUrl = function(user) {
- return '/users/' + slugify(getUserName(user));
+ return Meteor.absoluteUrl()+'users/' + slugify(getUserName(user));
+}
+getProfileUrlById = function(id){
+ return Meteor.absoluteUrl()+'users/'+ id;
+}
+getProfileUrlBySlug = function(slug) {
+ return Meteor.absoluteUrl()+'users/' + slug;
}
getTwitterName = function(user){
// return twitter name provided by user, or else the one used for twitter login
diff --git a/server/notifications.js b/server/notifications.js
index a9b2e742b..ab46251a2 100644
--- a/server/notifications.js
+++ b/server/notifications.js
@@ -14,7 +14,7 @@ Meteor.methods({
// console.log(userDoingAction);
// console.log(properties);
// console.log(sendEmail);
- var notification= {
+ var notification = {
timestamp: new Date().getTime(),
userId: userToNotify._id,
event: event,
@@ -26,38 +26,45 @@ Meteor.methods({
// send the notification if notifications are activated,
// the notificationsFrequency is set to 1, or if it's undefined (legacy compatibility)
if(sendEmail){
- Meteor.call('sendNotificationEmail', userToNotify, newNotificationId);
+ // get specific notification content for "email" context
+ var contents = getNotificationContents(notification, 'email');
+ sendNotification(contents);
}
},
- sendNotificationEmail : function(userToNotify, notificationId){
- // Note: we query the DB instead of simply passing arguments from the client
- // to make sure our email method cannot be used for spam
- var notification = Notifications.findOne(notificationId);
- var n = getNotification(notification.event, notification.properties, 'email');
- var to = getEmail(userToNotify);
- var text = n.text + '\n\n Unsubscribe from all notifications: '+getUnsubscribeLink(userToNotify);
- var html = n.html + '
Unsubscribe from all notifications';
- sendEmail(to, n.subject, text, html);
- },
unsubscribeUser : function(hash){
// TO-DO: currently, if you have somebody's email you can unsubscribe them
- // A site-specific salt should be added to the hashing method to prevent this
+ // A user-specific salt should be added to the hashing method to prevent this
var user = Meteor.users.findOne({email_hash: hash});
if(user){
var update = Meteor.users.update(user._id, {
- $set: {'profile.notificationsFrequency' : 0}
+ $set: {
+ 'profile.notifications.users' : 0,
+ 'profile.notifications.posts' : 0,
+ 'profile.notifications.comments' : 0,
+ 'profile.notifications.replies' : 0
+ }
});
return true;
}
return false;
},
- notifyUsers : function(notification, currentUser){
+ newPostNotify : function(properties){
+ var currentUser = Meteor.users.findOne(this.userId);
+ console.log('newPostNotify')
// send a notification to every user according to their notifications settings
Meteor.users.find().forEach(function(user) {
+ // don't send users notifications for their own posts
if(user._id !== currentUser._id && getUserSetting('notifications.posts', false, user)){
- // don't send users notifications for their own posts
- sendEmail(getEmail(user), notification.subject, notification.text, notification.html);
+ properties.userId = user._id;
+ var notification = getNotificationContents(properties, 'email');
+ sendNotification(notification, user);
}
});
}
});
+
+sendNotification = function (notification) {
+ // console.log('send notification:')
+ // console.log(notification)
+ sendEmail(notification.to, notification.subject, notification.text, notification.html);
+}
\ No newline at end of file
diff --git a/server/users.js b/server/users.js
index aa4f8aa8d..e17e56f01 100644
--- a/server/users.js
+++ b/server/users.js
@@ -13,12 +13,20 @@ Accounts.onCreateUser(function(options, user){
if (options.email)
user.profile.email = options.email;
- if (user.profile.email)
- user.email_hash = CryptoJS.MD5(user.profile.email.trim().toLowerCase()).toString();
+ if (getEmail(user))
+ user.email_hash = getEmailHash(user);
if (!user.profile.name)
user.profile.name = user.username;
+ // set notifications default preferences
+ user.profile.notifications = {
+ users: false,
+ posts: false,
+ comments: true,
+ replies: true
+ }
+
// create slug from username
user.slug = slugify(getUserName(user));
@@ -35,9 +43,29 @@ Accounts.onCreateUser(function(options, user){
if(user.profile.email)
addToMailChimpList(user);
+ // send notifications to admins
+ var admins = Meteor.users.find({isAdmin: true});
+ admins.forEach(function(admin){
+ if(getUserSetting('notifications.users', false, admin)){
+ var notification = getNotificationContents({
+ event: 'newUser',
+ username: getUserName(user),
+ profileUrl: getProfileUrl(user),
+ userId: admin._id
+ }, 'email');
+ sendNotification(notification, admin);
+ }
+ });
+
+
return user;
});
+getEmailHash = function(user){
+ // todo: add some kind of salt in here
+ return CryptoJS.MD5(getEmail(user).trim().toLowerCase() + user.createdAt).toString();
+}
+
addToMailChimpList = function(user){
// add a user to a MailChimp list.
// called when a new user is created, or when an existing user fills in their email
@@ -82,9 +110,9 @@ Meteor.methods({
var newScore = baseScore / Math.pow(ageInHours + 2, 1.3);
return Math.abs(object.score - newScore);
},
- generateEmailHash: function(){
- var email_hash = CryptoJS.MD5(getEmail(Meteor.user()).trim().toLowerCase()).toString();
- Meteor.users.update(Meteor.userId(), {$set : {email_hash : email_hash}});
+ setEmailHash: function(user){
+ var email_hash = CryptoJS.MD5(getEmail(user).trim().toLowerCase()).toString();
+ Meteor.users.update(user._id, {$set : {email_hash : email_hash}});
},
addCurrentUserToMailChimpList: function(){
addToMailChimpList(Meteor.user());
From 832c0dc03db69f76eafdf320bc9416682d012bd8 Mon Sep 17 00:00:00 2001
From: Sacha Greif
Date: Mon, 18 Nov 2013 11:31:32 +0900
Subject: [PATCH 24/25] updated history; fix 177 178
---
History.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/History.md b/History.md
index a00a6790d..b93871f8a 100644
--- a/History.md
+++ b/History.md
@@ -1,5 +1,6 @@
## v0.7.3
+* Refactored notifications.
* Added notifications for new users creation.
## v0.7.2
From ca43c338f6cd1554b078d53d81180d1568e46605 Mon Sep 17 00:00:00 2001
From: Sacha Greif
Date: Mon, 18 Nov 2013 13:20:40 +0900
Subject: [PATCH 25/25] fix #179
---
server/users.js | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/server/users.js b/server/users.js
index e17e56f01..1ce88564f 100644
--- a/server/users.js
+++ b/server/users.js
@@ -49,8 +49,10 @@ Accounts.onCreateUser(function(options, user){
if(getUserSetting('notifications.users', false, admin)){
var notification = getNotificationContents({
event: 'newUser',
- username: getUserName(user),
- profileUrl: getProfileUrl(user),
+ properties: {
+ username: getUserName(user),
+ profileUrl: getProfileUrl(user)
+ },
userId: admin._id
}, 'email');
sendNotification(notification, admin);