mirror of
https://github.com/codeninjasllc/discourse.git
synced 2024-11-27 17:46:05 -05:00
Refactor user controller, create action, mostly.
The gist of the commit are a few improvements in the create action, where: * long boolean statemenst have been wrapped in smaller more readable methods. * the 3rd party user info creation has been extracted (still in controller) * a small helper method for creating a new user from params (to reduce visual clutter) * specs have been added where I came across untested methods/branches Other changes are more trivial like formatting and whitespace fixes. Hope this helps. Regards.
This commit is contained in:
parent
4413d2a92b
commit
3dcb1905e3
3 changed files with 178 additions and 63 deletions
|
@ -140,83 +140,83 @@ class UsersController < ApplicationController
|
||||||
|
|
||||||
def create
|
def create
|
||||||
|
|
||||||
if params[:password_confirmation] != honeypot_value || params[:challenge] != challenge_value.try(:reverse)
|
if honeypot_or_challenge_fails?(params)
|
||||||
# Don't give any indication that we caught you in the honeypot
|
# Don't give any indication that we caught you in the honeypot
|
||||||
return render(json: {success: true, active: false, message: I18n.t("login.activate_email", email: params[:email]) })
|
honey_pot_response = {
|
||||||
|
success: true,
|
||||||
|
active: false,
|
||||||
|
message: I18n.t("login.activate_email", email: params[:email])
|
||||||
|
}
|
||||||
|
return render(json: honey_pot_response)
|
||||||
end
|
end
|
||||||
|
|
||||||
user = User.new
|
user = User.new_from_params(params)
|
||||||
user.name = params[:name]
|
|
||||||
user.email = params[:email]
|
|
||||||
user.password = params[:password]
|
|
||||||
user.username = params[:username]
|
|
||||||
|
|
||||||
auth = session[:authentication]
|
auth = session[:authentication]
|
||||||
if auth && auth[:email] == params[:email] && auth[:email_valid]
|
if valid_session_authentication?(auth, params[:email])
|
||||||
user.active = true
|
user.active = true
|
||||||
end
|
end
|
||||||
user.password_required! unless auth
|
user.password_required! unless auth
|
||||||
|
|
||||||
DiscourseHub.register_nickname( user.username, user.email ) if user.valid? && SiteSetting.call_discourse_hub?
|
if user.valid? && SiteSetting.call_discourse_hub?
|
||||||
|
DiscourseHub.register_nickname(user.username, user.email)
|
||||||
|
end
|
||||||
|
|
||||||
if user.save
|
if user.save
|
||||||
|
|
||||||
msg = nil
|
msg = nil
|
||||||
active_result = user.active?
|
active_user = user.active?
|
||||||
if active_result
|
|
||||||
|
|
||||||
|
if active_user
|
||||||
# If the user is active (remote authorized email)
|
# If the user is active (remote authorized email)
|
||||||
if SiteSetting.must_approve_users?
|
if SiteSetting.must_approve_users?
|
||||||
msg = I18n.t("login.wait_approval")
|
msg = I18n.t("login.wait_approval")
|
||||||
active_result = false
|
active_user = false
|
||||||
else
|
else
|
||||||
log_on_user(user)
|
log_on_user(user)
|
||||||
user.enqueue_welcome_message('welcome_user')
|
user.enqueue_welcome_message('welcome_user')
|
||||||
msg = I18n.t("login.active")
|
msg = I18n.t("login.active")
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
msg = I18n.t("login.activate_email", email: user.email)
|
msg = I18n.t("login.activate_email", email: user.email)
|
||||||
Jobs.enqueue(:user_email, type: :signup, user_id: user.id, email_token: user.email_tokens.first.token)
|
Jobs.enqueue(
|
||||||
end
|
:user_email, type: :signup, user_id: user.id,
|
||||||
|
email_token: user.email_tokens.first.token
|
||||||
# Create auth records
|
)
|
||||||
if auth.present?
|
|
||||||
if auth[:twitter_user_id] && auth[:twitter_screen_name] && TwitterUserInfo.find_by_twitter_user_id(auth[:twitter_user_id]).nil?
|
|
||||||
TwitterUserInfo.create(user_id: user.id, screen_name: auth[:twitter_screen_name], twitter_user_id: auth[:twitter_user_id])
|
|
||||||
end
|
|
||||||
|
|
||||||
if auth[:facebook].present? && FacebookUserInfo.find_by_facebook_user_id(auth[:facebook][:facebook_user_id]).nil?
|
|
||||||
FacebookUserInfo.create!(auth[:facebook].merge(user_id: user.id))
|
|
||||||
end
|
|
||||||
|
|
||||||
if auth[:github_user_id] && auth[:github_screen_name] && GithubUserInfo.find_by_github_user_id(auth[:github_user_id]).nil?
|
|
||||||
GithubUserInfo.create(user_id: user.id, screen_name: auth[:github_screen_name], github_user_id: auth[:github_user_id])
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Create 3rd party auth records (Twitter, Facebook, GitHub)
|
||||||
|
create_third_party_auth_records(user, auth) if auth.present?
|
||||||
|
|
||||||
# Clear authentication session.
|
# Clear authentication session.
|
||||||
session[:authentication] = nil
|
session[:authentication] = nil
|
||||||
|
|
||||||
# JSON result
|
# JSON result
|
||||||
render json: {success: true, active: active_result, message: msg }
|
render json: { success: true, active: active_user, message: msg }
|
||||||
else
|
else
|
||||||
render json: {success: false, message: I18n.t("login.errors", errors: user.errors.full_messages.join("\n"))}
|
render json: {
|
||||||
|
success: false,
|
||||||
|
message: I18n.t("login.errors", errors: user.errors.full_messages.join("\n"))
|
||||||
|
}
|
||||||
end
|
end
|
||||||
rescue ActiveRecord::StatementInvalid
|
rescue ActiveRecord::StatementInvalid
|
||||||
render json: {success: false, message: I18n.t("login.something_already_taken")}
|
render json: { success: false, message: I18n.t("login.something_already_taken") }
|
||||||
rescue DiscourseHub::NicknameUnavailable
|
rescue DiscourseHub::NicknameUnavailable
|
||||||
render json: {success: false, message: I18n.t("login.errors", errors:I18n.t("login.not_available", suggestion: User.suggest_username(params[:username])) )}
|
render json: { success: false,
|
||||||
|
message: I18n.t(
|
||||||
|
"login.errors",
|
||||||
|
errors:I18n.t(
|
||||||
|
"login.not_available", suggestion: User.suggest_username(params[:username])
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
rescue RestClient::Forbidden
|
rescue RestClient::Forbidden
|
||||||
render json: {errors: [I18n.t("discourse_hub.access_token_problem")]}
|
render json: { errors: [I18n.t("discourse_hub.access_token_problem")] }
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_honeypot_value
|
def get_honeypot_value
|
||||||
render json: {value: honeypot_value, challenge: challenge_value}
|
render json: {value: honeypot_value, challenge: challenge_value}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
# all avatars are funneled through here
|
# all avatars are funneled through here
|
||||||
def avatar
|
def avatar
|
||||||
|
|
||||||
|
@ -224,13 +224,10 @@ class UsersController < ApplicationController
|
||||||
# raise ActiveRecord::RecordNotFound
|
# raise ActiveRecord::RecordNotFound
|
||||||
|
|
||||||
user = User.select(:email).where(username_lower: params[:username].downcase).first
|
user = User.select(:email).where(username_lower: params[:username].downcase).first
|
||||||
if user
|
if user.present?
|
||||||
# for now we only support gravatar in square (redirect cached for a day), later we can use x-sendfile and/or a cdn to serve local
|
# for now we only support gravatar in square (redirect cached for a day),
|
||||||
size = params[:size].to_i
|
# later we can use x-sendfile and/or a cdn to serve local
|
||||||
size = 64 if size == 0
|
size = determine_avatar_size(params[:size])
|
||||||
size = 10 if size < 10
|
|
||||||
size = 128 if size > 128
|
|
||||||
|
|
||||||
url = user.avatar_template.gsub("{size}", size.to_s)
|
url = user.avatar_template.gsub("{size}", size.to_s)
|
||||||
expires_in 1.day
|
expires_in 1.day
|
||||||
redirect_to url
|
redirect_to url
|
||||||
|
@ -270,14 +267,18 @@ class UsersController < ApplicationController
|
||||||
guardian.ensure_can_edit!(user)
|
guardian.ensure_can_edit!(user)
|
||||||
|
|
||||||
# Raise an error if the email is already in use
|
# Raise an error if the email is already in use
|
||||||
raise Discourse::InvalidParameters.new(:email) if User.where("lower(email) = ?", params[:email].downcase).exists?
|
if User.where("lower(email) = ?", params[:email].downcase).exists?
|
||||||
|
raise Discourse::InvalidParameters.new(:email)
|
||||||
|
end
|
||||||
|
|
||||||
email_token = user.email_tokens.create(email: params[:email])
|
email_token = user.email_tokens.create(email: params[:email])
|
||||||
Jobs.enqueue(:user_email,
|
Jobs.enqueue(
|
||||||
to_address: params[:email],
|
:user_email,
|
||||||
type: :authorize_email,
|
to_address: params[:email],
|
||||||
user_id: user.id,
|
type: :authorize_email,
|
||||||
email_token: email_token.token)
|
user_id: user.id,
|
||||||
|
email_token: email_token.token
|
||||||
|
)
|
||||||
|
|
||||||
render nothing: true
|
render nothing: true
|
||||||
end
|
end
|
||||||
|
@ -327,8 +328,8 @@ class UsersController < ApplicationController
|
||||||
|
|
||||||
results = UserSearch.search term, topic_id
|
results = UserSearch.search term, topic_id
|
||||||
|
|
||||||
render json: { users: results.as_json( only: [ :username, :name ],
|
render json: { users: results.as_json(only: [ :username, :name ],
|
||||||
methods: :avatar_template ) }
|
methods: :avatar_template) }
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -351,4 +352,58 @@ class UsersController < ApplicationController
|
||||||
guardian.ensure_can_see!(user)
|
guardian.ensure_can_see!(user)
|
||||||
user
|
user
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def honeypot_or_challenge_fails?(params)
|
||||||
|
params[:password_confirmation] != honeypot_value ||
|
||||||
|
params[:challenge] != challenge_value.try(:reverse)
|
||||||
|
end
|
||||||
|
|
||||||
|
def valid_session_authentication?(auth, email)
|
||||||
|
auth && auth[:email] == email && auth[:email_valid]
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_third_party_auth_records(user, auth)
|
||||||
|
if twitter_auth?(auth)
|
||||||
|
TwitterUserInfo.create(
|
||||||
|
user_id: user.id,
|
||||||
|
screen_name: auth[:twitter_screen_name],
|
||||||
|
twitter_user_id: auth[:twitter_user_id]
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
if facebook_auth?(auth)
|
||||||
|
FacebookUserInfo.create!(auth[:facebook].merge(user_id: user.id))
|
||||||
|
end
|
||||||
|
|
||||||
|
if github_auth?(auth)
|
||||||
|
GithubUserInfo.create(
|
||||||
|
user_id: user.id,
|
||||||
|
screen_name: auth[:github_screen_name],
|
||||||
|
github_user_id: auth[:github_user_id]
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def twitter_auth?(auth)
|
||||||
|
auth[:twitter_user_id] && auth[:twitter_screen_name] &&
|
||||||
|
TwitterUserInfo.find_by_twitter_user_id(auth[:twitter_user_id]).nil?
|
||||||
|
end
|
||||||
|
|
||||||
|
def facebook_auth?(auth)
|
||||||
|
auth[:facebook].present? &&
|
||||||
|
FacebookUserInfo.find_by_facebook_user_id(auth[:facebook][:facebook_user_id]).nil?
|
||||||
|
end
|
||||||
|
|
||||||
|
def github_auth?(auth)
|
||||||
|
auth[:github_user_id] && auth[:github_screen_name] &&
|
||||||
|
GithubUserInfo.find_by_github_user_id(auth[:github_user_id]).nil?
|
||||||
|
end
|
||||||
|
|
||||||
|
def determine_avatar_size(size)
|
||||||
|
size = size.to_i
|
||||||
|
size = 64 if size == 0
|
||||||
|
size = 10 if size < 10
|
||||||
|
size = 128 if size > 128
|
||||||
|
size
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -102,6 +102,15 @@ class User < ActiveRecord::Base
|
||||||
find_available_username_based_on(name)
|
find_available_username_based_on(name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.new_from_params(params)
|
||||||
|
user = User.new
|
||||||
|
user.name = params[:name]
|
||||||
|
user.email = params[:email]
|
||||||
|
user.password = params[:password]
|
||||||
|
user.username = params[:username]
|
||||||
|
user
|
||||||
|
end
|
||||||
|
|
||||||
def self.create_for_email(email, opts={})
|
def self.create_for_email(email, opts={})
|
||||||
username = suggest_username(email)
|
username = suggest_username(email)
|
||||||
|
|
||||||
|
|
|
@ -277,12 +277,14 @@ describe UsersController do
|
||||||
context 'when creating a non active user (unconfirmed email)' do
|
context 'when creating a non active user (unconfirmed email)' do
|
||||||
it 'should enqueue a signup email' do
|
it 'should enqueue a signup email' do
|
||||||
Jobs.expects(:enqueue).with(:user_email, has_entries(type: :signup))
|
Jobs.expects(:enqueue).with(:user_email, has_entries(type: :signup))
|
||||||
xhr :post, :create, name: @user.name, username: @user.username, password: "strongpassword", email: @user.email
|
xhr :post, :create, name: @user.name, username: @user.username,
|
||||||
|
password: "strongpassword", email: @user.email
|
||||||
end
|
end
|
||||||
|
|
||||||
it "doesn't send a welcome email" do
|
it "doesn't send a welcome email" do
|
||||||
User.any_instance.expects(:enqueue_welcome_message).with('welcome_user').never
|
User.any_instance.expects(:enqueue_welcome_message).with('welcome_user').never
|
||||||
xhr :post, :create, name: @user.name, username: @user.username, password: "strongpassword", email: @user.email
|
xhr :post, :create, name: @user.name, username: @user.username,
|
||||||
|
password: "strongpassword", email: @user.email
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -294,7 +296,8 @@ describe UsersController do
|
||||||
|
|
||||||
it 'should enqueue a signup email' do
|
it 'should enqueue a signup email' do
|
||||||
User.any_instance.expects(:enqueue_welcome_message).with('welcome_user')
|
User.any_instance.expects(:enqueue_welcome_message).with('welcome_user')
|
||||||
xhr :post, :create, name: @user.name, username: @user.username, password: "strongpassword", email: @user.email
|
xhr :post, :create, name: @user.name, username: @user.username,
|
||||||
|
password: "strongpassword", email: @user.email
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should be logged in" do
|
it "should be logged in" do
|
||||||
|
@ -309,6 +312,7 @@ describe UsersController do
|
||||||
::JSON.parse(response.body)['active'].should == true
|
::JSON.parse(response.body)['active'].should == true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
context 'when approving of users is required' do
|
context 'when approving of users is required' do
|
||||||
before do
|
before do
|
||||||
SiteSetting.expects(:must_approve_users).returns(true)
|
SiteSetting.expects(:must_approve_users).returns(true)
|
||||||
|
@ -322,14 +326,51 @@ describe UsersController do
|
||||||
it "doesn't return active in the JSON" do
|
it "doesn't return active in the JSON" do
|
||||||
::JSON.parse(response.body)['active'].should == false
|
::JSON.parse(response.body)['active'].should == false
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'authentication records for' do
|
||||||
|
|
||||||
|
before do
|
||||||
|
SiteSetting.expects(:must_approve_users).returns(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should create twitter user info if none exists' do
|
||||||
|
twitter_auth = { twitter_user_id: 42, twitter_screen_name: "bruce" }
|
||||||
|
session[:authentication] = twitter_auth
|
||||||
|
TwitterUserInfo.expects(:find_by_twitter_user_id).returns(nil)
|
||||||
|
TwitterUserInfo.expects(:create)
|
||||||
|
|
||||||
|
xhr :post, :create, name: @user.name, username: @user.username,
|
||||||
|
password: "strongpassword", email: @user.email
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should create facebook user info if none exists' do
|
||||||
|
fb_auth = { facebook: { facebook_user_id: 42} }
|
||||||
|
session[:authentication] = fb_auth
|
||||||
|
FacebookUserInfo.expects(:find_by_facebook_user_id).returns(nil)
|
||||||
|
FacebookUserInfo.expects(:create!)
|
||||||
|
|
||||||
|
xhr :post, :create, name: @user.name, username: @user.username,
|
||||||
|
password: "strongpassword", email: @user.email
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should create github user info if none exists' do
|
||||||
|
gh_auth = { github_user_id: 2, github_screen_name: "bruce" }
|
||||||
|
session[:authentication] = gh_auth
|
||||||
|
GithubUserInfo.expects(:find_by_github_user_id).returns(nil)
|
||||||
|
GithubUserInfo.expects(:create)
|
||||||
|
|
||||||
|
xhr :post, :create, name: @user.name, username: @user.username,
|
||||||
|
password: "strongpassword", email: @user.email
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'after success' do
|
context 'after success' do
|
||||||
before do
|
before do
|
||||||
xhr :post, :create, name: @user.name, username: @user.username, password: "strongpassword", email: @user.email
|
xhr :post, :create, name: @user.name, username: @user.username,
|
||||||
|
password: "strongpassword", email: @user.email
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should succeed' do
|
it 'should succeed' do
|
||||||
|
@ -403,13 +444,22 @@ describe UsersController do
|
||||||
it_should_behave_like 'failed signup'
|
it_should_behave_like 'failed signup'
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when InvalidStatement is raised' do
|
context 'when an Exception is raised' do
|
||||||
before do
|
|
||||||
User.any_instance.stubs(:save).raises(ActiveRecord::StatementInvalid)
|
[ ActiveRecord::StatementInvalid,
|
||||||
|
DiscourseHub::NicknameUnavailable,
|
||||||
|
RestClient::Forbidden ].each do |exception|
|
||||||
|
before { User.any_instance.stubs(:save).raises(exception) }
|
||||||
|
|
||||||
|
let(:create_params) {
|
||||||
|
{ name: @user.name, username: @user.username,
|
||||||
|
password: "strongpassword", email: @user.email}
|
||||||
|
}
|
||||||
|
|
||||||
|
it_should_behave_like 'failed signup'
|
||||||
end
|
end
|
||||||
let(:create_params) { {name: @user.name, username: @user.username, password: "strongpassword", email: @user.email} }
|
|
||||||
it_should_behave_like 'failed signup'
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
context '.username' do
|
context '.username' do
|
||||||
|
@ -704,7 +754,9 @@ describe UsersController do
|
||||||
|
|
||||||
context 'not logged in' do
|
context 'not logged in' do
|
||||||
it 'raises an error when not logged in' do
|
it 'raises an error when not logged in' do
|
||||||
lambda { xhr :put, :update, username: 'somename' }.should raise_error(Discourse::NotLoggedIn)
|
expect do
|
||||||
|
xhr :put, :update, username: 'somename'
|
||||||
|
end.to raise_error(Discourse::NotLoggedIn)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -735,7 +787,6 @@ describe UsersController do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "search_users" do
|
describe "search_users" do
|
||||||
|
|
Loading…
Reference in a new issue