New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow user to use whatever provider they want to use to login to the same email-binded account. #177

Merged
merged 1 commit into from Feb 25, 2015
Jump to file or symbol
Failed to load files and symbols.
+132 −8
Diff settings

Always

Just for now

@@ -24,14 +24,30 @@ def assign_provider_attrs(user, auth_hash)
end
# RecordNotUnique is thrown when the email has already been used with another
# provider.
# provider, sign that user in since we know the user own the email through
# their provider.
def user_exists_with_other_providers
@error = 'الإيميل مستعمل من قبل. حاول تسجيل الدخول بطريقة أخرى (فيسبوك أو جوجل أو بإيميل وكلمة سر)'
respond_to do |format|
format.html {
render :layout => "omniauth_response",
:template => "devise_token_auth/omniauth_failure"
}
@resource = User.find_by_email(@resource.email)
@resource.tokens[@client_id] = {
token: BCrypt::Password.create(@token),
expiry: @expiry
}
if resource_class.devise_modules.include?(:confirmable)
@resource.skip_confirmation!
end
if @resource.avatar_uid.nil?
@resource.avatar_url = get_large_image(auth_hash['info']['image'])
end
if @resource.nickname.nil?
@resource.nickname = auth_hash['info']['nickname']
end
sign_in(:user, @resource, store: false, bypass: false)
@resource.save!
render :layout => "layouts/omniauth_response", :template => "devise_token_auth/omniauth_success"
end
end
@@ -0,0 +1,39 @@
class Api::V1::PasswordsController < DeviseTokenAuth::PasswordsController
before_filter :set_user_by_token, :only => [:update]
# TODO(mkhatib): The only change here is to allow resource with a non-email
# provider to change their passwords.
def update
# make sure user is authorized
unless @resource
return render json: {
success: false,
errors: ['Unauthorized']
}, status: 401
end
# ensure that password params were sent
unless password_resource_params[:password] and password_resource_params[:password_confirmation]
return render json: {
success: false,
errors: ['You must fill out the fields labeled "password" and "password confirmation".']
}, status: 422
end
if @resource.update_attributes(password_resource_params)
return render json: {
success: true,
data: {
user: @resource,
message: "Your password has been successfully updated."
}
}
else
return render json: {
success: false,
errors: @resource.errors
}, status: 422
end
end
end
@@ -0,0 +1,67 @@
class Api::V1::SessionsController < DeviseTokenAuth::SessionsController
# TODO(mkhatib): The only change is to drop the "AND provider='email'" clause
# in the initial query for the resource. This is in order to allow non-email
# providers to login using their email and a later set password.
def create
# Check
field = (resource_params.keys.map(&:to_sym) & resource_class.authentication_keys).first
@resource = nil
if field
q_value = resource_params[field]
if resource_class.case_insensitive_keys.include?(field)
q_value.downcase!
end
q = "#{field.to_s} = ?"
if ActiveRecord::Base.connection.adapter_name.downcase.starts_with? 'mysql'
q = "BINARY " + q
end
@resource = resource_class.where(q, q_value).first
end
if @resource and valid_params?(field, q_value) and @resource.valid_password?(resource_params[:password]) and @resource.confirmed?
# create client id
@client_id = SecureRandom.urlsafe_base64(nil, false)
@token = SecureRandom.urlsafe_base64(nil, false)
@resource.tokens[@client_id] = {
token: BCrypt::Password.create(@token),
expiry: (Time.now + DeviseTokenAuth.token_lifespan).to_i
}
@resource.save
sign_in(:user, @resource, store: false, bypass: false)
render json: {
data: @resource.as_json(except: [
:tokens, :created_at, :updated_at
])
}
elsif @resource and not @resource.confirmed?
render json: {
success: false,
errors: [
"A confirmation email was sent to your account at #{@resource.email}. "+
"You must follow the instructions in the email before your account "+
"can be activated"
]
}, status: 401
else
render json: {
errors: ["Invalid login credentials. Please try again."]
}, status: 401
end
end
def valid_params?(key, val)
resource_params[:password] && key && val
end
end
@@ -13,7 +13,7 @@
# time. In this case, each request in the batch will need to share the same
# auth token. This setting determines how far apart the requests can be while
# still using the same auth token.
#config.batch_request_buffer_throttle = 5.seconds
config.batch_request_buffer_throttle = 30.seconds
# This route will be the prefix for all oauth2 redirect callbacks. For
# example, using the default '/omniauth', the github oauth2 provider will
View
@@ -2,7 +2,9 @@
scope do
mount_devise_token_auth_for 'User', at: '/auth', controllers: {
sessions: 'api/v1/sessions',
confirmations: 'api/v1/confirmations',
passwords: 'api/v1/passwords',
omniauth_callbacks: 'api/v1/omniauth_callbacks'
}
ProTip! Use n and p to navigate between commits in a pull request.