def create
build_resource(sign_up_params.select{|k,v| v.present?})
if Identity.identity_exists?(resource.email)
# Prompt user to sign in with Facebook instead
puts 'prompt user to sign in with facebook'
else
if resource.save
# redirect_to_signup_finish / return ?
else
clean_up_passwords resource
end
end
respond_to do |format|
format.html { render :new }
format.json { render :json => { errors: resource.errors }, :status => :unprocessable_entity }
end
end
I have this code where if a user has signed up with Facebook with the same email as before, we prevent user from signing up again. Instead, we prompt them to login with facebook. We want to create a custom resource.errors that states this scenario. What is the best way to achieve it?
Related
Hello I have an app where a user is invited as an attendee
In the attendee controller, when the attendee is created the user is created but not sent an invite to the system
attendees_controller.rb
def create
#attendee = Attendee.new(attendee_params)
#user = User.invite!({email: "#{#attendee.email}"}, current_user) do |u|
u.skip_invitation = true
end
#attendee.user_id = #user.id
respond_to do |format|
if #attendee.save
format.html { redirect_to meeting_url(#attendee.meeting), notice: "Attendee was successfully created." }
format.json { render :show, status: :created, location: #attendee }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: #attendee.errors, status: :unprocessable_entity }
end
end
end
in the same controller i then have a send_invite
def send_invite
#attendee = Attendee.find(params[:attendee_id])
User.where(id: #attendee.user_id).deliver_invitation
redirect_to meeting_url(#attendee.meeting)
end
when i hit it via a button I get
NoMethodError in AttendeesController#send_invite
undefined method `deliver_invitation' for #<ActiveRecord::Relation
[devise_invitable][1] clearly states
If you want to create the invitation but not send it, you can set skip_invitation to true.
user = User.invite!(email: 'new_user#example.com', name: 'John Doe') do |u|
u.skip_invitation = true
end
# => the record will be created, but the invitation email will not be sent
When generating the accept_user_invitation_url yourself, you must use the raw_invitation_token. This value is temporarily available when you invite a user and will be decrypted when received.
accept_user_invitation_url(invitation_token: user.raw_invitation_token)
When skip_invitation is used, you must also then set the invitation_sent_at field when the user is sent their token. Failure to do so will yield “Invalid invitation token” error when the user attempts to accept the invite. You can set the column, or call deliver_invitation to send the invitation and set the column:
user.deliver_invitation
What am I missing?
[1]: https://github.com/scambra/devise_invitable#send-an-invitation-
I guess .deliver_invitation is an instance method on the User Model. (through devise_invitable).
In that case you would probably want something like this:
User.where(id: #attendee.user_id).each do |user|
user.deliver_invitation
end
Assuming deliver_invitation is an instance method of the User model, you can modify your send_invite method like below:
def send_invite
#attendee = Attendee.find(params[:attendee_id])
user = User.find(#attendee.user_id)
user.deliver_invitation
redirect_to meeting_url(#attendee.meeting)
end
I am trying to learn Rails API with React front end and have created a login, signup and logout feature. Currently, I am using localstorage to check if a user is signed in or registered. If the value is true, the logout button appears, and clicking logout empties the localstorage and sets the value to false. But I think this isn't the correct way of doing it since rails devise has its own session and logout endpoint. I tried writing some code for the destroy session and when testing it using the endpoint in POSTMAN it doesn't seem to work the way I want.
Here's the code:
class API::V1::SessionsController < Devise::SessionsController
def create
#user = User.find_by_email(user_params[:email])
if #user && #user.valid_password?(user_params[:password])
session[:user_id]=#user.id
sign_in :user, #user
render json: #user
elsif #user && not(#user.valid_password?(user_params[:password]))
invalid_attempt
else
no_user
end
end
def destroy
puts "logout clicked"
#user = User.find_by_email(user_params[:email])
if #user.valid_password(user_params[:password]) && #user.destroy
render :json => { success: "user was successfully deleted" }, :status => 201
else
render :json => { error: "user could not be deleted" }, :status => 422
end
end
private
def no_user
render json: {error: "An account with this email doesn't exist. Please create a new one"}, status: :unprocessable_entity
end
def invalid_attempt
render json: { error: "Your password isn't correct" }, status: :unprocessable_entity
end
def user_params
params.require(:user).permit(:email, :password)
end
end
http://localhost:3000/users/sign_out
{
"user":{
"email":"test1#test.com",
"password":"test1#test.com"
}
}
Please note that this user does exist. Sending a delete request to http://localhost:3000/users/sign_out isn't even logging the "logout clicked" and the status gives 204.
I have this method:
def update
#user = User.find(params[:id])
respond_to do |format|
if #user.update_attributes(params[:user])
if params[:mypmnode]
session[:return_to] = projects_pmnode_path(params[:mypmnode])
sign_in(#user)
end
format.html { redirect_to(session[:return_to], :notice => 'User was successfully updated.') }
format.xml { head :ok }
else
#create_company = true if params[:user][:company_id].blank? and params[:user][:company_attributes].length > 0
#create_department = true if params[:user][:department_id].blank? and params[:user][:department_attributes].length > 0
format.html { render :action => "edit" }
format.xml { render :xml => #user.errors, :status => :unprocessable_entity }
end
end
end
The idea is that if the user is updated, He is automatically signed-in and redirected to a page where authentication is required.
In this page, I have: before_filter :authenticate_user!
This doesn't work on redirect.
If I then go to another page making use of this sign_in function, then the user logs-in correctly.
Any idea why redirect doesn't work? Thx!
UPDATE:
to make it clearer, I insert the second page code (controller):
class PmnodesController < Projects::BaseController
before_filter authenticate_user!
def index
#pmnodes = Pmnode.all
respond_to do |format|
format.html
end
end
If the password is updated on #user, devise will invalidate the session. After the update_attributes, you could try calling sign_out first.
sign_out(#user)
sign_in(#user)
Are you sure that your progam goes inside this blog
if params[:mypmnode]
session[:return_to] = projects_pmnode_path(params[:mypmnode])
sign_in(#user)
end
if not this should sign in your use automatically.
def update
#user = User.find(params[:id])
respond_to do |format|
if #user.update_attributes(params[:user])
if params[:mypmnode]
session[:return_to] = projects_pmnode_path(params[:mypmnode])
end
sign_in(#user)
format.html { redirect_to(session[:return_to], :notice => 'User was successfully updated.') }
format.xml { head :ok }
else
#create_company = true if params[:user][:company_id].blank? and params[:user][:company_attributes].length > 0
#create_department = true if params[:user][:department_id].blank? and params[:user][:department_attributes].length > 0
format.html { render :action => "edit" }
format.xml { render :xml => #user.errors, :status => :unprocessable_entity }
end
end
end
I had a similar problem:
I had a controller method that created and signed in a user
def new
#user = User.create!
sign_in #user
redirect_to some_nondefault_path
end
where some_nondefault_path required authentication. The new action did not require authentication. The user was getting created and signed in, but the user session wasn't persisting and the user was getting 401-unauthorized and redirected to the signin page instead of some_nondefault_path.
I ended up solving it by adding
skip_before_filter :verify_authenticity_token, :only => :new
to the first controller. It seemed to be trying to verify the CSRF token before creating the user session, which was failing and blocking the creation of a normal user session (even though it wasn't trying to authenticate_user!).
Hope this helps!
I have an option for a user to update their username in their profile. However, when the url for their profile has been set as localhost/user/username and when they submit their changes, they are redirected to their old username (not the new updated one).
Here is my update from users_controller.rb
Any suggestions?
def update
#user = User.find_by_username(params[:id])
#page_title = "Edit Profile"
respond_to do |format|
if #user.update_attributes(params[:user])
format.html { redirect_to(user_url,
:notice => "Your profile has been saved.") }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #user.errors,
:status => :unprocessable_entity }
end
end
end
also, I'm using
def to_param
username
end
Doesn't user_url take #user as an argument? How have you defined your route for that?
One thing I can think of immediately is #user.reload!.
I am trying to make it possible for users to login as quick as possible, so I want users to be able to login and create records in the same form.
Is it possible to authenticate a user with the restful_authentication plugin from any controller by somehow calling the create method in the session controller, and return the authenticated user? It seems like this could be done easily somehow, but I just can't figure out how to do it in Rails.
Maybe something like:
#Records Controller
def create
if params[:login] && params[:password]
#This method would call /session/ and pass the login/password params
user = authenticate_user(params[:login'], params[:password])
end
#record = Record.new(params[:record])
#record.user = user
if #question.save && user
flash[:notice] = 'Record was successfully created.'
redirect_to(#record)
end
end
Any ideas on how to do this would be appreciated!
I've tested this code on Rails 2.3.4 and it works; the user remains logged in. Bear in mind that you should try to refactor so that the authentication code lives in a single place, rather than having it duplicated in several controllers.
Note also that the authentication code in this snippet is a simplified version of that in the Sessions controller, & so doesn't handle any of the 'remember me' functionality.
# POST /stacks
# POST /stacks.xml
def create
#stack = Stack.new(params[:stack])
if params[:login] && params[:password]
logout_keeping_session!
user = User.authenticate(params[:login], params[:password])
self.current_user = user
end
respond_to do |format|
if !user
flash[:error] = 'Login details incorrect.'
format.html { render :action => "new" }
format.xml { render :xml => #stack.errors, :status => :unprocessable_entity }
elsif #stack.save
flash[:notice] = 'Stack was successfully created.'
format.html { redirect_to(#stack) }
format.xml { render :xml => #stack, :status => :created, :location => #stack }
else
format.html { render :action => "new" }
format.xml { render :xml => #stack.errors, :status => :unprocessable_entity }
end
end
end