Trust level 4: add ability to edit any post and see edit history

This commit is contained in:
Neil Lalonde 2014-03-13 10:47:37 -04:00
parent 50cc7dedb0
commit 283dc7dd2d
8 changed files with 88 additions and 16 deletions

View File

@ -350,14 +350,7 @@ Discourse.Post = Discourse.Model.extend({
var topic = this.get('topic'); var topic = this.get('topic');
return !topic.isReplyDirectlyBelow(this); return !topic.isReplyDirectlyBelow(this);
}.property('reply_count'), }.property('reply_count')
canViewEditHistory: function() {
return (Discourse.SiteSettings.edit_history_visible_to_public ||
(Discourse.User.current() &&
(Discourse.User.current().get('staff') || Discourse.User.current().get('id') === this.get('user_id'))));
}.property()
}); });
Discourse.Post.reopenClass({ Discourse.Post.reopenClass({

View File

@ -55,7 +55,7 @@
<div class='topic-meta-data-inside'> <div class='topic-meta-data-inside'>
{{#if hasHistory}} {{#if hasHistory}}
<div class='post-info edits'> <div class='post-info edits'>
{{#if canViewEditHistory}} {{#if can_view_edit_history}}
<a href='#' class="{{unbound historyHeat}}" {{action showHistory this}} title="{{i18n post.last_edited_on}} {{rawDate updated_at}}"> <a href='#' class="{{unbound historyHeat}}" {{action showHistory this}} title="{{i18n post.last_edited_on}} {{rawDate updated_at}}">
{{editCount}} {{editCount}}
<i class='fa fa-pencil'></i> <i class='fa fa-pencil'></i>

View File

@ -178,6 +178,7 @@ class PostsController < ApplicationController
def revisions def revisions
post_revision = find_post_revision_from_params post_revision = find_post_revision_from_params
guardian.ensure_can_see!(post_revision)
post_revision_serializer = PostRevisionSerializer.new(post_revision, scope: guardian, root: false) post_revision_serializer = PostRevisionSerializer.new(post_revision, scope: guardian, root: false)
render_json_dump(post_revision_serializer) render_json_dump(post_revision_serializer)
end end

View File

@ -45,7 +45,8 @@ class PostSerializer < BasicPostSerializer
:deleted_at, :deleted_at,
:deleted_by, :deleted_by,
:user_deleted, :user_deleted,
:edit_reason :edit_reason,
:can_view_edit_history
def moderator? def moderator?
@ -200,6 +201,10 @@ class PostSerializer < BasicPostSerializer
SiteSetting.enable_names? SiteSetting.enable_names?
end end
def can_view_edit_history
scope.can_view_post_revisions?(object)
end
private private
def post_actions def post_actions

View File

@ -69,7 +69,7 @@ module PostGuardain
# Editing Method # Editing Method
def can_edit_post?(post) def can_edit_post?(post)
is_staff? || (!post.topic.archived? && is_my_own?(post) && !post.user_deleted && !post.deleted_at && !post.edit_time_limit_expired?) is_staff? || @user.has_trust_level?(:elder) || (!post.topic.archived? && is_my_own?(post) && !post.user_deleted && !post.deleted_at && !post.edit_time_limit_expired?)
end end
# Deleting Methods # Deleting Methods
@ -111,8 +111,15 @@ module PostGuardain
def can_see_post_revision?(post_revision) def can_see_post_revision?(post_revision)
return false if post_revision.nil? return false if post_revision.nil?
can_view_post_revisions?(post_revision.post)
end
def can_view_post_revisions?(post)
return false if post.nil?
return true if SiteSetting.edit_history_visible_to_public return true if SiteSetting.edit_history_visible_to_public
authenticated? && (is_staff? || can_see_post?(post_revision.post)) authenticated? &&
(is_staff? || @user.has_trust_level?(:elder) || @user.id == post.user_id) &&
can_see_post?(post)
end end
def can_vote?(post, opts={}) def can_vote?(post, opts={})

View File

@ -8,6 +8,7 @@ describe Guardian do
let(:moderator) { build(:moderator) } let(:moderator) { build(:moderator) }
let(:admin) { build(:admin) } let(:admin) { build(:admin) }
let(:leader) { build(:user, trust_level: 3) } let(:leader) { build(:user, trust_level: 3) }
let(:elder) { build(:user, trust_level: 4) }
let(:another_admin) { build(:admin) } let(:another_admin) { build(:admin) }
let(:coding_horror) { build(:coding_horror) } let(:coding_horror) { build(:coding_horror) }
@ -259,7 +260,6 @@ describe Guardian do
end end
describe 'a Post' do describe 'a Post' do
let(:another_admin) { Fabricate(:admin) } let(:another_admin) { Fabricate(:admin) }
it 'correctly handles post visibility' do it 'correctly handles post visibility' do
post = Fabricate(:post) post = Fabricate(:post)
@ -279,8 +279,43 @@ describe Guardian do
Guardian.new(user).can_see?(post).should be_false Guardian.new(user).can_see?(post).should be_false
Guardian.new(admin).can_see?(post).should be_true Guardian.new(admin).can_see?(post).should be_true
end end
end
describe 'a PostRevision' do
let(:post_revision) { Fabricate(:post_revision) }
context 'edit_history_visible_to_public is true' do
before { SiteSetting.stubs(:edit_history_visible_to_public).returns(true) }
it 'is false for nil' do
Guardian.new.can_see?(nil).should be_false
end
it 'is true if not logged in' do
Guardian.new.can_see?(post_revision).should == true
end
it 'is true when logged in' do
Guardian.new(Fabricate(:user)).can_see?(post_revision).should == true
end
end
context 'edit_history_visible_to_public is false' do
before { SiteSetting.stubs(:edit_history_visible_to_public).returns(false) }
it 'is true for staff' do
Guardian.new(Fabricate(:admin)).can_see?(post_revision).should == true
Guardian.new(Fabricate(:moderator)).can_see?(post_revision).should == true
end
it 'is true for trust level 4' do
Guardian.new(Fabricate(:elder)).can_see?(post_revision).should == true
end
it 'is false for trust level lower than 4' do
Guardian.new(Fabricate(:leader)).can_see?(post_revision).should == false
end
end
end end
end end
@ -551,6 +586,10 @@ describe Guardian do
Guardian.new(admin).can_edit?(post).should be_true Guardian.new(admin).can_edit?(post).should be_true
end end
it 'returns true as a trust level 4 user' do
Guardian.new(elder).can_edit?(post).should be_true
end
context 'post is older than post_edit_time_limit' do context 'post is older than post_edit_time_limit' do
let(:old_post) { build(:post, topic: topic, user: topic.user, created_at: 6.minutes.ago) } let(:old_post) { build(:post, topic: topic, user: topic.user, created_at: 6.minutes.ago) }
before do before do

View File

@ -431,7 +431,13 @@ describe PostsController do
before { SiteSetting.stubs(:edit_history_visible_to_public).returns(false) } before { SiteSetting.stubs(:edit_history_visible_to_public).returns(false) }
it "ensures anonymous can not see the revisions" do it "ensures anonymous cannot see the revisions" do
xhr :get, :revisions, post_id: post_revision.post_id, revision: post_revision.number
response.should be_forbidden
end
it "ensures regular user cannot see the revisions" do
u = log_in(:user)
xhr :get, :revisions, post_id: post_revision.post_id, revision: post_revision.number xhr :get, :revisions, post_id: post_revision.post_id, revision: post_revision.number
response.should be_forbidden response.should be_forbidden
end end
@ -444,11 +450,18 @@ describe PostsController do
it "ensures poster can see the revisions" do it "ensures poster can see the revisions" do
user = log_in(:active_user) user = log_in(:active_user)
pr = Fabricate(:post_revision, user: user) post = Fabricate(:post, user: user)
pr = Fabricate(:post_revision, user: user, post: post)
xhr :get, :revisions, post_id: pr.post_id, revision: pr.number xhr :get, :revisions, post_id: pr.post_id, revision: pr.number
response.should be_success response.should be_success
end end
it "ensures trust level 4 can see the revisions" do
log_in(:elder)
xhr :get, :revisions, post_id: post_revision.post_id, revision: post_revision.number
response.should be_success
end
end end
context "when edit history is visible to everyone" do context "when edit history is visible to everyone" do

View File

@ -60,5 +60,19 @@ Fabricator(:active_user, from: :user) do
password 'myawesomepassword' password 'myawesomepassword'
trust_level TrustLevel.levels[:basic] trust_level TrustLevel.levels[:basic]
active true active true
bio_raw "Don't as me about my dad!" bio_raw "Don't ask me about my dad!"
end end
Fabricator(:leader, from: :user) do
name 'Leader McLeaderman'
username { sequence(:username) { |i| "leader#{i}" } }
email { sequence(:email) { |i| "leader#{i}@leaderfun.com" } }
trust_level TrustLevel.levels[:leader]
end
Fabricator(:elder, from: :user) do
name 'Elder McElderson'
username { sequence(:username) { |i| "elder#{i}" } }
email { sequence(:email) { |i| "elder#{i}@elderfun.com" } }
trust_level TrustLevel.levels[:elder]
end