diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index bef1963ed..255904119 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -96,6 +96,9 @@ class UsersController < ApplicationController def check_username params.require(:username) + # The special case where someone is changing the case of their own username + return render(json: {available: true}) if current_user and params[:username].downcase == current_user.username.downcase + validator = UsernameValidator.new(params[:username]) if !validator.valid_format? render json: {errors: validator.errors} diff --git a/app/models/user.rb b/app/models/user.rb index 5e313e0c2..a9a45917e 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -159,9 +159,10 @@ class User < ActiveRecord::Base end def change_username(new_username) - current_username, self.username = username, new_username + current_username = self.username + self.username = new_username - if SiteSetting.call_discourse_hub? && valid? + if current_username.downcase != new_username.downcase && SiteSetting.call_discourse_hub? && valid? begin DiscourseHub.change_nickname(current_username, new_username) rescue DiscourseHub::NicknameUnavailable @@ -566,7 +567,8 @@ class User < ActiveRecord::Base def username_validator username_format_validator || begin lower = username.downcase - if username_changed? && User.where(username_lower: lower).exists? + existing = User.where(username_lower: lower).first + if username_changed? && existing && existing.id != self.id errors.add(:username, I18n.t(:'user.username.unique')) end end diff --git a/spec/controllers/users_controller_spec.rb b/spec/controllers/users_controller_spec.rb index feb899db7..0587cef32 100644 --- a/spec/controllers/users_controller_spec.rb +++ b/spec/controllers/users_controller_spec.rb @@ -772,6 +772,26 @@ describe UsersController do json['errors'][0].should_not be_nil end end + + describe 'different case of existing username' do + context "it's my username" do + let!(:user) { Fabricate(:user, username: 'hansolo') } + before do + log_in_user(user) + xhr :get, :check_username, username: 'HanSolo' + end + include_examples 'when username is available everywhere' + end + + context "it's someone else's username" do + let!(:user) { Fabricate(:user, username: 'hansolo') } + before do + log_in + xhr :get, :check_username, username: 'HanSolo' + end + include_examples 'when username is unavailable locally' + end + end end describe '.invited' do diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index d26be8d7f..97a665c15 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -196,6 +196,19 @@ describe User do end end + describe 'change the case of my username' do + let!(:myself) { Fabricate(:user, username: 'hansolo') } + + it 'should return true' do + myself.change_username('HanSolo').should be_true + end + + it 'should change the username' do + myself.change_username('HanSolo') + myself.reload.username.should == 'HanSolo' + end + end + end describe 'delete posts' do