Skip to content

Instantly share code, notes, and snippets.

@esteedqueen
Forked from Bomadeno/registrations_controller.rb
Last active December 7, 2022 08:52
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save esteedqueen/a50fee0b83d13326f9a0 to your computer and use it in GitHub Desktop.
Save esteedqueen/a50fee0b83d13326f9a0 to your computer and use it in GitHub Desktop.
JSON API User Registration and Sessions with Devise
module Authenticable
# Devise methods overwrite
def current_user
@current_user ||= User.find_by(authentication_token: request.headers['Authorization'])
end
def authenticate_with_token!
render json: { errors: "Not authenticated" },
status: :unauthorized unless user_signed_in?
end
def user_signed_in?
current_user.present?
end
end
class Api::V1::BaseController < ApplicationController
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
respond_to :json
skip_before_filter :verify_authenticity_token, :if => Proc.new { |c| c.request.format == 'application/json' }
protect_from_forgery with: :null_session, if: Proc.new { |c| c.request.format == 'application/json' }
skip_before_filter :authenticate_user!
include Authenticable
...
# set and include other common functions in here
end
class Api::V1::Users::RegistrationsController < Api::V1::BaseController
before_action :authenticate_with_token!, only: [:update, :destroy]
respond_to :json
def create
if params[:user][:email].nil?
render :status => 400,
:json => {:message => 'User request must contain the user email.'}
return
elsif params[:user][:password].nil?
render :status => 400,
:json => {:message => 'User request must contain the user password.'}
return
end
if params[:user][:email]
duplicate_user = User.find_by_email(params[:user][:email])
unless duplicate_user.nil?
render :status => 409,
:json => {:message => 'Duplicate email. A user already exists with that email address.'}
return
end
end
@user = User.create(sign_up_params)
if @user.save
render(status: 200, json: Api::V1::UserSerializer.new(@user, root:false).to_json)
else
render :status => 400,
:json => {:message => @user.errors.full_messages}
end
end
private
def sign_up_params
params.require(:user).permit(:email, :username, :password)
end
end
class Api::V1::SessionsController < Api::V1::BaseController
before_filter :authenticate_with_token!, except: [:create]
before_filter :ensure_params_exist
respond_to :json
def create
resource = User.find_for_database_authentication(
email: params[:user][:email]
)
return invalid_login_attempt unless resource
if resource.valid_password?(params[:user][:password])
sign_in(:user, resource)
render(status: 200, success: true, json: Api::V1::UserSerializer.new(resource, root:false).to_json)
return
end
invalid_login_attempt
end
def destroy
resource = current_user
resource.authentication_token = nil
resource.save
head 204
end
protected
def ensure_params_exist
return unless params[:user].blank?
render json: {
success: false,
message: "missing user parameter"
}, status: 422
end
def invalid_login_attempt
warden.custom_failure!
render json: {
success: false,
message: "Error with your email or password"
}, status: 401
end
end
@esteedqueen
Copy link
Author

Here is the Devise User auth setup that worked for my Rails API

Take note of the serializer I'm rendering on success, that's specific for my setup, you could just render user or the data you need.

@dpain13
Copy link

dpain13 commented Jul 18, 2019

What are the routes for this? Cause I'm having a routing error!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment