adding permission check for post and comment edit

This commit is contained in:
Sacha Greif 2012-10-10 10:48:14 +09:00
parent 1b4d48577c
commit b3c932b2ab
9 changed files with 105 additions and 60 deletions

View file

@ -127,4 +127,11 @@ Handlebars.registerHelper('isAdmin', function(showError) {
throwError('Sorry, you do not have access to this page'); throwError('Sorry, you do not have access to this page');
return false; return false;
} }
});
Handlebars.registerHelper('canEdit', function(collectionName, action) {
var action = (typeof action !== 'string') ? null : action;
var collection = (typeof collectionName !== 'string') ? Posts : eval(collectionName);
var itemId = (collectionName==="Posts") ? Session.get('selectedPostId') : Session.get('selectedCommentId');
var item=collection.findOne(itemId);
return item && canEdit(Meteor.user(), item, action);
}); });

View file

@ -1,18 +1,20 @@
<template name="comment_edit"> <template name="comment_edit">
<div class="grid submit"> {{#if canEdit Comments replace}}
{{#with comment}} <div class="grid submit">
<form class="grid-block form-horizontal"> {{#with comment}}
{{#constant}} <form class="grid-block form-horizontal">
<div class="control-group"> {{#constant}}
<label class="control-label">Comment</label> <div class="control-group">
<div class="controls" id="editor"><textarea id="body" value="" class="input-xlarge">{{body}}</textarea></div> <label class="control-label">Comment</label>
</div> <div class="controls" id="editor"><textarea id="body" value="" class="input-xlarge">{{body}}</textarea></div>
{{/constant}} </div>
<div class="form-actions"> {{/constant}}
<a class="delete-link" href="/comments/deleted">Delete Comment</a> <div class="form-actions">
<input type="submit" value="Submit" title="(⌘+enter)" /> <a class="delete-link" href="/comments/deleted">Delete Comment</a>
</div> <input type="submit" value="Submit" title="(⌘+enter)" />
</form> </div>
{{/with}} </form>
</div> {{/with}}
</div>
{{/if}}
</template> </template>

View file

@ -0,0 +1,2 @@
<template name="no_rights">
</template>

View file

View file

@ -1,42 +1,44 @@
<template name="post_edit"> <template name="post_edit">
<div class="grid submit"> {{#if canEdit "Posts" "replace"}}
{{#with post}} <div class="grid submit">
<form class="grid-block form-horizontal"> {{#with post}}
<div class="control-group"> <form class="grid-block form-horizontal">
<label class="control-label">Title</label> <div class="control-group">
<div class="controls"><input id="title" type="text" value="{{headline}}" /></div> <label class="control-label">Title</label>
</div> <div class="controls"><input id="title" type="text" value="{{headline}}" /></div>
<div class="control-group">
<label class="control-label">URL</label>
<div class="controls"><input id="url" type="text" value="{{url}}" /></div>
</div>
<div class="control-group">
<label class="control-label">Body</label>
<div class="controls" id="editor"><textarea id="body" value="" class="input-xlarge">{{body}}</textarea></div>
</div>
<div class="control-group">
<label class="control-label">Category</label>
<div class="controls">
{{#each categories}}
<label class="radio inline">
<input id="category_{{_id}}" type="checkbox" value="{{name}}" name="category" {{#if isChecked }} checked {{/if}}/> {{name}}
</label>
{{/each}}
</div> </div>
</div> <div class="control-group">
{{#if currentUser.isAdmin}} <label class="control-label">URL</label>
<div class="control-group"> <div class="controls"><input id="url" type="text" value="{{url}}" /></div>
<label class="control-label">Sticky?</label> </div>
<div class="controls"> <div class="control-group">
<input type="radio" name="sticky" id="sticky" {{#if sticky}}checked{{/if}} /> <label class="control-label">Body</label>
</div> <div class="controls" id="editor"><textarea id="body" value="" class="input-xlarge">{{body}}</textarea></div>
</div>
<div class="control-group">
<label class="control-label">Category</label>
<div class="controls">
{{#each categories}}
<label class="radio inline">
<input id="category_{{_id}}" type="checkbox" value="{{name}}" name="category" {{#if isChecked }} checked {{/if}}/> {{name}}
</label>
{{/each}}
</div> </div>
{{/if}} </div>
<div class="form-actions"> {{#if isAdmin}}
<a class="delete-link" href="/posts/deleted">Delete Post</a> <div class="control-group">
<input type="submit" value="Submit" /> <label class="control-label">Sticky?</label>
</div> <div class="controls">
</form> <input type="radio" name="sticky" id="sticky" {{#if sticky}}checked{{/if}} />
{{/with}} </div>
</div> </div>
{{/if}}
<div class="form-actions">
<a class="delete-link" href="/posts/deleted">Delete Post</a>
<input type="submit" value="Submit" />
</div>
</form>
{{/with}}
</div>
{{/if}}
</template> </template>

View file

@ -50,7 +50,10 @@ Template.post_edit.rendered = function(){
Template.post_edit.events = { Template.post_edit.events = {
'click input[type=submit]': function(e, instance){ 'click input[type=submit]': function(e, instance){
e.preventDefault(); e.preventDefault();
if(!Meteor.user()) throw 'You must be logged in.'; if(!Meteor.user()){
throwError('You must be logged in.');
return false;
}
var selectedPostId=Session.get('selectedPostId'); var selectedPostId=Session.get('selectedPostId');
var title= $('#title').val(); var title= $('#title').val();
@ -75,11 +78,15 @@ Template.post_edit.events = {
, categories: categories , categories: categories
} }
} }
,function(error){
if(error){
throwError(error.reason);
}else{
trackEvent("edit post", {'postId': selectedPostId});
Router.navigate("posts/"+selectedPostId, {trigger:true});
}
}
); );
trackEvent("edit post", {'postId': selectedPostId});
Router.navigate("posts/"+selectedPostId, {trigger:true});
} }
, 'click .delete-link': function(e){ , 'click .delete-link': function(e){

View file

@ -13,7 +13,7 @@ Meteor.methods({
post = _.extend(post, { post = _.extend(post, {
userId: user._id, userId: user._id,
author: user.username, author: getDisplayName(user),
submitted: new Date().getTime(), submitted: new Date().getTime(),
votes: 0, votes: 0,
comments: 0, comments: 0,

View file

@ -153,4 +153,25 @@ canDownvote = function(user, collection, action){
var user=(typeof user === 'undefined') ? Meteor.user() : user; var user=(typeof user === 'undefined') ? Meteor.user() : user;
var action=(typeof action === 'undefined') ? null : action; var action=(typeof action === 'undefined') ? null : action;
return canPost(user, action); return canPost(user, action);
}
canEdit = function(user, item, action){
var user=(typeof user === 'undefined') ? Meteor.user() : user;
var action=(typeof action === 'undefined') ? null : action;
try{
if(!user || !item || user._id!==item.userId){
throw "no_rights";
}else{
return true;
}
}catch(error){
if(action){
switch(error){
case "no_rights":
throwError("Sorry, you do not have the rights to edit this item.");
action=='replace' ? Router.goto('no_rights') : Router.navigate('no_rights', {trigger : true});
break;
}
}
return false;
}
} }

View file

@ -80,12 +80,14 @@ Meteor.startup(function(){
if(isAdminById(userId) || (docs[0].user_id && docs[0].user_id==userId)){ if(isAdminById(userId) || (docs[0].user_id && docs[0].user_id==userId)){
return true; return true;
} }
throw new Meteor.Error(403, 'You do not have permission to edit this post');
return false; return false;
} }
, remove: function(userId, docs){ , remove: function(userId, docs){
if(isAdminById(userId) || (docs[0].user_id && docs[0].user_id==userId)){ if(isAdminById(userId) || (docs[0].user_id && docs[0].user_id==userId)){
return true; return true;
} }
throw new Meteor.Error(403, 'You do not have permission to delete this post');
return false; } return false; }
}); });
}); });
@ -110,11 +112,13 @@ Meteor.startup(function(){
if(isAdminById(userId) || (docs[0].user_id && docs[0].user_id==userId)){ if(isAdminById(userId) || (docs[0].user_id && docs[0].user_id==userId)){
return true; return true;
} }
throw new Meteor.Error(403, 'You do not have permission to edit this comment');
return false; return false;
} }
, remove: function(userId, docs){ , remove: function(userId, docs){
if(isAdminById(userId) || (docs[0].user_id && docs[0].user_id==userId)){ if(isAdminById(userId) || (docs[0].user_id && docs[0].user_id==userId)){
return true; return true;
throw new Meteor.Error(403, 'You do not have permission to delete this comment');
} }
return false; return false;
} }