Commit e0cc30a9 by liyijie

Copy authentication exist code to project.

parent 225a0743
require "rails_api_authentication/version" require "rails_api_authentication/version"
module RailsApiAuthentication module RailsApiAuthentication
VERSION = "0.1"
end end
module RailsApiAuthentication
module AuthAction
extend ActiveSupport::Concern
included do
private :perform
end
def perform
klass = self.class.action_class
@current_auth = klass.send(:auth!, request)
rescue UserError => e
render json: e.message, status: e.status
end
module ClassMethods
def auth_action klass_sym, options={}
before_action :perform, options
@klass = klass_sym.to_s.camelize.constantize
define_method("current_#{klass_sym}") { @current_auth || nil }
end
def action_class
@klass
end
end
end
end
module RailsApiAuthentication
module AuthSession
extend ActiveSupport::Concern
included do
end
def create
auth_key = self.class.klass.auth_key
auth_password = self.class.klass.auth_password
@auth_token = self.class.klass.login(session_params[auth_key], session_params[auth_password])
render json: { token: @auth_token.token }, status: 200
rescue UserError => e
render json: e.message, status: e.status
end
def destroy
self.send("current_#{self.class.klass_sym}")&.logout
render json: "logout successful", status: 200
end
private
def session_params
auth_key = self.class.klass.auth_key
auth_password = self.class.klass.auth_password
params.require(self.class.klass_sym).permit(auth_key, auth_password)
end
module ClassMethods
attr_reader :klass, :klass_sym
def auth_session klass_sym
@klass = klass_sym.to_s.camelize.constantize
@klass_sym = klass_sym
end
end
end
end
module RailsApiAuthentication
class AuthToken < Ohm::Model
# Authentication Token, should be unique
attribute :token
# authable model id, relate to the actual model
attribute :oid
# authable model class, relate to the actual model
attribute :klass
# client authentication platform, etc: ios, android, web
attribute :platform
# client authentication vertion, etc: 4.1.2
attribute :version
index :token
unique :token
index :klass
def self.create(klass, params = {})
params[:klass] = klass
params[:token] = SecureRandom.uuid62
super params
end
end
end
\ No newline at end of file
module RailsApiAuthentication
module Authable
extend ActiveSupport::Concern
DIGEST = Digest::SHA2.new
included do
attr_accessor :token
def logout
AuthToken.find(token: token)&.first&.delete if token.present?
end
end
module ClassMethods
attr_reader :auth_key, :auth_password
def auth_for params
@auth_key = params[:auth_key]&.to_sym || :name
@auth_password = params[:auth_password]&.to_sym || :password
end
def login(name, password)
user = self.find_by(@auth_key => name)
raise(UserError.new(401, '-1', 'Unauthorized')) if user.nil?
salted = user.password.split(':')
raise(UserError.new(401, '-1', 'Unauthorized')) unless salt(password, salted[1]) == salted[0]
AuthToken.create(self, { oid: user.id })
end
def auth!(request)
user = auth(request)
user.nil? ? raise(UserError.new(401, '-1', 'Unauthorized')) : user
end
def register(name, password)
raise(UserError.new(401, '-1', 'password is blank')) if password.blank?
self.create!(@auth_key => name, @auth_password => generate_password(password))
rescue ActiveRecord::RecordInvalid => e
raise UserError.new(401, '-1', e.message)
end
private
def salt(password, suffix)
5.times { password = DIGEST.digest(password + suffix) }
password.unpack('H*')[0]
end
def generate_password(password)
suffix = SecureRandom.hex 8
"#{salt(password, suffix)}:#{suffix}"
end
def auth(request)
token = request.env["HTTP_#{self.to_s.upcase}_TOKEN"] || request.env["#{self.to_s.upcase}_TOKEN"]
auth = AuthToken.find(token: token)&.first
if auth.nil?
nil
else
user = self.find_by(id: auth.oid)
user.token = auth.token
user
end
end
end
end
class UserError < RuntimeError
attr_reader :status, :code, :message
def initialize(status, code, message)
super()
@status = status
@code = code
@message = message
end
end
end
...@@ -30,6 +30,10 @@ Gem::Specification.new do |spec| ...@@ -30,6 +30,10 @@ Gem::Specification.new do |spec|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"] spec.require_paths = ["lib"]
# Object-Hash Mapping for Redis
# https://github.com/soveran/ohm
spec.add_dependency "ohm"
spec.add_development_dependency "bundler", "~> 1.14" spec.add_development_dependency "bundler", "~> 1.14"
spec.add_development_dependency "rake", "~> 10.0" spec.add_development_dependency "rake", "~> 10.0"
spec.add_development_dependency "rspec", "~> 3.0" spec.add_development_dependency "rspec", "~> 3.0"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment