Authentification par Token en mode API et Basic en mode navigateur
This commit is contained in:
parent
41d1d6d8fe
commit
e13fb4828a
|
@ -1,30 +0,0 @@
|
|||
class Api::V1::ApiKeysController < Api::V1::BaseController
|
||||
# include ApiKeyAuthenticable
|
||||
|
||||
# # Require API key authentication
|
||||
# prepend_before_action :authenticate_with_api_key!, only: %i[index destroy]
|
||||
|
||||
def index
|
||||
render json: current_bearer.api_keys
|
||||
end
|
||||
|
||||
def create
|
||||
authenticate_with_http_basic do |email, password|
|
||||
user = User.find_by email: email
|
||||
|
||||
if user&.authenticate(password)
|
||||
api_key = user.api_keys.create! token: SecureRandom.hex
|
||||
|
||||
render json: api_key, status: :created and return
|
||||
end
|
||||
end
|
||||
|
||||
render status: :unauthorized
|
||||
end
|
||||
|
||||
def destroy
|
||||
api_key = current_bearer.api_keys.find(params[:id])
|
||||
|
||||
api_key.destroy
|
||||
end
|
||||
end
|
|
@ -1,4 +1,9 @@
|
|||
class Api::V1::BaseController < ApplicationController
|
||||
include ApiKeyAuthentication
|
||||
|
||||
# Require API key authentication
|
||||
prepend_before_action :authenticate_with_api_key!
|
||||
|
||||
# before_action :authenticate
|
||||
|
||||
protect_from_forgery with: :null_session
|
||||
|
|
|
@ -12,14 +12,15 @@ class Api::V1::ChecksController < Api::V1::BaseController
|
|||
end
|
||||
|
||||
private
|
||||
# Use callbacks to share common setup or constraints between actions.
|
||||
def set_check
|
||||
@check = Check.find(params[:id])
|
||||
end
|
||||
|
||||
# Only allow a list of trusted parameters through.
|
||||
def check_params
|
||||
params.require(:check).permit(:name, :description, :hostname)
|
||||
end
|
||||
# Use callbacks to share common setup or constraints between actions.
|
||||
def set_check
|
||||
@check = Check.find(params[:id])
|
||||
end
|
||||
|
||||
# Only allow a list of trusted parameters through.
|
||||
def check_params
|
||||
params.require(:check).permit(:name, :description, :hostname)
|
||||
end
|
||||
|
||||
end
|
|
@ -1,5 +1,5 @@
|
|||
class ApplicationController < ActionController::Base
|
||||
include Authentication
|
||||
include BasicAuthentication
|
||||
include Pundit
|
||||
|
||||
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
|
||||
|
|
3
app/controllers/authenticated_controller.rb
Normal file
3
app/controllers/authenticated_controller.rb
Normal file
|
@ -0,0 +1,3 @@
|
|||
class AuthenticatedController < ApplicationController
|
||||
before_action :authenticate_user!
|
||||
end
|
|
@ -1,4 +1,4 @@
|
|||
class ChecksController < ApplicationController
|
||||
class ChecksController < AuthenticatedController
|
||||
before_action :set_check, only: %i[ show edit update destroy ]
|
||||
|
||||
# GET /checks or /checks.json
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
module ApiKeyAuthenticatable
|
||||
include ActionController::HttpAuthentication::Basic::ControllerMethods
|
||||
include ActionController::HttpAuthentication::Token::ControllerMethods
|
||||
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
attr_reader :current_api_key
|
||||
attr_reader :current_bearer
|
||||
|
||||
# Use this to raise an error and automatically respond with a 401 HTTP status
|
||||
# code when API key authentication fails
|
||||
def authenticate_with_api_key!
|
||||
@current_bearer = authenticate_or_request_with_http_token &method(:authenticator)
|
||||
end
|
||||
|
||||
# Use this for optional API key authentication
|
||||
def authenticate_with_api_key
|
||||
@current_bearer = authenticate_with_http_token &method(:authenticator)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_writer :current_api_key
|
||||
attr_writer :current_bearer
|
||||
|
||||
def authenticator(token, options)
|
||||
@current_api_key = ApiKey.authenticate_by_token token
|
||||
|
||||
current_api_key&.bearer
|
||||
end
|
||||
end
|
31
app/controllers/concerns/api_key_authentication.rb
Normal file
31
app/controllers/concerns/api_key_authentication.rb
Normal file
|
@ -0,0 +1,31 @@
|
|||
module ApiKeyAuthentication
|
||||
include ActionController::HttpAuthentication::Basic::ControllerMethods
|
||||
include ActionController::HttpAuthentication::Token::ControllerMethods
|
||||
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
attr_reader :current_api_key
|
||||
attr_reader :current_bearer
|
||||
|
||||
# Use this to raise an error and automatically respond with a 401 HTTP status
|
||||
# code when API key authentication fails
|
||||
def authenticate_with_api_key!
|
||||
@current_bearer = authenticate_or_request_with_http_token &method(:authenticator)
|
||||
end
|
||||
|
||||
# Use this for optional API key authentication
|
||||
def authenticate_with_api_key
|
||||
@current_bearer = authenticate_with_http_token &method(:authenticator)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_writer :current_api_key
|
||||
attr_writer :current_bearer
|
||||
|
||||
def authenticator(token, options)
|
||||
@current_api_key = ApiKey.authenticate_by_token token
|
||||
|
||||
current_api_key&.bearer
|
||||
end
|
||||
end
|
|
@ -1,58 +0,0 @@
|
|||
module Authentication
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
before_action :current_user
|
||||
helper_method :current_user
|
||||
helper_method :user_signed_in?
|
||||
end
|
||||
|
||||
def authenticate_user!
|
||||
store_location
|
||||
redirect_to login_path, alert: "You need to login to access that page." unless user_signed_in?
|
||||
end
|
||||
|
||||
def login(user)
|
||||
reset_session
|
||||
user.regenerate_session_token
|
||||
session[:current_user_session_token] = user.reload.session_token
|
||||
end
|
||||
|
||||
def forget(user)
|
||||
cookies.delete :remember_token
|
||||
user.regenerate_remember_token
|
||||
end
|
||||
|
||||
def logout
|
||||
user = current_user
|
||||
reset_session
|
||||
user.regenerate_session_token
|
||||
end
|
||||
|
||||
def redirect_if_authenticated
|
||||
redirect_to root_path, alert: "You are already logged in." if user_signed_in?
|
||||
end
|
||||
|
||||
def remember(user)
|
||||
user.regenerate_remember_token
|
||||
cookies.permanent.encrypted[:remember_token] = user.remember_token
|
||||
end
|
||||
|
||||
def store_location
|
||||
session[:user_return_to] = request.original_url if request.get? && request.local?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def current_user
|
||||
Current.user ||= if session[:current_user_session_token].present?
|
||||
User.find_by(session_token: session[:current_user_session_token])
|
||||
elsif cookies.permanent.encrypted[:remember_token].present?
|
||||
User.find_by(remember_token: cookies.permanent.encrypted[:remember_token])
|
||||
end
|
||||
end
|
||||
|
||||
def user_signed_in?
|
||||
Current.user.present?
|
||||
end
|
||||
end
|
58
app/controllers/concerns/basic_authentication.rb
Normal file
58
app/controllers/concerns/basic_authentication.rb
Normal file
|
@ -0,0 +1,58 @@
|
|||
module BasicAuthentication
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
before_action :current_user
|
||||
helper_method :current_user
|
||||
helper_method :user_signed_in?
|
||||
end
|
||||
|
||||
def authenticate_user!
|
||||
store_location
|
||||
redirect_to login_path, alert: "You need to login to access that page." unless user_signed_in?
|
||||
end
|
||||
|
||||
def login(user)
|
||||
reset_session
|
||||
user.regenerate_session_token
|
||||
session[:current_user_session_token] = user.reload.session_token
|
||||
end
|
||||
|
||||
def forget(user)
|
||||
cookies.delete :remember_token
|
||||
user.regenerate_remember_token
|
||||
end
|
||||
|
||||
def logout
|
||||
user = current_user
|
||||
reset_session
|
||||
user.regenerate_session_token
|
||||
end
|
||||
|
||||
def redirect_if_authenticated
|
||||
redirect_to root_path, alert: "You are already logged in." if user_signed_in?
|
||||
end
|
||||
|
||||
def remember(user)
|
||||
user.regenerate_remember_token
|
||||
cookies.permanent.encrypted[:remember_token] = user.remember_token
|
||||
end
|
||||
|
||||
def store_location
|
||||
session[:user_return_to] = request.original_url if request.get? && request.local?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def current_user
|
||||
Current.user ||= if session[:current_user_session_token].present?
|
||||
User.find_by(session_token: session[:current_user_session_token])
|
||||
elsif cookies.permanent.encrypted[:remember_token].present?
|
||||
User.find_by(remember_token: cookies.permanent.encrypted[:remember_token])
|
||||
end
|
||||
end
|
||||
|
||||
def user_signed_in?
|
||||
Current.user.present?
|
||||
end
|
||||
end
|
|
@ -1,53 +1,52 @@
|
|||
class PasswordsController < ApplicationController
|
||||
before_action :redirect_if_authenticated
|
||||
|
||||
def create
|
||||
@user = User.find_by(email: params[:user][:email].downcase)
|
||||
if @user.present?
|
||||
if @user.confirmed?
|
||||
@user.send_password_reset_email!
|
||||
redirect_to root_path, notice: "If that user exists we've sent instructions to their email."
|
||||
else
|
||||
redirect_to new_confirmation_path, alert: "Please confirm your email first."
|
||||
end
|
||||
else
|
||||
before_action :redirect_if_authenticated
|
||||
|
||||
def create
|
||||
@user = User.find_by(email: params[:user][:email].downcase)
|
||||
if @user.present?
|
||||
if @user.confirmed?
|
||||
@user.send_password_reset_email!
|
||||
redirect_to root_path, notice: "If that user exists we've sent instructions to their email."
|
||||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
@user = User.find_signed(params[:password_reset_token], purpose: :reset_password)
|
||||
if @user.present? && @user.unconfirmed?
|
||||
redirect_to new_confirmation_path, alert: "You must confirm your email before you can sign in."
|
||||
elsif @user.nil?
|
||||
redirect_to new_password_path, alert: "Invalid or expired token."
|
||||
end
|
||||
end
|
||||
|
||||
def new
|
||||
end
|
||||
|
||||
def update
|
||||
@user = User.find_signed(params[:password_reset_token], purpose: :reset_password)
|
||||
if @user
|
||||
if @user.unconfirmed?
|
||||
redirect_to new_confirmation_path, alert: "You must confirm your email before you can sign in."
|
||||
elsif @user.update(password_params)
|
||||
redirect_to login_path, notice: "Sign in."
|
||||
else
|
||||
flash.now[:alert] = @user.errors.full_messages.to_sentence
|
||||
render :edit, status: :unprocessable_entity
|
||||
end
|
||||
else
|
||||
flash.now[:alert] = "Invalid or expired token."
|
||||
render :new, status: :unprocessable_entity
|
||||
redirect_to new_confirmation_path, alert: "Please confirm your email first."
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def password_params
|
||||
params.require(:user).permit(:password, :password_confirmation)
|
||||
else
|
||||
redirect_to root_path, notice: "If that user exists we've sent instructions to their email."
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def edit
|
||||
@user = User.find_signed(params[:password_reset_token], purpose: :reset_password)
|
||||
if @user.present? && @user.unconfirmed?
|
||||
redirect_to new_confirmation_path, alert: "You must confirm your email before you can sign in."
|
||||
elsif @user.nil?
|
||||
redirect_to new_password_path, alert: "Invalid or expired token."
|
||||
end
|
||||
end
|
||||
|
||||
def new
|
||||
end
|
||||
|
||||
def update
|
||||
@user = User.find_signed(params[:password_reset_token], purpose: :reset_password)
|
||||
if @user
|
||||
if @user.unconfirmed?
|
||||
redirect_to new_confirmation_path, alert: "You must confirm your email before you can sign in."
|
||||
elsif @user.update(password_params)
|
||||
redirect_to login_path, notice: "Sign in."
|
||||
else
|
||||
flash.now[:alert] = @user.errors.full_messages.to_sentence
|
||||
render :edit, status: :unprocessable_entity
|
||||
end
|
||||
else
|
||||
flash.now[:alert] = "Invalid or expired token."
|
||||
render :new, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def password_params
|
||||
params.require(:user).permit(:password, :password_confirmation)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,31 +1,30 @@
|
|||
class SessionsController < ApplicationController
|
||||
before_action :redirect_if_authenticated, only: [:create, :new]
|
||||
before_action :authenticate_user!, only: [:destroy]
|
||||
|
||||
def create
|
||||
@user = User.authenticate_by(email: params[:user][:email].downcase, password: params[:user][:password])
|
||||
if @user
|
||||
if @user.unconfirmed?
|
||||
redirect_to new_confirmation_path, alert: "Incorrect email or password."
|
||||
else
|
||||
after_login_path = session[:user_return_to] || root_path
|
||||
login @user
|
||||
remember(@user) if params[:user][:remember_me] == "1"
|
||||
redirect_to after_login_path, notice: "Signed in."
|
||||
end
|
||||
before_action :redirect_if_authenticated, only: [:create, :new]
|
||||
before_action :authenticate_user!, only: [:destroy]
|
||||
|
||||
def create
|
||||
@user = User.authenticate_by(email: params[:user][:email].downcase, password: params[:user][:password])
|
||||
if @user
|
||||
if @user.unconfirmed?
|
||||
redirect_to new_confirmation_path, alert: "Incorrect email or password."
|
||||
else
|
||||
flash.now[:alert] = "Incorrect email or password."
|
||||
render :new, status: :unprocessable_entity
|
||||
after_login_path = session[:user_return_to] || root_path
|
||||
login @user
|
||||
remember(@user) if params[:user][:remember_me] == "1"
|
||||
redirect_to after_login_path, notice: "Signed in."
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
forget(current_user)
|
||||
logout
|
||||
redirect_to root_path, notice: "Signed out."
|
||||
end
|
||||
|
||||
def new
|
||||
else
|
||||
flash.now[:alert] = "Incorrect email or password."
|
||||
render :new, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def destroy
|
||||
forget(current_user)
|
||||
logout
|
||||
redirect_to root_path, notice: "Signed out."
|
||||
end
|
||||
|
||||
def new
|
||||
end
|
||||
end
|
|
@ -4,7 +4,6 @@ Rails.application.routes.draw do
|
|||
namespace :v1 do
|
||||
defaults format: :json do
|
||||
get '/ping', to: 'base#ping'
|
||||
resources :api_keys, path: 'api-keys', only: %i[index create destroy]
|
||||
resources :checks, only: [:create]
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue