mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2024-11-11 10:06:53 +08:00
94 lines
2.8 KiB
Ruby
94 lines
2.8 KiB
Ruby
module Api
|
|
class ApiController < ActionController::API
|
|
attr_reader :iss
|
|
attr_reader :token
|
|
attr_reader :current_user
|
|
|
|
before_action :load_token, except: %i(authenticate status health)
|
|
before_action :load_iss, except: %i(authenticate status health)
|
|
before_action :authenticate_request!, except: %i(authenticate status health)
|
|
|
|
rescue_from StandardError do |e|
|
|
logger.error e.message
|
|
render json: {}, status: :bad_request
|
|
end
|
|
|
|
rescue_from JWT::InvalidPayload, JWT::DecodeError do |e|
|
|
logger.error e.message
|
|
render json: { message: I18n.t('api.core.invalid_token') },
|
|
status: :unauthorized
|
|
end
|
|
|
|
def initialize
|
|
super
|
|
@iss = nil
|
|
end
|
|
|
|
def health
|
|
render plain: 'RUNNING'
|
|
end
|
|
|
|
def status
|
|
response = {}
|
|
response[:message] = I18n.t('api.core.status_ok')
|
|
response[:versions] = []
|
|
Extends::API_VERSIONS.each do |ver|
|
|
response[:versions] << { version: ver, baseUrl: "/api/#{ver}/" }
|
|
end
|
|
render json: response, status: :ok
|
|
end
|
|
|
|
def authenticate
|
|
if auth_params[:grant_type] == 'password'
|
|
user = User.find_by_email(auth_params[:email])
|
|
unless user && user.valid_password?(auth_params[:password])
|
|
raise StandardError, 'Wrong user password'
|
|
end
|
|
payload = { user_id: user.id }
|
|
token = CoreJwt.encode(payload)
|
|
render json: { token_type: 'bearer', access_token: token }
|
|
else
|
|
raise StandardError, 'Wrong grant type in request'
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
def load_token
|
|
if request.headers['Authorization']
|
|
@token =
|
|
request.headers['Authorization'].scan(/Bearer (.*)$/).flatten.last
|
|
end
|
|
raise StandardError, 'No token in the header' unless @token
|
|
end
|
|
|
|
def authenticate_request!
|
|
Extends::API_PLUGABLE_AUTH_METHODS.each do |auth_method|
|
|
method(auth_method).call
|
|
return true if current_user
|
|
end
|
|
# Check request header for proper auth token
|
|
payload = CoreJwt.decode(token)
|
|
@current_user = User.find_by_id(payload['user_id'])
|
|
# Implement sliding sessions, i.e send new token in case of successful
|
|
# authorization and when tokens TTL reached specific value (to avoid token
|
|
# generation on each request)
|
|
if CoreJwt.refresh_needed?(payload)
|
|
new_token = CoreJwt.encode(user_id: @current_user.id)
|
|
response.headers['X-Access-Token'] = new_token
|
|
end
|
|
rescue JWT::ExpiredSignature
|
|
render json: { message: I18n.t('api.core.expired_token') },
|
|
status: :unauthorized
|
|
end
|
|
|
|
def load_iss
|
|
@iss = CoreJwt.read_iss(token)
|
|
raise JWT::InvalidPayload, 'Wrong ISS in the token' unless @iss
|
|
end
|
|
|
|
def auth_params
|
|
params.permit(:grant_type, :email, :password)
|
|
end
|
|
end
|
|
end
|