Files
MySMSAPio/app/controllers/concerns/api_authenticatable.rb
2025-10-22 17:22:17 +08:00

74 lines
1.7 KiB
Ruby

module ApiAuthenticatable
extend ActiveSupport::Concern
included do
before_action :authenticate_api_key!
end
private
def authenticate_api_key!
api_key = extract_api_key
return render_unauthorized("Missing API key") unless api_key
key_digest = Digest::SHA256.hexdigest(api_key)
if api_key.start_with?("gw_")
authenticate_gateway(key_digest)
else
authenticate_client_api_key(key_digest)
end
end
def authenticate_gateway(key_digest)
@current_gateway = Gateway.find_by(api_key_digest: key_digest, active: true)
unless @current_gateway
render_unauthorized("Invalid gateway API key")
end
end
def authenticate_client_api_key(key_digest)
@current_api_key = ApiKey.find_by(key_digest: key_digest, active: true)
unless @current_api_key
render_unauthorized("Invalid API key")
return
end
# Check if key has expired
if @current_api_key.expires_at.present? && @current_api_key.expires_at < Time.current
render_unauthorized("API key has expired")
return
end
@current_api_key.touch(:last_used_at)
end
def extract_api_key
auth_header = request.headers["Authorization"]
return nil unless auth_header
# Support both "Bearer token" and just "token"
auth_header.sub(/^Bearer\s+/, "")
end
def render_unauthorized(message = "Unauthorized")
render json: { error: message }, status: :unauthorized
end
def current_gateway
@current_gateway
end
def current_api_key
@current_api_key
end
def require_permission(permission)
unless @current_api_key&.can?(permission)
render json: { error: "Insufficient permissions" }, status: :forbidden
end
end
end