From 2d904ade6dfb260c85e2437247eafe86c7ade3b9 Mon Sep 17 00:00:00 2001 From: Dan Ungureanu Date: Mon, 12 Jul 2021 00:57:38 +0300 Subject: [PATCH] FIX: Let staged users choose their username (#13678) When a staged user tried to redeem an invite, a different username was suggested and manually typing the staged username failed because the username was not available. --- .../discourse/app/controllers/invites-show.js | 1 + app/controllers/invites_controller.rb | 1 + app/models/invite_redeemer.rb | 11 +++--- spec/requests/invites_controller_spec.rb | 34 +++++++++++++++++++ 4 files changed, 41 insertions(+), 6 deletions(-) diff --git a/app/assets/javascripts/discourse/app/controllers/invites-show.js b/app/assets/javascripts/discourse/app/controllers/invites-show.js index 49f9f7998be..278b6c01096 100644 --- a/app/assets/javascripts/discourse/app/controllers/invites-show.js +++ b/app/assets/javascripts/discourse/app/controllers/invites-show.js @@ -28,6 +28,7 @@ export default Controller.extend( invitedBy: readOnly("model.invited_by"), email: alias("model.email"), + accountEmail: alias("email"), hiddenEmail: alias("model.hidden_email"), emailVerifiedByLink: alias("model.email_verified_by_link"), accountUsername: alias("model.username"), diff --git a/app/controllers/invites_controller.rb b/app/controllers/invites_controller.rb index 5d84267d841..f883e4c4d53 100644 --- a/app/controllers/invites_controller.rb +++ b/app/controllers/invites_controller.rb @@ -74,6 +74,7 @@ class InvitesController < ApplicationController } if staged_user = User.where(staged: true).with_email(invite.email).first + info[:username] = staged_user.username info[:user_fields] = staged_user.user_fields end diff --git a/app/models/invite_redeemer.rb b/app/models/invite_redeemer.rb index a6353d18435..9dfc743cbd3 100644 --- a/app/models/invite_redeemer.rb +++ b/app/models/invite_redeemer.rb @@ -13,17 +13,16 @@ InviteRedeemer = Struct.new(:invite, :email, :username, :name, :password, :user_ # extracted from User cause it is very specific to invites def self.create_user_from_invite(email:, invite:, username: nil, name: nil, password: nil, user_custom_fields: nil, ip_address: nil, session: nil, email_token: nil) - user = User.where(staged: true).with_email(email.strip.downcase).first - user.unstage! if user - - user ||= User.new - - if username && UsernameValidator.new(username).valid_format? && User.username_available?(username) + if username && UsernameValidator.new(username).valid_format? && User.username_available?(username, email) available_username = username else available_username = UserNameSuggester.suggest(email) end + user = User.where(staged: true).with_email(email.strip.downcase).first + user.unstage! if user + user ||= User.new + user.attributes = { email: email, username: available_username, diff --git a/spec/requests/invites_controller_spec.rb b/spec/requests/invites_controller_spec.rb index 972715b6449..4c8efebe093 100644 --- a/spec/requests/invites_controller_spec.rb +++ b/spec/requests/invites_controller_spec.rb @@ -37,6 +37,7 @@ describe InvitesController do expect(response.body).to have_tag("div#data-preloaded") do |element| json = JSON.parse(element.current_scope.attribute('data-preloaded').value) invite_info = JSON.parse(json['invite_info']) + expect(invite_info['username']).to eq(staged_user.username) expect(invite_info['user_fields'][user_field.id.to_s]).to eq('some value') end end @@ -757,6 +758,39 @@ describe InvitesController do expect(response.parsed_body['redirect_to']).to eq("/") end end + + context 'staged user' do + fab!(:invite) { Fabricate(:invite) } + fab!(:staged_user) { Fabricate(:user, staged: true, email: invite.email) } + + it 'can keep the old username' do + old_username = staged_user.username + + put "/invites/show/#{invite.invite_key}.json", params: { + username: staged_user.username, + password: "Password123456", + email_token: invite.email_token, + } + + expect(response.status).to eq(200) + expect(invite.reload.redeemed?).to be_truthy + user = invite.invited_users.first.user + expect(user.username).to eq(old_username) + end + + it 'can change the username' do + put "/invites/show/#{invite.invite_key}.json", params: { + username: "new_username", + password: "Password123456", + email_token: invite.email_token, + } + + expect(response.status).to eq(200) + expect(invite.reload.redeemed?).to be_truthy + user = invite.invited_users.first.user + expect(user.username).to eq("new_username") + end + end end context '#destroy_all_expired' do