FEATURE: Log username changes by staff

Also fix the tests for changing username
This commit is contained in:
riking 2015-01-16 14:30:46 -08:00
parent 18215f90d0
commit 1ab0d6bd82
6 changed files with 59 additions and 10 deletions

View file

@ -88,7 +88,8 @@ class UsersController < ApplicationController
user = fetch_user_from_params user = fetch_user_from_params
guardian.ensure_can_edit_username!(user) guardian.ensure_can_edit_username!(user)
result = user.change_username(params[:new_username]) # TODO proper error surfacing (result is a Model#save call)
result = user.change_username(params[:new_username], current_user)
raise Discourse::InvalidParameters.new(:new_username) unless result raise Discourse::InvalidParameters.new(:new_username) unless result
render json: { render json: {

View file

@ -185,7 +185,11 @@ class User < ActiveRecord::Base
Jobs.enqueue(:send_system_message, user_id: id, message_type: message_type) Jobs.enqueue(:send_system_message, user_id: id, message_type: message_type)
end end
def change_username(new_username) def change_username(new_username, actor=nil)
if actor && actor != self
StaffActionLogger.new(actor).log_username_change(self, self.username, new_username)
end
self.username = new_username self.username = new_username
save save
end end

View file

@ -34,7 +34,8 @@ class UserHistory < ActiveRecord::Base
:delete_post, :delete_post,
:delete_topic, :delete_topic,
:impersonate, :impersonate,
:roll_up) :roll_up,
:change_username)
end end
# Staff actions is a subset of all actions, used to audit actions taken by staff users. # Staff actions is a subset of all actions, used to audit actions taken by staff users.
@ -52,7 +53,8 @@ class UserHistory < ActiveRecord::Base
:delete_post, :delete_post,
:delete_topic, :delete_topic,
:impersonate, :impersonate,
:roll_up] :roll_up,
:change_username]
end end
def self.staff_action_ids def self.staff_action_ids

View file

@ -100,6 +100,16 @@ class StaffActionLogger
})) }))
end end
def log_username_change(user, old_username, new_username, opts={})
raise Discourse::InvalidParameters.new('user is nil') unless user
UserHistory.create( params(opts).merge({
action: UserHistory.actions[:change_username],
target_user_id: user.id,
previous_value: old_username,
new_value: new_username
}))
end
def log_user_suspend(user, reason, opts={}) def log_user_suspend(user, reason, opts={})
raise Discourse::InvalidParameters.new('user is nil') unless user raise Discourse::InvalidParameters.new('user is nil') unless user
UserHistory.create( params(opts).merge({ UserHistory.create( params(opts).merge({

View file

@ -1863,6 +1863,7 @@ en:
actions: actions:
delete_user: "delete user" delete_user: "delete user"
change_trust_level: "change trust level" change_trust_level: "change trust level"
change_username: "change username"
change_site_setting: "change site setting" change_site_setting: "change site setting"
change_site_customization: "change site customization" change_site_customization: "change site customization"
delete_site_customization: "delete site customization" delete_site_customization: "delete site customization"

View file

@ -612,28 +612,59 @@ describe UsersController do
end end
context 'while logged in' do context 'while logged in' do
let!(:user) { log_in } let(:old_username) { "OrigUsrname" }
let(:new_username) { "#{user.username}1234" } let(:new_username) { "#{old_username}1234" }
let(:user) { Fabricate(:user, username: old_username) }
before do
user.username = old_username
log_in_user(user)
end
it 'raises an error without a new_username param' do it 'raises an error without a new_username param' do
expect { xhr :put, :username, username: user.username }.to raise_error(ActionController::ParameterMissing) expect { xhr :put, :username, username: user.username }.to raise_error(ActionController::ParameterMissing)
user.reload.username.should == old_username
end end
it 'raises an error when you don\'t have permission to change the username' do it 'raises an error when you don\'t have permission to change the username' do
Guardian.any_instance.expects(:can_edit_username?).with(user).returns(false) Guardian.any_instance.expects(:can_edit_username?).with(user).returns(false)
xhr :put, :username, username: user.username, new_username: new_username xhr :put, :username, username: user.username, new_username: new_username
expect(response).to be_forbidden expect(response).to be_forbidden
user.reload.username.should == old_username
end end
# Bad behavior, this should give a real JSON error, not an InvalidParameters
it 'raises an error when change_username fails' do it 'raises an error when change_username fails' do
User.any_instance.expects(:change_username).with(new_username).returns(false) User.any_instance.expects(:save).returns(false)
expect { xhr :put, :username, username: user.username, new_username: new_username }.to raise_error(Discourse::InvalidParameters) expect { xhr :put, :username, username: user.username, new_username: new_username }.to raise_error(Discourse::InvalidParameters)
user.reload.username.should == old_username
end end
it 'should succeed when the change_username returns true' do it 'should succeed in normal circumstances' do
User.any_instance.expects(:change_username).with(new_username).returns(true)
xhr :put, :username, username: user.username, new_username: new_username xhr :put, :username, username: user.username, new_username: new_username
expect(response).to be_success response.should be_success
user.reload.username.should == new_username
end
pending 'should fail if the user is old', 'ensure_can_edit_username! is not throwing' do
# Older than the change period and >1 post
user.created_at = Time.now - (SiteSetting.username_change_period + 1).days
user.stubs(:post_count).returns(200)
Guardian.new(user).can_edit_username?(user).should == false
xhr :put, :username, username: user.username, new_username: new_username
response.should be_forbidden
user.reload.username.should == old_username
end
it 'should create a staff action log when a staff member changes the username' do
acting_user = Fabricate(:admin)
log_in_user(acting_user)
xhr :put, :username, username: user.username, new_username: new_username
response.should be_success
UserHistory.where(action: UserHistory.actions[:change_username], target_user_id: user.id, acting_user_id: acting_user.id).should be_present
user.reload.username.should == new_username
end end
it 'should return a JSON response with the updated username' do it 'should return a JSON response with the updated username' do