I have 2 database tables namely coreteam
and user
. Both the models are configured with devise.
For now to sign in for core team my API is: localhost:3000/api/v1/core_teams/sign_in
with following request data.
{
"core_team": {
"email": "[email protected]",
"password": "Password21"
}
}
And the API for users to sign in is: localhost:3000//api/v1/users/sign_in
with the following request data.
{
"user": {
"email": "[email protected]",
"password": "Password20"
}
}
And following is my routes.rb file
Rails.application.routes.draw do
root to: 'users#index'
scope 'api/v1', defaults: { format: :json } do
devise_for :core_teams, controllers: {
sessions: 'api/v1/sessions',
passwords: 'api/v1/passwords'
}
devise_for :users, controllers: {
sessions: 'api/v1/sessions',
invitations: 'api/v1/invitations',
passwords: 'api/v1/passwords',
registrations: 'api/v1/registrations'
}
end
end
And I am using devise sessionscontroller to login. Only difference is the way I am rendering the data.
My sessions_controller.rb is as follows:
module Api
module V1
class SessionsController < Devise::SessionsController
private
def respond_with(resource, _opts = {})
render json: resource
end
def respond_to_on_destroy
head :no_content
end
end
end
end
Now my aim is to have only one API call to sign in using the same type of requests data. Reason to have two different user table is my app is kind of multi-tenanted and core team is outside of tenant and users are inside tenant.
Try this
routes
post "/api/v1/sign_in" => "api/v1/sessions#create"
devise_for :users, ...
devise_for :core_teams, ...
api/v1/sessions_controller.rb
module Api
module V1
class SessionsController < Devise::SessionsController
before_action :rewrite_request_params, only: %i[create]
protected
def devise_mapping
@devise_mapping ||= Devise.mappings[account_name || :user]
end
private
def rewrite_request_params
return unless account_name
request.params[account_name] = {
email: params[:email],
password: params[:password],
}
end
def account_name
@account_name ||= account.class.name.underscore.to_sym if account
end
def account
return if params[:email].blank?
return @account if defined? @account
@account = CoreTeam.find_by(email: params[:email]) || User.find_by(email: params[:email])
end
end
end
end
this will allow you to submit params to /api/v1/sign_in
for both User
and CoreTeam
First it will look for an account
in core_teams
table then users
table. if found it will rewrite the request.params
# core_teams
$.post('/api/v1/sign_in', {
"email": "[email protected]",
"password": "Password21"
})
# users
$.post('/api/v1/sign_in', {
"email": "[email protected]",
"password": "Password20"
})