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
|
class Api::V1::BaseController < ApplicationController
|
||||||
|
include ApiKeyAuthentication
|
||||||
|
|
||||||
|
# Require API key authentication
|
||||||
|
prepend_before_action :authenticate_with_api_key!
|
||||||
|
|
||||||
# before_action :authenticate
|
# before_action :authenticate
|
||||||
|
|
||||||
protect_from_forgery with: :null_session
|
protect_from_forgery with: :null_session
|
||||||
|
|
|
@ -12,14 +12,15 @@ class Api::V1::ChecksController < Api::V1::BaseController
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
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.
|
# Use callbacks to share common setup or constraints between actions.
|
||||||
def check_params
|
def set_check
|
||||||
params.require(:check).permit(:name, :description, :hostname)
|
@check = Check.find(params[:id])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Only allow a list of trusted parameters through.
|
||||||
|
def check_params
|
||||||
|
params.require(:check).permit(:name, :description, :hostname)
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
|
@ -1,5 +1,5 @@
|
||||||
class ApplicationController < ActionController::Base
|
class ApplicationController < ActionController::Base
|
||||||
include Authentication
|
include BasicAuthentication
|
||||||
include Pundit
|
include Pundit
|
||||||
|
|
||||||
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
|
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 ]
|
before_action :set_check, only: %i[ show edit update destroy ]
|
||||||
|
|
||||||
# GET /checks or /checks.json
|
# 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
|
class PasswordsController < ApplicationController
|
||||||
before_action :redirect_if_authenticated
|
before_action :redirect_if_authenticated
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@user = User.find_by(email: params[:user][:email].downcase)
|
@user = User.find_by(email: params[:user][:email].downcase)
|
||||||
if @user.present?
|
if @user.present?
|
||||||
if @user.confirmed?
|
if @user.confirmed?
|
||||||
@user.send_password_reset_email!
|
@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
|
|
||||||
redirect_to root_path, notice: "If that user exists we've sent instructions to their 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
|
else
|
||||||
flash.now[:alert] = "Invalid or expired token."
|
redirect_to new_confirmation_path, alert: "Please confirm your email first."
|
||||||
render :new, status: :unprocessable_entity
|
|
||||||
end
|
end
|
||||||
end
|
else
|
||||||
|
redirect_to root_path, notice: "If that user exists we've sent instructions to their email."
|
||||||
private
|
|
||||||
|
|
||||||
def password_params
|
|
||||||
params.require(:user).permit(:password, :password_confirmation)
|
|
||||||
end
|
end
|
||||||
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
|
class SessionsController < ApplicationController
|
||||||
before_action :redirect_if_authenticated, only: [:create, :new]
|
before_action :redirect_if_authenticated, only: [:create, :new]
|
||||||
before_action :authenticate_user!, only: [:destroy]
|
before_action :authenticate_user!, only: [:destroy]
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@user = User.authenticate_by(email: params[:user][:email].downcase, password: params[:user][:password])
|
@user = User.authenticate_by(email: params[:user][:email].downcase, password: params[:user][:password])
|
||||||
if @user
|
if @user
|
||||||
if @user.unconfirmed?
|
if @user.unconfirmed?
|
||||||
redirect_to new_confirmation_path, alert: "Incorrect email or password."
|
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
|
|
||||||
else
|
else
|
||||||
flash.now[:alert] = "Incorrect email or password."
|
after_login_path = session[:user_return_to] || root_path
|
||||||
render :new, status: :unprocessable_entity
|
login @user
|
||||||
|
remember(@user) if params[:user][:remember_me] == "1"
|
||||||
|
redirect_to after_login_path, notice: "Signed in."
|
||||||
end
|
end
|
||||||
end
|
else
|
||||||
|
flash.now[:alert] = "Incorrect email or password."
|
||||||
def destroy
|
render :new, status: :unprocessable_entity
|
||||||
forget(current_user)
|
|
||||||
logout
|
|
||||||
redirect_to root_path, notice: "Signed out."
|
|
||||||
end
|
|
||||||
|
|
||||||
def new
|
|
||||||
end
|
end
|
||||||
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
|
namespace :v1 do
|
||||||
defaults format: :json do
|
defaults format: :json do
|
||||||
get '/ping', to: 'base#ping'
|
get '/ping', to: 'base#ping'
|
||||||
resources :api_keys, path: 'api-keys', only: %i[index create destroy]
|
|
||||||
resources :checks, only: [:create]
|
resources :checks, only: [:create]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue