code clean-up

This commit is contained in:
SachaG 2017-09-13 12:13:04 +02:00
parent af22ba4e84
commit 5b497c38ba
15 changed files with 83 additions and 435 deletions

View file

@ -6,9 +6,9 @@ import './routes.js';
import './headtags.js';
import './i18n.js';
export * from './categories/index.js';
export * from './comments/index.js';
export * from './posts/index.js';
export { default as Categories } from './categories/index.js';
export { default as Comments } from './comments/index.js';
export { default as Posts } from './posts/index.js';
import './embedly/index.js';
import './voting/index.js';

View file

@ -1,78 +0,0 @@
import Posts from '../collection.js'
import Users from 'meteor/vulcan:users';
import { addCallback, getSetting } from 'meteor/vulcan:core';
import Events from 'meteor/vulcan:events';
// ------------------------------------- posts.remove.sync -------------------------------- //
function PostsRemoveOperations (post) {
Users.update({_id: post.userId}, {$inc: {'postCount': -1}});
return post;
}
addCallback('posts.remove.sync', PostsRemoveOperations);
// ------------------------------------- posts.approve.async -------------------------------- //
/**
* @summary set postedAt when a post is approved and it doesn't have a postedAt date
*/
function PostsSetPostedAt (modifier, post) {
if (!modifier.$set.postedAt && !post.postedAt) {
modifier.$set.postedAt = new Date();
if (modifier.$unset) {
delete modifier.$unset.postedAt;
}
}
return modifier;
}
addCallback('posts.approve.sync', PostsSetPostedAt);
// ------------------------------------- users.remove.async -------------------------------- //
function UsersRemoveDeletePosts (user, options) {
if (options.deletePosts) {
Posts.remove({userId: user._id});
} else {
// not sure if anything should be done in that scenario yet
// Posts.update({userId: userId}, {$set: {author: '\[deleted\]'}}, {multi: true});
}
}
addCallback('users.remove.async', UsersRemoveDeletePosts);
// /**
// * @summary Increase the number of clicks on a post
// * @param {string} postId the ID of the post being edited
// * @param {string} ip the IP of the current user
// */
Posts.increaseClicks = (post, ip) => {
const clickEvent = {
name: 'click',
properties: {
postId: post._id,
ip: ip
}
};
if (getSetting('trackClickEvents', true)) {
// make sure this IP hasn't previously clicked on this post
const existingClickEvent = Events.findOne({name: 'click', 'properties.postId': post._id, 'properties.ip': ip});
if(!existingClickEvent) {
Events.log(clickEvent);
return Posts.update(post._id, { $inc: { clickCount: 1 }});
}
} else {
return Posts.update(post._id, { $inc: { clickCount: 1 }});
}
};
function PostsClickTracking(post, ip) {
return Posts.increaseClicks(post, ip);
}
// track links clicked, locally in Events collection
// note: this event is not sent to segment cause we cannot access the current user
// in our server-side route /out -> sending an event would create a new anonymous
// user: the free limit of 1,000 unique users per month would be reached quickly
addCallback('posts.click.async', PostsClickTracking);

View file

@ -1,112 +0,0 @@
import marked from 'marked';
import Posts from '../collection.js'
import { runCallbacks, runCallbacksAsync, addCallback, getSetting, Utils } from 'meteor/vulcan:core';
//////////////////////////////////////////////////////
// posts.edit.sync //
//////////////////////////////////////////////////////
/**
* @summary Check for duplicate links
*/
function PostsEditDuplicateLinksCheck (modifier, post) {
if(post.url !== modifier.$set.url && !!modifier.$set.url) {
Posts.checkForSameUrl(modifier.$set.url);
}
return modifier;
}
addCallback('posts.edit.sync', PostsEditDuplicateLinksCheck);
/**
* @summary Force sticky to default to false when it's not specified
* (simpleSchema's defaultValue does not work on edit, so do it manually in callback)
*/
// function PostsEditForceStickyToFalse (modifier, post) {
// if (!modifier.$set.sticky) {
// if (modifier.$unset && modifier.$unset.sticky) {
// delete modifier.$unset.sticky;
// }
// modifier.$set.sticky = false;
// }
// return modifier;
// }
// addCallback('posts.edit.sync', PostsEditForceStickyToFalse);
/**
* @summary Set status
*/
// function PostsEditSetIsFuture (modifier, post) {
// const postTime = new Date(modifier.$set.postedAt).getTime();
// const currentTime = new Date().getTime() + 1000; // why '+ 1000' ??
// if (modifier.$set.postedAt) {
// if (postTime > currentTime) {
// // if a post's postedAt date is in the future, set isFuture to true
// modifier.$set.isFuture = true;
// } else if (post.isFuture) {
// // else if a post has isFuture to true but its date is in the past, set isFuture to false
// modifier.$set.isFuture = false;
// }
// }
// return modifier;
// }
// addCallback('posts.edit.sync', PostsEditSetIsFuture);
function PostsEditRunPostApprovedSyncCallbacks (modifier, post) {
if (modifier.$set && Posts.isApproved(modifier.$set) && !Posts.isApproved(post)) {
modifier = runCallbacks('posts.approve.sync', modifier, post);
}
return modifier;
}
addCallback('posts.edit.sync', PostsEditRunPostApprovedSyncCallbacks);
/**
* @summary If title is changing, return new slug
*/
// function PostsEditSlugify (modifier, post) {
// if (modifier.$set && modifier.$set.title) {
// modifier.$set.slug = Utils.slugify(modifier.$set.title);
// }
// return modifier;
// }
// addCallback('posts.edit.sync', PostsEditSlugify);
/**
* @summary If body is changing, update related fields (htmlBody & excerpt)
*/
// function PostsEditHTMLContent (modifier, post) {
// if (modifier.$set && typeof modifier.$set.body !== 'undefined') {
// // excerpt length is configurable via the settings (30 words by default, ~255 characters)
// const excerptLength = getSetting('postExcerptLength', 30);
// // extend the modifier
// modifier.$set = {
// ...modifier.$set,
// htmlBody: Utils.sanitize(marked(modifier.$set.body)),
// excerpt: Utils.trimHTML(Utils.sanitize(marked(modifier.$set.body)), excerptLength),
// };
// } else if (modifier.$unset && modifier.$unset.body) {
// // extend the modifier
// modifier.$unset = {
// ...modifier.$unset,
// htmlBody: true,
// excerpt: true,
// };
// }
// return modifier;
// }
// addCallback('posts.edit.sync', PostsEditHTMLContent);
//////////////////////////////////////////////////////
// posts.edit.async //
//////////////////////////////////////////////////////
function PostsEditRunPostApprovedAsyncCallbacks (post, oldPost) {
if (Posts.isApproved(post) && !Posts.isApproved(oldPost)) {
runCallbacksAsync('posts.approve.async', post);
}
}
addCallback('posts.edit.async', PostsEditRunPostApprovedAsyncCallbacks);

View file

@ -1,128 +0,0 @@
import Posts from '../collection.js'
import marked from 'marked';
import Users from 'meteor/vulcan:users';
import { addCallback, getSetting, Utils } from 'meteor/vulcan:core';
import { createError } from 'apollo-errors';
//////////////////////////////////////////////////////
// posts.new.validate //
//////////////////////////////////////////////////////
/**
* @summary Rate limiting
*/
function PostsNewRateLimit (post, user) {
if(!Users.isAdmin(user)){
var timeSinceLastPost = Users.timeSinceLast(user, Posts),
numberOfPostsInPast24Hours = Users.numberOfItemsInPast24Hours(user, Posts),
postInterval = Math.abs(parseInt(getSetting('postInterval', 30))),
maxPostsPer24Hours = Math.abs(parseInt(getSetting('maxPostsPerDay', 5)));
// check that user waits more than X seconds between posts
if(timeSinceLastPost < postInterval){
const RateLimitError = createError('posts.rate_limit_error', {message: 'posts.rate_limit_error'});
throw new RateLimitError({data: {break: true, value: postInterval-timeSinceLastPost}});
}
// check that the user doesn't post more than Y posts per day
if(numberOfPostsInPast24Hours >= maxPostsPer24Hours){
const RateLimitError = createError('posts.max_per_day', {message: 'posts.max_per_day'});
throw new RateLimitError({data: {break: true, value: maxPostsPer24Hours}});
}
}
return post;
}
addCallback('posts.new.validate', PostsNewRateLimit);
//////////////////////////////////////////////////////
// posts.new.sync //
//////////////////////////////////////////////////////
/**
* @summary Check for duplicate links
*/
function PostsNewDuplicateLinksCheck (post, user) {
if(!!post.url && Posts.checkForSameUrl(post.url)) {
const DuplicateError = createError('posts.link_already_posted', {message: 'posts.link_already_posted'});
throw new DuplicateError({data: {break: true, url: post.url}});
}
return post;
}
addCallback('posts.new.sync', PostsNewDuplicateLinksCheck);
/**
* @summary Set the post's postedAt if it's going to be approved
*/
// function PostsSetPostedAt (post, user) {
// if (!post.postedAt && Posts.getDefaultStatus(user) === Posts.config.STATUS_APPROVED) post.postedAt = new Date();
// return post;
// }
// addCallback('posts.new.sync', PostsSetPostedAt);
/**
* @summary Set the post's isFuture to true if necessary
*/
// function PostsNewSetFuture (post, user) {
// post.isFuture = post.postedAt && new Date(post.postedAt).getTime() > new Date(post.createdAt).getTime() + 1000; // round up to the second
// return post;
// }
// addCallback('posts.new.sync', PostsNewSetFuture);
/**
* @summary Force sticky to default to false when it's not specified
*/
// function PostsNewSetStickyToFalse (post, user) {
// if (!post.sticky) {
// post.sticky = false;
// }
// return post;
// }
// addCallback('posts.new.sync', PostsNewSetStickyToFalse);
/**
* @summary Set the post's slug based on its title
*/
// function PostsNewSlugify (post) {
// post.slug = Utils.slugify(post.title);
// return post;
// }
// addCallback('posts.new.sync', PostsNewSlugify);
/**
* @summary Set the post's HTML content & the excerpt based on its possible body
*/
// function PostsNewHTMLContent (post) {
// if (post.body) {
// // excerpt length is configurable via the settings (30 words by default, ~255 characters)
// const excerptLength = getSetting('postExcerptLength', 30);
// // extend the post document
// post = {
// ...post,
// htmlBody: Utils.sanitize(marked(post.body)),
// excerpt: Utils.trimHTML(Utils.sanitize(marked(post.body)), excerptLength),
// };
// }
// return post;
// }
// addCallback('posts.new.sync', PostsNewHTMLContent);
//////////////////////////////////////////////////////
// posts.new.async //
//////////////////////////////////////////////////////
/**
* @summary Increment the user's post count
*/
function PostsNewIncrementPostCount (post) {
var userId = post.userId;
Users.update({_id: userId}, {$inc: {'postCount': 1}});
}
addCallback('posts.new.async', PostsNewIncrementPostCount);

View file

@ -5,9 +5,6 @@ import './custom_fields.js';
import './parameters.js';
import './views.js';
import './helpers.js';
import './callbacks/callbacks_posts_new.js';
import './callbacks/callbacks_posts_edit.js';
import './callbacks/callbacks_other.js';
import './permissions.js';
import './redux.js';
import './admin.js';

View file

@ -1,42 +1,9 @@
import Users from 'meteor/vulcan:users';
import { addCallback } from 'meteor/vulcan:core';
import { createNotification } from './notifications.js';
import { createNotification } from '../email/notifications.js';
// note: leverage weak dependencies on packages
const Comments = Package['vulcan:comments'] ? Package['vulcan:comments'].default : null;
const Posts = Package['vulcan:posts'] ? Package['vulcan:posts'].default : null;
/**
* @summary Add notification callback when a post is approved
*/
function PostsApprovedNotification (post) {
createNotification(post.userId, 'postApproved', {documentId: post._id});
}
/**
* @summary Add new post notification callback on post submit
*/
function PostsNewNotifications (post) {
let adminIds = _.pluck(Users.adminUsers({fields: {_id:1}}), '_id');
let notifiedUserIds = _.pluck(Users.find({'notifications_posts': true}, {fields: {_id:1}}).fetch(), '_id');
// remove post author ID from arrays
adminIds = _.without(adminIds, post.userId);
notifiedUserIds = _.without(notifiedUserIds, post.userId);
if (post.status === Posts.config.STATUS_PENDING && !!adminIds.length) {
// if post is pending, only notify admins
createNotification(adminIds, 'newPendingPost', {documentId: post._id});
} else if (!!notifiedUserIds.length) {
// if post is approved, notify everybody
createNotification(notifiedUserIds, 'newPost', {documentId: post._id});
}
}
addCallback("posts.approve.async", PostsApprovedNotification);
addCallback("posts.new.async", PostsNewNotifications);
import Posts from '../../modules/posts/index.js';
import Comments from '../../modules/comments/index.js';
// add new comment notification callback on comment submit
function CommentsNewNotifications (comment) {
@ -79,5 +46,4 @@ function CommentsNewNotifications (comment) {
}
}
addCallback("comments.new.async", CommentsNewNotifications);

View file

@ -2,6 +2,8 @@
export * from '../modules/index.js';
export * from '../email/notifications.js';
// Server
import './email/templates.js';

View file

@ -1,8 +1,10 @@
import Posts from '../collection.js'
import marked from 'marked';
import Users from 'meteor/vulcan:users';
import Events from 'meteor/vulcan:events';
import { getSetting, runCallbacks, runCallbacksAsync, addCallback } from 'meteor/vulcan:core';
import { addCallback, getSetting, Utils, runCallbacks, runCallbacksAsync } from 'meteor/vulcan:core';
import { createError } from 'apollo-errors';
import Events from 'meteor/vulcan:events';
import { createNotification } from '../email/notifications.js';
//////////////////////////////////////////////////////
// posts.new.validate //
@ -40,7 +42,6 @@ addCallback('posts.new.validate', PostsNewRateLimit);
// posts.new.sync //
//////////////////////////////////////////////////////
/**
* @summary Check for duplicate links
*/
@ -57,7 +58,6 @@ addCallback('posts.new.sync', PostsNewDuplicateLinksCheck);
// posts.new.async //
//////////////////////////////////////////////////////
/**
* @summary Increment the user's post count
*/
@ -67,12 +67,33 @@ function PostsNewIncrementPostCount (post) {
}
addCallback('posts.new.async', PostsNewIncrementPostCount);
/**
* @summary Add new post notification callback on post submit
*/
function PostsNewNotifications (post) {
let adminIds = _.pluck(Users.adminUsers({fields: {_id:1}}), '_id');
let notifiedUserIds = _.pluck(Users.find({'notifications_posts': true}, {fields: {_id:1}}).fetch(), '_id');
// remove post author ID from arrays
adminIds = _.without(adminIds, post.userId);
notifiedUserIds = _.without(notifiedUserIds, post.userId);
if (post.status === Posts.config.STATUS_PENDING && !!adminIds.length) {
// if post is pending, only notify admins
createNotification(adminIds, 'newPendingPost', {documentId: post._id});
} else if (!!notifiedUserIds.length) {
// if post is approved, notify everybody
createNotification(notifiedUserIds, 'newPost', {documentId: post._id});
}
}
addCallback("posts.new.async", PostsNewNotifications);
//////////////////////////////////////////////////////
// posts.edit.sync //
//////////////////////////////////////////////////////
/**
* @summary Check for duplicate links
*/
@ -84,7 +105,6 @@ function PostsEditDuplicateLinksCheck (modifier, post) {
}
addCallback('posts.edit.sync', PostsEditDuplicateLinksCheck);
function PostsEditRunPostApprovedSyncCallbacks (modifier, post) {
if (modifier.$set && Posts.isApproved(modifier.$set) && !Posts.isApproved(post)) {
modifier = runCallbacks('posts.approve.sync', modifier, post);
@ -104,8 +124,17 @@ function PostsEditRunPostApprovedAsyncCallbacks (post, oldPost) {
}
addCallback('posts.edit.async', PostsEditRunPostApprovedAsyncCallbacks);
/**
* @summary Add notification callback when a post is approved
*/
function PostsApprovedNotification (post) {
createNotification(post.userId, 'postApproved', {documentId: post._id});
}
addCallback("posts.approve.async", PostsApprovedNotification);
// ------------------------------------- posts.remove.sync -------------------------------- //
//////////////////////////////////////////////////////
// posts.remove.sync //
//////////////////////////////////////////////////////
function PostsRemoveOperations (post) {
Users.update({_id: post.userId}, {$inc: {'postCount': -1}});
@ -113,7 +142,9 @@ function PostsRemoveOperations (post) {
}
addCallback('posts.remove.sync', PostsRemoveOperations);
// ------------------------------------- posts.approve.async -------------------------------- //
//////////////////////////////////////////////////////
// posts.approve.sync //
//////////////////////////////////////////////////////
/**
* @summary set postedAt when a post is approved and it doesn't have a postedAt date
@ -129,7 +160,9 @@ function PostsSetPostedAt (modifier, post) {
}
addCallback('posts.approve.sync', PostsSetPostedAt);
// ------------------------------------- users.remove.async -------------------------------- //
//////////////////////////////////////////////////////
// users.remove.async //
//////////////////////////////////////////////////////
function UsersRemoveDeletePosts (user, options) {
if (options.deletePosts) {
@ -141,6 +174,9 @@ function UsersRemoveDeletePosts (user, options) {
}
addCallback('users.remove.async', UsersRemoveDeletePosts);
//////////////////////////////////////////////////////
// posts.click.async //
//////////////////////////////////////////////////////
// /**
// * @summary Increase the number of clicks on a post

View file

@ -1,4 +1,4 @@
import Posts from "meteor/vulcan:posts";
import { Posts } from 'meteor/example-forum';
Posts.addField([
{

View file

@ -1,5 +1,5 @@
import cloudinary from "cloudinary";
import Posts from "meteor/vulcan:posts";
// import Posts from "meteor/vulcan:posts";
import Users from 'meteor/vulcan:users';
import { addCallback, Utils, getSetting } from 'meteor/vulcan:core';
@ -52,71 +52,41 @@ const CloudinaryUtils = {
};
// methods
Meteor.methods({
testCloudinaryUpload: function (thumbnailUrl) {
if (Users.isAdmin(Meteor.user())) {
thumbnailUrl = typeof thumbnailUrl === "undefined" ? "http://www.telescopeapp.org/images/logo.png" : thumbnailUrl;
const data = CloudinaryUtils.uploadImage(thumbnailUrl);
console.log(data); // eslint-disable-line
}
},
cachePostThumbnails: function (limit = 20) {
// Meteor.methods({
// testCloudinaryUpload: function (thumbnailUrl) {
// if (Users.isAdmin(Meteor.user())) {
// thumbnailUrl = typeof thumbnailUrl === "undefined" ? "http://www.telescopeapp.org/images/logo.png" : thumbnailUrl;
// const data = CloudinaryUtils.uploadImage(thumbnailUrl);
// console.log(data); // eslint-disable-line
// }
// },
// cachePostThumbnails: function (limit = 20) {
if (Users.isAdmin(Meteor.user())) {
// if (Users.isAdmin(Meteor.user())) {
console.log(`// caching ${limit} thumbnails…`)
// console.log(`// caching ${limit} thumbnails…`)
var postsWithUncachedThumbnails = Posts.find({
thumbnailUrl: { $exists: true },
originalThumbnailUrl: { $exists: false }
}, {sort: {createdAt: -1}, limit: limit});
// var postsWithUncachedThumbnails = Posts.find({
// thumbnailUrl: { $exists: true },
// originalThumbnailUrl: { $exists: false }
// }, {sort: {createdAt: -1}, limit: limit});
postsWithUncachedThumbnails.forEach(Meteor.bindEnvironment((post, index) => {
// postsWithUncachedThumbnails.forEach(Meteor.bindEnvironment((post, index) => {
Meteor.setTimeout(function () {
console.log(`// ${index}. Caching thumbnail for post “${post.title}” (_id: ${post._id})`); // eslint-disable-line
// Meteor.setTimeout(function () {
// console.log(`// ${index}. Caching thumbnail for post “${post.title}” (_id: ${post._id})`); // eslint-disable-line
const data = CloudinaryUtils.uploadImage(post.thumbnailUrl);
Posts.update(post._id, {$set:{
cloudinaryId: data.cloudinaryId,
cloudinaryUrls: data.urls
}});
// const data = CloudinaryUtils.uploadImage(post.thumbnailUrl);
// Posts.update(post._id, {$set:{
// cloudinaryId: data.cloudinaryId,
// cloudinaryUrls: data.urls
// }});
}, index * 1000);
}));
}
}
});
// post submit callback
function cachePostThumbnailOnSubmit (post) {
if (cloudinarySettings) {
if (post.thumbnailUrl) {
const data = CloudinaryUtils.uploadImage(post.thumbnailUrl);
if (data) {
post.cloudinaryId = data.cloudinaryId;
post.cloudinaryUrls = data.urls;
}
}
}
return post;
}
addCallback("posts.new.sync", cachePostThumbnailOnSubmit);
function cachePostThumbnailOnEdit (modifier, oldPost) {
if (cloudinarySettings) {
if (modifier.$set.thumbnailUrl && modifier.$set.thumbnailUrl !== oldPost.thumbnailUrl) {
const data = CloudinaryUtils.uploadImage(modifier.$set.thumbnailUrl);
modifier.$set.cloudinaryId = data.cloudinaryId;
modifier.$set.cloudinaryUrls = data.urls;
}
}
return modifier;
}
addCallback("posts.edit.sync", cachePostThumbnailOnEdit);
// }, index * 1000);
// }));
// }
// }
// });
export default CloudinaryUtils;

View file

@ -10,14 +10,9 @@ Package.onUse(function (api) {
api.versionsFrom(['METEOR@1.0']);
api.use([
'vulcan:posts@1.7.0',
'vulcan:core@1.7.0'
]);
api.addFiles([
'lib/custom_fields.js'
], ['client', 'server']);
api.addFiles([
], ['client']);