class Api::V1::Auth::UsersController < Api::BaseController
respond_to :json
def show
respond_with current_user
end
end
class Api::V1::Auth::TokensController < Api::BaseController
skip_before_action :authenticate_with_token!, only: :create
respond_to :json
def show
respond_with current_user.tokens
end
def create
user = User.find_by(email: auth_params[:email])
if user && user.valid_password?(auth_params[:password])
sign_in :user, user, store: false
user.generate_token
respond_with user.tokens.last, location: -> { api_v1_auth_tokens_path }
else
render json: { status: 422, errors: 'Invalid email or password' }
end
end
def destroy
token = current_user.tokens.find_by(token: params[:token])
token.destroy
head 204
end
private
def auth_params
params.require(:user).permit(:email, :password)
end
end
Rails.application.routes.draw do
root 'home#index'
namespace :api, defaults: { format: :json } do
namespace :v1 do
namespace :auth do
resource :user, only: :show
resource :registration, only: [:create, :update]
resource :tokens, only: [:show, :create, :destroy]
end
end
end
end
class Api::V1::Auth::RegistrationsController < Api::BaseController
skip_before_action :authenticate_with_token!, only: :create
respond_to :json
def create
user = User.create(user_params)
respond_with user, location: -> { api_v1_auth_user_path }
end
def update
current_user.update(user_params)
respond_with current_user, location: -> { api_v1_auth_user_path }
end
private
def user_params
params.require(:user).permit(:email, :password, :password_confirmation)
end
end
class CreateTokens < ActiveRecord::Migration[5.0]
def change
create_table :tokens do |t|
t.string :token, null: false
t.references :user, null: false, foreign_key: true
t.timestamps
end
add_index :tokens, :token, unique: true
end
end
class Api::BaseController < ApplicationController
protect_from_forgery with: :null_session
rescue_from ActiveRecord::RecordNotFound, with: :not_found
before_action :destroy_session
before_action :authenticate_with_token!
def current_user
@current_user ||= find_user
end
def user_signed_in?
current_user.present?
end
private
def destroy_session
request.session_options[:skip] = true
end
def not_found
render json: { status: 404, errors: 'Not found' }
end
def authenticate_with_token!
render json: { status: 401, errors: 'Not authenticated' } unless user_signed_in?
end
def find_user
return nil if params[:token].blank?
token = Token.find_by(token: params[:token])
token&.user if Devise.secure_compare(token&.token, params[:token])
end
end