2013-02-05 14:16:51 -05:00
require 'spec_helper'
describe SessionController do
2014-02-25 14:30:49 +11:00
describe '.sso_login' do
before do
@sso_url = " http://somesite.com/discourse_sso "
@sso_secret = " shjkfdhsfkjh "
SiteSetting . stubs ( " enable_sso " ) . returns ( true )
SiteSetting . stubs ( " sso_url " ) . returns ( @sso_url )
SiteSetting . stubs ( " sso_secret " ) . returns ( @sso_secret )
2014-02-26 10:52:11 +11:00
# We have 2 options, either fabricate an admin or don't
# send welcome messages
Fabricate ( :admin )
# skip for now
# SiteSetting.stubs("send_welcome_message").returns(false)
2014-02-25 14:30:49 +11:00
end
2014-02-26 09:58:30 +11:00
def get_sso ( return_path )
2014-02-25 14:30:49 +11:00
nonce = SecureRandom . hex
dso = DiscourseSingleSignOn . new
dso . nonce = nonce
2014-02-26 09:58:30 +11:00
dso . register_nonce ( return_path )
2014-02-25 14:30:49 +11:00
sso = SingleSignOn . new
sso . nonce = nonce
sso . sso_secret = @sso_secret
sso
end
it 'can take over an account' do
2014-02-26 09:58:30 +11:00
sso = get_sso ( " / " )
2014-02-25 14:30:49 +11:00
user = Fabricate ( :user )
sso . email = user . email
2014-02-27 16:48:46 -08:00
sso . external_id = 'abc'
sso . username = 'sam'
2014-02-25 14:30:49 +11:00
get :sso_login , Rack :: Utils . parse_query ( sso . payload )
response . should redirect_to ( '/' )
logged_on_user = Discourse . current_user_provider . new ( request . env ) . current_user
logged_on_user . email . should == user . email
logged_on_user . single_sign_on_record . external_id . should == " abc "
2014-02-27 16:48:46 -08:00
logged_on_user . single_sign_on_record . external_username . should == 'sam'
2014-02-25 14:30:49 +11:00
end
it 'allows you to create an account' do
2014-02-26 09:58:30 +11:00
sso = get_sso ( '/a/' )
2014-02-25 14:30:49 +11:00
sso . external_id = '666' # the number of the beast
sso . email = 'bob@bob.com'
sso . name = 'Sam Saffron'
sso . username = 'sam'
2014-04-22 13:52:13 +10:00
sso . custom_fields [ " shop_url " ] = " http://my_shop.com "
sso . custom_fields [ " shop_name " ] = " Sam "
2014-02-25 14:30:49 +11:00
get :sso_login , Rack :: Utils . parse_query ( sso . payload )
2014-02-26 09:58:30 +11:00
response . should redirect_to ( '/a/' )
2014-02-25 14:30:49 +11:00
logged_on_user = Discourse . current_user_provider . new ( request . env ) . current_user
2014-04-22 13:52:13 +10:00
# ensure nothing is transient
logged_on_user = User . find ( logged_on_user . id )
2014-02-25 14:30:49 +11:00
logged_on_user . email . should == 'bob@bob.com'
logged_on_user . name . should == 'Sam Saffron'
logged_on_user . username . should == 'sam'
logged_on_user . single_sign_on_record . external_id . should == " 666 "
2014-02-27 16:48:46 -08:00
logged_on_user . single_sign_on_record . external_username . should == 'sam'
2014-02-26 10:28:03 +11:00
logged_on_user . active . should == true
2014-04-22 13:52:13 +10:00
logged_on_user . custom_fields [ " shop_url " ] . should == " http://my_shop.com "
logged_on_user . custom_fields [ " shop_name " ] . should == " Sam "
logged_on_user . custom_fields [ " bla " ] . should == nil
2014-02-25 14:30:49 +11:00
end
2014-04-22 13:52:13 +10:00
2014-02-25 14:30:49 +11:00
it 'allows login to existing account with valid nonce' do
2014-02-26 09:58:30 +11:00
sso = get_sso ( '/hello/world' )
2014-02-25 14:30:49 +11:00
sso . external_id = '997'
user = Fabricate ( :user )
user . create_single_sign_on_record ( external_id : '997' , last_payload : '' )
get :sso_login , Rack :: Utils . parse_query ( sso . payload )
user . single_sign_on_record . reload
user . single_sign_on_record . last_payload . should == sso . unsigned_payload
response . should redirect_to ( '/hello/world' )
logged_on_user = Discourse . current_user_provider . new ( request . env ) . current_user
user . id . should == logged_on_user . id
# nonce is bad now
get :sso_login , Rack :: Utils . parse_query ( sso . payload )
response . code . should == '500'
end
2014-03-26 15:39:44 +11:00
describe 'local attribute override from SSO payload' do
2014-02-27 16:48:46 -08:00
before do
SiteSetting . stubs ( " sso_overrides_email " ) . returns ( true )
SiteSetting . stubs ( " sso_overrides_username " ) . returns ( true )
SiteSetting . stubs ( " sso_overrides_name " ) . returns ( true )
2014-03-26 15:39:44 +11:00
2014-02-27 16:48:46 -08:00
@user = Fabricate ( :user )
2014-03-26 15:39:44 +11:00
2014-02-27 16:48:46 -08:00
@sso = get_sso ( '/hello/world' )
@sso . external_id = '997'
2014-03-26 15:39:44 +11:00
2014-02-27 16:48:46 -08:00
@reversed_username = @user . username . reverse
@sso . username = @reversed_username
@sso . email = " #{ @reversed_username } @garbage.org "
@reversed_name = @user . name . reverse
@sso . name = @reversed_name
2014-03-26 15:39:44 +11:00
2014-02-27 16:48:46 -08:00
@suggested_username = UserNameSuggester . suggest ( @sso . username || @sso . name || @sso . email )
@suggested_name = User . suggest_name ( @sso . name || @sso . username || @sso . email )
@user . create_single_sign_on_record ( external_id : '997' , last_payload : '' )
end
2014-03-26 15:39:44 +11:00
2014-02-27 16:48:46 -08:00
it 'stores the external attributes' do
get :sso_login , Rack :: Utils . parse_query ( @sso . payload )
@user . single_sign_on_record . reload
@user . single_sign_on_record . external_username . should == @sso . username
@user . single_sign_on_record . external_email . should == @sso . email
@user . single_sign_on_record . external_name . should == @sso . name
end
2014-03-26 15:39:44 +11:00
2014-02-27 16:48:46 -08:00
it 'overrides attributes' do
get :sso_login , Rack :: Utils . parse_query ( @sso . payload )
2014-03-26 15:39:44 +11:00
2014-02-27 16:48:46 -08:00
logged_on_user = Discourse . current_user_provider . new ( request . env ) . current_user
logged_on_user . username . should == @suggested_username
logged_on_user . email . should == " #{ @reversed_username } @garbage.org "
logged_on_user . name . should == @suggested_name
end
2014-03-26 15:39:44 +11:00
2014-02-27 16:48:46 -08:00
it 'does not change matching attributes for an existing account' do
@sso . username = @user . username
@sso . name = @user . name
@sso . email = @user . email
2014-03-26 15:39:44 +11:00
2014-02-27 16:48:46 -08:00
get :sso_login , Rack :: Utils . parse_query ( @sso . payload )
2014-03-26 15:39:44 +11:00
2014-02-27 16:48:46 -08:00
logged_on_user = Discourse . current_user_provider . new ( request . env ) . current_user
logged_on_user . username . should == @user . username
logged_on_user . name . should == @user . name
logged_on_user . email . should == @user . email
end
2014-03-26 15:39:44 +11:00
2014-02-27 16:48:46 -08:00
it 'does not change attributes for unchanged external attributes' do
@user . single_sign_on_record . external_username = @sso . username
@user . single_sign_on_record . external_email = @sso . email
@user . single_sign_on_record . external_name = @sso . name
@user . single_sign_on_record . save
2014-03-26 15:39:44 +11:00
2014-02-27 16:48:46 -08:00
get :sso_login , Rack :: Utils . parse_query ( @sso . payload )
logged_on_user = Discourse . current_user_provider . new ( request . env ) . current_user
logged_on_user . username . should == @user . username
logged_on_user . email . should == @user . email
logged_on_user . name . should == @user . name
end
2014-03-26 15:39:44 +11:00
end
2014-02-25 14:30:49 +11:00
end
2013-02-05 14:16:51 -05:00
describe '.create' do
let ( :user ) { Fabricate ( :user ) }
2013-02-11 11:18:26 -05:00
context 'when email is confirmed' do
2013-02-05 14:16:51 -05:00
before do
2014-05-06 14:41:59 +01:00
token = user . email_tokens . find_by ( email : user . email )
2013-02-11 11:18:26 -05:00
EmailToken . confirm ( token . token )
2013-02-05 14:16:51 -05:00
end
2013-02-11 11:18:26 -05:00
it " raises an error when the login isn't present " do
2013-07-23 23:02:42 -04:00
lambda { xhr :post , :create } . should raise_error ( ActionController :: ParameterMissing )
2013-02-05 14:16:51 -05:00
end
2013-02-11 11:18:26 -05:00
describe 'invalid password' do
it " should return an error with an invalid password " do
xhr :post , :create , login : user . username , password : 'sssss'
:: JSON . parse ( response . body ) [ 'error' ] . should be_present
end
2013-02-05 14:16:51 -05:00
end
2013-11-07 13:53:32 -05:00
describe 'suspended user' do
2013-06-27 15:14:42 -04:00
it 'should return an error' do
2013-11-07 13:53:32 -05:00
User . any_instance . stubs ( :suspended? ) . returns ( true )
User . any_instance . stubs ( :suspended_till ) . returns ( 2 . days . from_now )
2013-06-27 15:14:42 -04:00
xhr :post , :create , login : user . username , password : 'myawesomepassword'
:: JSON . parse ( response . body ) [ 'error' ] . should be_present
end
end
2014-04-28 13:46:28 -04:00
describe 'deactivated user' do
it 'should return an error' do
User . any_instance . stubs ( :active ) . returns ( false )
xhr :post , :create , login : user . username , password : 'myawesomepassword'
expect ( JSON . parse ( response . body ) [ 'error' ] ) . to eq ( I18n . t ( 'login.not_activated' ) )
end
end
2013-02-11 11:18:26 -05:00
describe 'success by username' do
2014-03-26 15:39:44 +11:00
it 'logs in correctly' do
2013-02-11 11:18:26 -05:00
xhr :post , :create , login : user . username , password : 'myawesomepassword'
2014-03-26 15:39:44 +11:00
2013-02-11 11:18:26 -05:00
user . reload
2013-02-05 14:16:51 -05:00
2013-02-11 11:18:26 -05:00
session [ :current_user_id ] . should == user . id
user . auth_token . should be_present
2014-03-26 15:39:44 +11:00
cookies [ :_t ] . should == user . auth_token
2013-02-11 11:18:26 -05:00
end
2014-03-26 15:39:44 +11:00
end
2013-02-05 14:16:51 -05:00
2014-03-26 15:39:44 +11:00
describe 'local logins disabled' do
it 'fails' do
SiteSetting . stubs ( :enable_local_logins ) . returns ( false )
xhr :post , :create , login : user . username , password : 'myawesomepassword'
response . status . to_i . should == 500
2013-02-11 11:18:26 -05:00
end
2013-02-05 14:16:51 -05:00
end
2013-02-11 11:18:26 -05:00
describe 'strips leading @ symbol' do
before do
xhr :post , :create , login : " @ " + user . username , password : 'myawesomepassword'
user . reload
end
2013-02-05 14:16:51 -05:00
2013-02-11 11:18:26 -05:00
it 'sets a session id' do
session [ :current_user_id ] . should == user . id
end
2013-02-05 14:16:51 -05:00
end
2013-02-11 11:18:26 -05:00
describe 'also allow login by email' do
2013-02-05 14:16:51 -05:00
before do
xhr :post , :create , login : user . email , password : 'myawesomepassword'
end
2013-02-11 11:18:26 -05:00
it 'sets a session id' do
session [ :current_user_id ] . should == user . id
2013-02-05 14:16:51 -05:00
end
end
2013-07-23 23:02:42 -04:00
context 'login has leading and trailing space' do
let ( :username ) { " #{ user . username } " }
let ( :email ) { " #{ user . email } " }
it " strips spaces from the username " do
xhr :post , :create , login : username , password : 'myawesomepassword'
:: JSON . parse ( response . body ) [ 'error' ] . should_not be_present
end
it " strips spaces from the email " do
xhr :post , :create , login : email , password : 'myawesomepassword'
:: JSON . parse ( response . body ) [ 'error' ] . should_not be_present
end
end
2013-02-11 11:18:26 -05:00
describe " when the site requires approval of users " do
before do
SiteSetting . expects ( :must_approve_users? ) . returns ( true )
end
context 'with an unapproved user' do
before do
xhr :post , :create , login : user . email , password : 'myawesomepassword'
end
it " doesn't log in the user " do
session [ :current_user_id ] . should be_blank
end
2013-06-05 18:21:19 -07:00
it " shows the 'not approved' error message " do
expect ( JSON . parse ( response . body ) [ 'error' ] ) . to eq (
I18n . t ( 'login.not_approved' )
)
end
2013-02-11 11:18:26 -05:00
end
2013-08-06 16:51:29 -04:00
context " with an unapproved user who is an admin " do
before do
User . any_instance . stubs ( :admin? ) . returns ( true )
xhr :post , :create , login : user . email , password : 'myawesomepassword'
end
it 'sets a session id' do
session [ :current_user_id ] . should == user . id
end
end
2013-02-11 11:18:26 -05:00
end
2013-02-05 14:16:51 -05:00
end
2013-02-11 11:18:26 -05:00
context 'when email has not been confirmed' do
2013-06-05 18:21:19 -07:00
def post_login
2013-02-11 11:18:26 -05:00
xhr :post , :create , login : user . email , password : 'myawesomepassword'
end
it " doesn't log in the user " do
2013-06-05 18:21:19 -07:00
post_login
2013-02-11 11:18:26 -05:00
session [ :current_user_id ] . should be_blank
end
2013-06-05 18:21:19 -07:00
it " shows the 'not activated' error message " do
post_login
expect ( JSON . parse ( response . body ) [ 'error' ] ) . to eq (
I18n . t 'login.not_activated'
)
end
context " and the 'must approve users' site setting is enabled " do
before { SiteSetting . expects ( :must_approve_users? ) . returns ( true ) }
it " shows the 'not approved' error message " do
post_login
expect ( JSON . parse ( response . body ) [ 'error' ] ) . to eq (
I18n . t 'login.not_approved'
)
end
2013-02-11 11:18:26 -05:00
end
end
2013-02-05 14:16:51 -05:00
end
describe '.destroy' do
before do
@user = log_in
xhr :delete , :destroy , id : @user . username
end
it 'removes the session variable' do
session [ :current_user_id ] . should be_blank
end
it 'removes the auth token cookie' do
cookies [ :_t ] . should be_blank
end
end
describe '.forgot_password' do
it 'raises an error without a username parameter' do
2013-06-06 00:14:32 -07:00
lambda { xhr :post , :forgot_password } . should raise_error ( ActionController :: ParameterMissing )
2013-02-05 14:16:51 -05:00
end
context 'for a non existant username' do
2013-02-25 19:42:20 +03:00
it " doesn't generate a new token for a made up username " do
2013-04-15 02:20:33 +02:00
lambda { xhr :post , :forgot_password , login : 'made_up' } . should_not change ( EmailToken , :count )
2013-02-05 14:16:51 -05:00
end
2013-02-25 19:42:20 +03:00
it " doesn't enqueue an email " do
2013-02-05 14:16:51 -05:00
Jobs . expects ( :enqueue ) . with ( :user_mail , anything ) . never
2013-04-15 02:20:33 +02:00
xhr :post , :forgot_password , login : 'made_up'
2013-02-25 19:42:20 +03:00
end
end
2013-02-05 14:16:51 -05:00
context 'for an existing username' do
let ( :user ) { Fabricate ( :user ) }
2014-03-26 15:39:44 +11:00
it " returns a 500 if local logins are disabled " do
SiteSetting . stubs ( :enable_local_logins ) . returns ( false )
xhr :post , :forgot_password , login : user . username
response . code . to_i . should == 500
end
2013-02-25 19:42:20 +03:00
it " generates a new token for a made up username " do
2013-04-15 02:20:33 +02:00
lambda { xhr :post , :forgot_password , login : user . username } . should change ( EmailToken , :count )
2013-02-05 14:16:51 -05:00
end
2013-02-25 19:42:20 +03:00
it " enqueues an email " do
2013-02-05 14:16:51 -05:00
Jobs . expects ( :enqueue ) . with ( :user_email , has_entries ( type : :forgot_password , user_id : user . id ) )
2013-04-15 02:20:33 +02:00
xhr :post , :forgot_password , login : user . username
2013-02-25 19:42:20 +03:00
end
end
2013-02-05 14:16:51 -05:00
end
2014-02-05 13:46:24 -05:00
describe '.current' do
context " when not logged in " do
it " retuns 404 " do
xhr :get , :current
response . should_not be_success
end
end
context " when logged in " do
let! ( :user ) { log_in }
it " returns the JSON for the user " do
xhr :get , :current
response . should be_success
json = :: JSON . parse ( response . body )
json [ 'current_user' ] . should be_present
json [ 'current_user' ] [ 'id' ] . should == user . id
end
end
end
2013-02-05 14:16:51 -05:00
end