mirror of
https://github.com/vale981/Vulcan
synced 2025-03-06 01:51:40 -05:00
working on permissions and router filters
This commit is contained in:
parent
321fa8fb19
commit
dafae9b57c
27 changed files with 124 additions and 203 deletions
|
@ -9,7 +9,7 @@
|
|||
* Removed `Telescope.utils.getCurrentTemplate()`;
|
||||
* Removed search logging.
|
||||
* Disabled single day view.
|
||||
|
||||
* `Posts.checkForSameUrl` doesn't auto-upvote the existing post anymore.
|
||||
* RSS feed and API can now both accept any post query parameter (`limit`, `view`, `cat`, `before`, `after`, etc.)
|
||||
|
||||
## v0.24 “SubScope2”
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<template name="comment_edit">
|
||||
<div class="comment-edit">
|
||||
{{#if canEdit}}
|
||||
{{#checker check="edit" doc=post message="sorry_you_cannot_edit_this_comment"}}
|
||||
|
||||
<div class="grid grid-module">
|
||||
<div class="comment-form">
|
||||
{{> quickForm collection="Comments" doc=comment id="editCommentForm" template="bootstrap3-horizontal" label-class="control-label" input-col-class="controls" type="method-update" meteormethod="editComment" fields=commentFields}}
|
||||
|
@ -10,8 +11,7 @@
|
|||
<div class="grid grid-module">
|
||||
<a class="delete-link" href="/">{{_ "delete_comment"}}</a>
|
||||
</div>
|
||||
{{else}}
|
||||
{{> no_rights message="sorry_you_cannot_edit_this_comment"}}
|
||||
{{/if}}
|
||||
|
||||
{{/checker}}
|
||||
</div>
|
||||
</template>
|
|
@ -22,6 +22,7 @@
|
|||
"thanks_for_signing_up" : "Thanks for registering!",
|
||||
"the_site_is_currently_invite_only_but_we_will_let_you_know_as_soon_as_a_spot_opens_up" : "The site is currently invite-only, but we will let you know as soon as a spot opens up.",
|
||||
"sorry_you_dont_have_the_rights_to_view_this_page" : "Sorry, you don't have the rights to view this page.",
|
||||
"sorry_you_need_to_be_an_admin_to_view_this_page": "Sorry, you need to be an admin to view this page",
|
||||
"sorry_you_do_not_have_the_rights_to_comments" : "Sorry, you do not have the rights to leave comments at this time.",
|
||||
"not_found" : "Not Found!",
|
||||
"were_sorry_whatever_you_were_looking_for_isnt_here" : "We're sorry; whatever you were looking for isn't here..",
|
||||
|
|
|
@ -28,9 +28,3 @@ FlowRouter.subscriptions = function() {
|
|||
}
|
||||
});
|
||||
};
|
||||
|
||||
FlowRouter.notFound = {
|
||||
action: function() {
|
||||
BlazeLayout.render("layout", {main: "not_found"});
|
||||
}
|
||||
};
|
|
@ -0,0 +1,7 @@
|
|||
<template name="checker">
|
||||
{{#if allow}}
|
||||
{{> Template.contentBlock}}
|
||||
{{else}}
|
||||
{{> no_rights message=message}}
|
||||
{{/if}}
|
||||
</template>
|
|
@ -0,0 +1,5 @@
|
|||
Template.checker.helpers({
|
||||
allow: function () {
|
||||
return Users.can[this.check](Meteor.user(), this.doc);
|
||||
}
|
||||
});
|
|
@ -8,9 +8,13 @@
|
|||
{{> modules zone="hero"}}
|
||||
<div class="content-wrapper">
|
||||
{{> messages}}
|
||||
{{#if notAllowed}}
|
||||
{{> Template.dynamic template=notAllowed.template data=notAllowed.data}}
|
||||
{{else}}
|
||||
{{> Template.dynamic template=adminMenu}}
|
||||
{{> modules zone="top"}}
|
||||
{{> Template.dynamic template=main}}
|
||||
{{/if}}
|
||||
{{> modules zone="footer"}}
|
||||
</div>
|
||||
<div class="overlay hidden"></div>
|
||||
|
|
|
@ -31,6 +31,33 @@ Template.layout.helpers({
|
|||
appIsReady: function () {
|
||||
return FlowRouter.subsReady();
|
||||
},
|
||||
notAllowed: function () {
|
||||
|
||||
FlowRouter.watchPathChange();
|
||||
var user = Meteor.user();
|
||||
var userRoutes = ['signIn', 'signUp', 'changePwd', 'forgotPwd', 'resetPwd', 'enrollAccount', 'verifyEmail', 'signOut'];
|
||||
var isOnUserRoute = !_.contains(userRoutes, FlowRouter.getRouteName());
|
||||
|
||||
// Router.onBeforeAction(filters.canView, {except: ['atSignIn', 'atSignUp', 'atForgotPwd', 'atResetPwd', 'signOut']});
|
||||
|
||||
if (!isOnUserRoute && user && ! Users.userProfileComplete(user)){
|
||||
return {template: "user_complete"};
|
||||
}
|
||||
|
||||
if (FlowRouter.current().route.group && FlowRouter.current().route.group.name === "admin" && !Users.is.admin(user)) {
|
||||
return {template: "no_rights", data: {message: i18n.t("sorry_you_need_to_be_an_admin_to_view_this_page")}};
|
||||
}
|
||||
|
||||
if (!isOnUserRoute && !Users.can.view(user)) {
|
||||
return {template: "no_rights", data: {message: i18n.t("sorry_you_dont_have_the_rights_to_view_this_page")}};
|
||||
}
|
||||
|
||||
if (FlowRouter.getRouteName() === "postSubmit" && !Users.can.post(user)) {
|
||||
return {template: "no_rights", data: {message: i18n.t("sorry_you_dont_have_permissions_to_add_new_items")}};
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
navLayout: function () {
|
||||
return Settings.get('navLayout', 'top-nav');
|
||||
},
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
Template.no_rights.helpers({
|
||||
errorMessage: function () {
|
||||
console.log(this)
|
||||
return !!this.message ? i18n.t(this.message) : i18n.t("sorry_you_dont_have_the_rights_to_view_this_page");
|
||||
}
|
||||
});
|
|
@ -1,158 +0,0 @@
|
|||
// //--------------------------------------------------------------------------------------------------//
|
||||
// //--------------------------------------------- Filters --------------------------------------------//
|
||||
// //--------------------------------------------------------------------------------------------------//
|
||||
|
||||
// Router._filters = {
|
||||
|
||||
// isReady: function () {
|
||||
// if (!this.ready()) {
|
||||
// // console.log('not ready')
|
||||
// this.render('loading');
|
||||
// }else{
|
||||
// this.next();
|
||||
// // console.log('ready')
|
||||
// }
|
||||
// },
|
||||
|
||||
// clearSeenMessages: function () {
|
||||
// Messages.clearSeen();
|
||||
// this.next();
|
||||
// },
|
||||
|
||||
// resetScroll: function () {
|
||||
// var scrollTo = window.currentScroll || 0;
|
||||
// var $body = $('body');
|
||||
// $body.scrollTop(scrollTo);
|
||||
// $body.css("min-height", 0);
|
||||
// },
|
||||
|
||||
// isAdmin: function () {
|
||||
// if(!this.ready()) return;
|
||||
// if(!Users.is.admin()){
|
||||
// this.render('no_rights');
|
||||
// } else {
|
||||
// this.next();
|
||||
// }
|
||||
// },
|
||||
|
||||
// canView: function () {
|
||||
// if(!this.ready() || Meteor.loggingIn()){
|
||||
// this.render('loading');
|
||||
// } else if (!Users.can.view()) {
|
||||
// this.render('no_invite');
|
||||
// } else {
|
||||
// this.next();
|
||||
// }
|
||||
// },
|
||||
|
||||
// canPost: function () {
|
||||
// if(!this.ready() || Meteor.loggingIn()){
|
||||
// this.render('loading');
|
||||
// } else if(!Users.can.post()) {
|
||||
// Messages.flash(i18n.t("sorry_you_dont_have_permissions_to_add_new_items"), "error");
|
||||
// this.render('no_rights');
|
||||
// } else {
|
||||
// this.next();
|
||||
// }
|
||||
// },
|
||||
|
||||
// hasCompletedProfile: function () {
|
||||
// if(!this.ready()) return;
|
||||
// var user = Meteor.user();
|
||||
// if (user && ! Users.userProfileComplete(user)){
|
||||
// this.render('user_complete');
|
||||
// } else {
|
||||
// this.next();
|
||||
// }
|
||||
// },
|
||||
|
||||
// setSEOProperties: function () {
|
||||
|
||||
// var props = {meta: {}, og: {}, twitter: {}};
|
||||
// var title = this.getTitle && this.getTitle();
|
||||
// var description = this.getDescription && this.getDescription();
|
||||
// var image = Settings.get("siteImage");
|
||||
|
||||
// if (!!title) {
|
||||
// props.title = title;
|
||||
// }
|
||||
|
||||
// if (!!description) {
|
||||
// props.meta.description = description;
|
||||
// props.og.description = description;
|
||||
// }
|
||||
|
||||
// if (!!image) {
|
||||
// props.og.image = image;
|
||||
// }
|
||||
|
||||
// if (!!Settings.get("twitterAccount")) {
|
||||
// props.twitter.site = Settings.get("twitterAccount");
|
||||
// }
|
||||
|
||||
// SEO.set(props);
|
||||
|
||||
// $('title').text(title);
|
||||
// },
|
||||
|
||||
// setCanonical: function () {
|
||||
// var post = Posts.findOne(this.params._id);
|
||||
// if (post) {
|
||||
// SEO.set({link: {canonical: Posts.getPageUrl(post)}}, false);
|
||||
// }
|
||||
// }
|
||||
|
||||
// };
|
||||
|
||||
// var filters = Router._filters;
|
||||
|
||||
// Meteor.startup( function (){
|
||||
|
||||
// if(Meteor.isClient){
|
||||
|
||||
// // Load Hooks
|
||||
|
||||
// Router.onBeforeAction( function () {
|
||||
|
||||
// // if we're not on the search page itself, clear search query and field
|
||||
// if(Router.current().route.getName() !== 'search'){
|
||||
// Session.set('searchQuery', '');
|
||||
// $('.search-field').val('').blur();
|
||||
// }
|
||||
|
||||
// this.next();
|
||||
|
||||
// });
|
||||
|
||||
// // onRun Hooks
|
||||
|
||||
// // note: this has to run in an onRun hook, because onBeforeAction hooks can get called multiple times
|
||||
// // per route, which would erase the message before the user has actually seen it
|
||||
// // TODO: find a way to make this work even with HCRs.
|
||||
// Router.onRun(filters.clearSeenMessages);
|
||||
|
||||
// // Before Hooks
|
||||
|
||||
// Router.onBeforeAction(filters.isReady);
|
||||
// Router.onBeforeAction(filters.hasCompletedProfile, {except: ['atSignIn', 'atSignUp', 'atForgotPwd', 'atResetPwd', 'signOut']});
|
||||
// Router.onBeforeAction(filters.canView, {except: ['atSignIn', 'atSignUp', 'atForgotPwd', 'atResetPwd', 'signOut']});
|
||||
// Router.onBeforeAction(filters.isAdmin, {only: ['posts_pending', 'all-users', 'settings', 'toolbox', 'logs']});
|
||||
|
||||
// Router.plugin('ensureSignedIn', {only: ['post_submit', 'post_edit', 'comment_edit']});
|
||||
|
||||
// Router.onBeforeAction(filters.canPost, {only: ['posts_pending', 'post_submit']});
|
||||
|
||||
// // After Hooks
|
||||
|
||||
// Router.onAfterAction(Events.analyticsInit); // will only run once thanks to _.once()
|
||||
// Router.onAfterAction(Events.analyticsRequest); // log this request with mixpanel, etc
|
||||
// Router.onAfterAction(filters.setSEOProperties, {except: ["post_page", "post_page_with_slug"]}); // post pages have their own SEO logic
|
||||
// Router.onAfterAction(filters.setCanonical, {only: ["post_page", "post_page_with_slug"]});
|
||||
|
||||
// // Unload Hooks
|
||||
|
||||
// //
|
||||
|
||||
// }
|
||||
|
||||
// });
|
|
@ -25,7 +25,6 @@ Package.onUse(function(api) {
|
|||
api.imply(packages);
|
||||
|
||||
api.addFiles([
|
||||
'lib/router/filters.js',
|
||||
'lib/modules.js',
|
||||
'lib/vote.js'
|
||||
], ['client', 'server']);
|
||||
|
@ -45,6 +44,8 @@ Package.onUse(function(api) {
|
|||
'lib/client/templates/common/footer_code.html',
|
||||
'lib/client/templates/common/footer_code.js',
|
||||
'lib/client/templates/common/loader.html',
|
||||
'lib/client/templates/common/checker.html',
|
||||
'lib/client/templates/common/checker.js',
|
||||
'lib/client/templates/common/layout.html',
|
||||
'lib/client/templates/common/layout.js',
|
||||
'lib/client/templates/errors/already_logged_in.html',
|
||||
|
|
|
@ -7,5 +7,6 @@
|
|||
"please_ask_your_admin_to_fill_in_embedly_key" : "Please ask your site admin to fill in an Embedly API key to enable thumbnails.",
|
||||
"embedlyKey" : "Embedly API Key",
|
||||
"thumbnailWidth" : "Thumbnail Width",
|
||||
"thumbnailHeight" : "Thumbnail Height"
|
||||
"thumbnailHeight" : "Thumbnail Height",
|
||||
"go_to_post": "Go to post"
|
||||
}
|
|
@ -38,6 +38,8 @@ var fillEmbedlyData = function (instance) {
|
|||
if (!$bodyField.val()) // if body field is empty, fill in body
|
||||
$bodyField.val(data.description);
|
||||
|
||||
data.url = url;
|
||||
|
||||
Telescope.callbacks.run("afterEmbedlyPrefill", data);
|
||||
|
||||
}
|
||||
|
|
|
@ -80,3 +80,13 @@ function addThumbnailClass (postClass, post) {
|
|||
}
|
||||
// add callback that adds "has-thumbnail" or "no-thumbnail" CSS classes
|
||||
Telescope.callbacks.add("postClass", addThumbnailClass);
|
||||
|
||||
function checkIfPreviouslyPosted (data) {
|
||||
Meteor.call("checkForDuplicates", data.url, function (error, result) {
|
||||
if (error) {
|
||||
Messages.flash(error.reason + '. <a href="'+FlowRouter.path("postPage", {_id: error.details})+'">'+i18n.t("go_to_post")+'</a>');
|
||||
}
|
||||
});
|
||||
}
|
||||
Telescope.callbacks.add("afterEmbedlyPrefill", checkIfPreviouslyPosted);
|
||||
|
||||
|
|
|
@ -13,3 +13,18 @@ FlowRouter.removeFromQueryArray = function (key, value) {
|
|||
params[key] = keyArray;
|
||||
FlowRouter.setQueryParams(params);
|
||||
}
|
||||
|
||||
Telescope.adminRoutes = FlowRouter.group({
|
||||
prefix: '/admin',
|
||||
name: 'admin'
|
||||
});
|
||||
|
||||
FlowRouter.notFound = {
|
||||
action: function() {
|
||||
BlazeLayout.render("layout", {main: "not_found"});
|
||||
}
|
||||
};
|
||||
|
||||
FlowRouter.triggers.exit([Messages.clearSeen]);
|
||||
FlowRouter.triggers.exit([Events.analyticsInit]); // will only run once thanks to _.once()
|
||||
FlowRouter.triggers.exit([Events.analyticsRequest]);
|
|
@ -1,4 +0,0 @@
|
|||
Telescope.adminRoutes = FlowRouter.group({
|
||||
prefix: '/admin',
|
||||
name: 'admin'
|
||||
});
|
|
@ -90,8 +90,7 @@ Package.onUse(function (api) {
|
|||
'lib/base.js',
|
||||
'lib/colors.js',
|
||||
'lib/icons.js',
|
||||
'lib/router/admin.js',
|
||||
'lib/router/query_arrays.js'
|
||||
'lib/router.js',
|
||||
], ['client', 'server']);
|
||||
|
||||
api.addFiles([
|
||||
|
|
|
@ -9,6 +9,7 @@ Messages = {
|
|||
},
|
||||
|
||||
clearSeen: function() {
|
||||
console.log("clearing messages…")
|
||||
this.collection.update({seen:true}, {$set: {show:false}}, {multi:true});
|
||||
}
|
||||
};
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
{{#if show}}
|
||||
<div class="grid">
|
||||
<div class="error {{type}}-message module">
|
||||
{{message}}
|
||||
{{{message}}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
<template name="post_edit">
|
||||
{{#if ready}}
|
||||
<div class="form-page post-edit">
|
||||
{{#if canEdit post}}
|
||||
{{#checker check="edit" doc=post message="sorry_you_cannot_edit_this_post"}}
|
||||
<div class="grid grid-module">
|
||||
{{> quickForm collection="Posts" doc=post id="editPostForm" template="bootstrap3-horizontal" label-class="control-label" input-col-class="controls" type="method-update" meteormethod="editPost" fields=postFields}}
|
||||
</div>
|
||||
{{else}}
|
||||
{{> no_rights message="sorry_you_cannot_edit_this_post"}}
|
||||
{{/if}}
|
||||
{{/checker}}
|
||||
</div>
|
||||
{{else}}
|
||||
{{> loading}}
|
||||
|
|
|
@ -97,19 +97,15 @@ Posts.helpers({isApproved: function () {return Posts.isApproved(this);}});
|
|||
* Check to see if post URL is unique.
|
||||
* We need the current user so we know who to upvote the existing post as.
|
||||
* @param {String} url
|
||||
* @param {Object} currentUser
|
||||
*/
|
||||
Posts.checkForSameUrl = function (url, currentUser) {
|
||||
Posts.checkForSameUrl = function (url) {
|
||||
|
||||
// check that there are no previous posts with the same link in the past 6 months
|
||||
var sixMonthsAgo = moment().subtract(6, 'months').toDate();
|
||||
var postWithSameLink = Posts.findOne({url: url, postedAt: {$gte: sixMonthsAgo}});
|
||||
|
||||
if (typeof postWithSameLink !== 'undefined') {
|
||||
Telescope.upvoteItem(Posts, postWithSameLink._id, currentUser);
|
||||
|
||||
// note: error.details returns undefined on the client, so add post ID to reason
|
||||
throw new Meteor.Error('603', i18n.t('this_link_has_already_been_posted') + '|' + postWithSameLink._id, postWithSameLink._id);
|
||||
throw new Meteor.Error('603', i18n.t('this_link_has_already_been_posted'), postWithSameLink._id);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -313,6 +313,10 @@ Meteor.methods({
|
|||
|
||||
Telescope.callbacks.runAsync("postDeleteAsync", post);
|
||||
|
||||
},
|
||||
|
||||
checkForDuplicates: function (url) {
|
||||
Posts.checkForSameUrl(url);
|
||||
}
|
||||
|
||||
});
|
||||
|
|
|
@ -5,4 +5,9 @@
|
|||
text-align:center;
|
||||
color:white;
|
||||
padding: 20px;
|
||||
a{
|
||||
&:link, &:hover{
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -61,5 +61,6 @@
|
|||
"invited" : "Invited",
|
||||
"uninvited" : "Uninvited",
|
||||
"filter_by" : "Filter by",
|
||||
"sort_by" : "Sort by"
|
||||
"sort_by" : "Sort by",
|
||||
"you_have_been_logged_out": "You have been logged out"
|
||||
}
|
|
@ -1,3 +1,6 @@
|
|||
// note: using collection helpers here is probably a bad idea,
|
||||
// because they'll throw an error when the user is undefined
|
||||
|
||||
/**
|
||||
* Telescope permissions
|
||||
* @namespace Users.can
|
||||
|
@ -20,6 +23,8 @@ Users.can.view = function (user) {
|
|||
}
|
||||
return true;
|
||||
};
|
||||
Users.helpers({canView: function () {return Users.can.view(this);}});
|
||||
|
||||
|
||||
Users.can.viewById = function (userId) {
|
||||
// if an invite is required to view, run permission check, else return true
|
||||
|
@ -28,6 +33,7 @@ Users.can.viewById = function (userId) {
|
|||
}
|
||||
return true;
|
||||
};
|
||||
Users.helpers({canViewById: function () {return Users.can.viewById(this);}});
|
||||
|
||||
Users.can.viewPendingPosts = function (user) {
|
||||
user = (typeof user === 'undefined') ? Meteor.user() : user;
|
||||
|
@ -38,7 +44,6 @@ Users.can.viewPendingPost = function (user, post) {
|
|||
return Users.is.owner(user, post) || Users.can.viewPendingPosts(user);
|
||||
};
|
||||
|
||||
|
||||
Users.can.viewRejectedPosts = function (user) {
|
||||
user = (typeof user === 'undefined') ? Meteor.user() : user;
|
||||
return Users.is.admin(user);
|
||||
|
@ -65,14 +70,17 @@ Users.can.post = function (user, returnError) {
|
|||
return true;
|
||||
}
|
||||
};
|
||||
Users.helpers({canPost: function () {return Users.can.post(this);}});
|
||||
|
||||
Users.can.comment = function (user, returnError) {
|
||||
return Users.can.post(user, returnError);
|
||||
};
|
||||
Users.helpers({canComment: function () {return Users.can.comment(this);}});
|
||||
|
||||
Users.can.vote = function (user, returnError) {
|
||||
return Users.can.post(user, returnError);
|
||||
};
|
||||
Users.helpers({canVote: function () {return Users.can.vote(this);}});
|
||||
|
||||
/**
|
||||
* Check if a user can edit a document
|
||||
|
@ -91,11 +99,13 @@ Users.can.edit = function (user, document) {
|
|||
|
||||
return adminCheck || ownerCheck;
|
||||
};
|
||||
Users.helpers({canEdit: function (document) {return Users.can.edit(this, document);}});
|
||||
|
||||
Users.can.editById = function (userId, document) {
|
||||
var user = Meteor.users.findOne(userId);
|
||||
return Users.can.edit(user, document);
|
||||
};
|
||||
Users.helpers({canEditById: function (document) {return Users.can.editById(this, document);}});
|
||||
|
||||
/**
|
||||
* Check if a user can submit a field
|
||||
|
@ -114,6 +124,7 @@ Users.can.submitField = function (user, field) {
|
|||
return adminCheck || memberCheck;
|
||||
|
||||
};
|
||||
Users.helpers({canSubmitField: function (field) {return Users.can.submitField(this, field);}});
|
||||
|
||||
/** @function
|
||||
* Check if a user can edit a field – for now, identical to Users.can.submitField
|
||||
|
@ -125,3 +136,5 @@ Users.can.editField = Users.can.submitField;
|
|||
Users.can.invite = function (user) {
|
||||
return Users.is.invited(user) || Users.is.admin(user);
|
||||
};
|
||||
Users.helpers({canInvite: function () {return Users.can.invite(this);}});
|
||||
|
||||
|
|
|
@ -23,13 +23,13 @@ FlowRouter.route('/account', {
|
|||
name: "userAccountShortcut",
|
||||
triggersEnter: [function(context, redirect) {
|
||||
redirect("userEdit", {_idOrSlug: Meteor.userId()});
|
||||
}],
|
||||
}]
|
||||
});
|
||||
|
||||
FlowRouter.route('/sign-out', {
|
||||
name: "signOut",
|
||||
action: function(params, queryParams) {
|
||||
Meteor.logout();
|
||||
BlazeLayout.render("layout", {main: "sign_out"});
|
||||
}
|
||||
triggersEnter: [function(context, redirect) {
|
||||
AccountsTemplates.logout();
|
||||
Messages.flash(i18n.t("you_have_been_logged_out"));
|
||||
}]
|
||||
});
|
Loading…
Add table
Reference in a new issue