Back end - temporary boosting of trust levels

This commit is contained in:
Navin 2013-07-03 10:27:40 +02:00
parent f92d9cec47
commit 3da37506da
9 changed files with 139 additions and 7 deletions

View File

@ -70,10 +70,7 @@ Discourse.AdminUser = Discourse.User.extend({
trustLevels: function() {
var site = Discourse.Site.instance();
// downgrading trust levels is not supported
var current = this.get('trust_level');
var levels = site.get('trust_levels');
return jQuery.grep(levels, function(e) { return e.id >= current })
return site.get('trust_levels');
}.property('trust_level'),
dirty: function() {
@ -89,7 +86,7 @@ Discourse.AdminUser = Discourse.User.extend({
window.location.reload();
}, function(e) {
// failure
var error = Em.String.i18n('admin.user.trustlevel_change_failed', { error: "http: " + e.status + " - " + e.body });
var error = Em.String.i18n('admin.user.trust_level_change_failed', { error: "http: " + e.status + " - " + e.body });
bootbox.alert(error);
});
},

View File

@ -1,9 +1,10 @@
require_dependency 'user_destroyer'
require_dependency 'admin_user_index_query'
require_dependency 'boost_trust_level'
class Admin::UsersController < Admin::AdminController
before_filter :fetch_user, only: [:ban, :unban, :refresh_browsers, :revoke_admin, :grant_admin, :revoke_moderation, :grant_moderation, :approve, :activate, :deactivate, :block, :unblock]
before_filter :fetch_user, only: [:ban, :unban, :refresh_browsers, :revoke_admin, :grant_admin, :revoke_moderation, :grant_moderation, :approve, :activate, :deactivate, :block, :unblock, :trust_level]
def index
query = ::AdminUserIndexQuery.new(params)
@ -69,6 +70,12 @@ class Admin::UsersController < Admin::AdminController
render_serialized(@user, AdminUserSerializer)
end
def trust_level
guardian.ensure_can_change_trust_level!(@user)
BoostTrustLevel.new(@user, params[:level]).save!
render_serialized(@user, AdminUserSerializer)
end
def approve
guardian.ensure_can_approve!(@user)
@user.approve(current_user)

View File

@ -1209,7 +1209,7 @@ en:
deactivate_explanation: "A deactivated user must re-validate their email."
banned_explanation: "A banned user can't log in."
block_explanation: "A blocked user can't post or start topics."
trust_level_change_failed: "There was a problem changing the user's trust level."
site_content:
none: "Choose a type of content to begin editing."

View File

@ -134,6 +134,8 @@ en:
title: "leader"
elder:
title: "elder"
change_failed_explanation: "You attempted to demote %{user_name} to '%{new_trust_level}'. However their trust level is already '%{current_trust_level}'. %{user_name} will remain at '%{current_trust_level}'"
rate_limiter:
too_many_requests: "You're doing that too often. Please wait %{time_left} before trying again."

View File

@ -49,6 +49,7 @@ Discourse::Application.routes.draw do
put 'deactivate'
put 'block'
put 'unblock'
put 'trust_level'
end
resources :impersonate, constraints: AdminConstraint.new

40
lib/boost_trust_level.rb Normal file
View File

@ -0,0 +1,40 @@
require_dependency 'promotion'
class BoostTrustLevel
def initialize(user, level)
@user = user
@level = level.to_i
@promotion = Promotion.new(@user)
@trust_levels = TrustLevel.levels
end
def save!
if @level < @user.trust_level
demote!
else
@user.update_attributes!(trust_level: @level)
end
end
protected
def demote!
current_trust_level = @user.trust_level
@user.update_attributes!(trust_level: @level)
if @promotion.review
@user.update_attributes!(trust_level: current_trust_level)
raise Discourse::InvalidAccess.new, I18n.t('trust_levels.change_failed_explanation',
user_name: @user.name,
new_trust_level: trust_level_lookup(@level),
current_trust_level: trust_level_lookup(current_trust_level))
else
true
end
end
def trust_level_lookup(level)
@trust_levels.key(level).id2name
end
end

View File

@ -137,6 +137,10 @@ class Guardian
user && is_staff?
end
def can_change_trust_level?(user)
can_administer?(user)
end
def can_block_user?(user)
user && is_staff? && not(user.staff?)
end

View File

@ -0,0 +1,48 @@
require 'spec_helper'
require 'boost_trust_level'
describe BoostTrustLevel do
let(:user) { Fabricate(:user) }
it "should upgrade the trust level of a user" do
boostr = BoostTrustLevel.new(user, TrustLevel.levels[:basic])
boostr.save!.should be_true
user.trust_level.should == TrustLevel.levels[:basic]
end
describe "demotions" do
before { user.update_attributes(trust_level: TrustLevel.levels[:newuser]) }
context "for a user that has not done the requisite things to attain their trust level" do
before do
# scenario: admin mistakenly promotes user's trust level
user.update_attributes(trust_level: TrustLevel.levels[:basic])
end
it "should demote the user" do
boostr = BoostTrustLevel.new(user, TrustLevel.levels[:newuser])
boostr.save!.should be_true
user.trust_level.should == TrustLevel.levels[:newuser]
end
end
context "for a user that has done the requisite things to attain their trust level" do
before do
user.topics_entered = SiteSetting.basic_requires_topics_entered + 1
user.posts_read_count = SiteSetting.basic_requires_read_posts + 1
user.time_read = SiteSetting.basic_requires_time_spent_mins * 60
user.save!
user.update_attributes(trust_level: TrustLevel.levels[:basic])
end
it "should not demote the user" do
boostr = BoostTrustLevel.new(user, TrustLevel.levels[:newuser])
expect { boostr.save! }.to raise_error(Discourse::InvalidAccess, "You attempted to demote #{user.name} to 'newuser'. However their trust level is already 'basic'. #{user.name} will remain at 'basic'")
user.trust_level.should == TrustLevel.levels[:basic]
end
end
end
end

View File

@ -120,6 +120,39 @@ describe Admin::UsersController do
end
end
context '.trust_level' do
before do
@another_user = Fabricate(:coding_horror)
end
it "raises an error when the user doesn't have permission" do
Guardian.any_instance.expects(:can_change_trust_level?).with(@another_user).returns(false)
xhr :put, :trust_level, user_id: @another_user.id
response.should be_forbidden
end
it "returns a 404 if the username doesn't exist" do
xhr :put, :trust_level, user_id: 123123
response.should be_forbidden
end
it "upgrades the user's trust level" do
xhr :put, :trust_level, user_id: @another_user.id, level: 2
@another_user.reload
@another_user.trust_level.should == 2
end
it "raises an error when demoting a user below their current trust level" do
@another_user.topics_entered = SiteSetting.basic_requires_topics_entered + 1
@another_user.posts_read_count = SiteSetting.basic_requires_read_posts + 1
@another_user.time_read = SiteSetting.basic_requires_time_spent_mins * 60
@another_user.save!
@another_user.update_attributes(trust_level: TrustLevel.levels[:basic])
xhr :put, :trust_level, user_id: @another_user.id, level: TrustLevel.levels[:newuser]
response.should be_forbidden
end
end
describe '.revoke_moderation' do
before do
@moderator = Fabricate(:moderator)