# frozen_string_literal # Concern added to controllres to provide methods for authentication. # # Automatically generated by the orthodox gem (https://github.com/katanacode/orthodox) # (c) Copyright 2019 Katana Code Ltd. All Rights Reserved. module Authentication extend ActiveSupport::Concern protected # Sign in a given record as a given type # # record - An AppliationRecord subclass instance (e.g. A Member) # as - A String or Symbol with the model name (e.g. "member") <%- if options[:two_factor] -%> # tfa - Mark as Two-Factor authentication authenticated. <%- end -%> # # Returns Integer def sign_in(record, as:<%= ", tfa: false" if options[:two_factor] -%>) session[:"#{as}_id"] = record.id.to_i <%- if options[:two_factor] -%> session[:"#{as}_tfa_authenticated"] = tfa <%- end -%> end # Sign out a given record type. # # as - A String or Symbol with the model name (e.g. "member") def sign_out(as) session[:"#{as}_id"] = nil <%- if options[:two_factor] -%> session[:"#{as}_tfa_authenticated"] = nil <%- end -%> instance_variable_set("@current_#{as}", nil) end module ClassMethods # Create a bunch of authentication methods for a given ActiveRecord model def authenticate_model(model_name, **options) # Define a current_ method to load the currently signed in record, if present # # Returns ApplicationRecord subclass define_method(:"current_#{model_name}") do instance_method_name = "@current_#{model_name}" if instance_variable_get(instance_method_name).present? instance_variable_get(instance_method_name) else scope = send(:"#{model_name}_auth_scope") instance_variable_set(instance_method_name, scope.find_by(id: session[:"#{model_name}_id"])) end end # Define a controller before_action method to authenticate a record for the given # model. Redirects to the _failed_authentication_url if not passed. # # Returns nil define_method(:"authenticate_#{model_name}") do unless send(:"current_#{model_name}?") redirect_to send(:"#{model_name}_failed_authentication_url"), warn: "You must be signed in to do that" end end before_action :"authenticate_#{model_name}" # Creates a scope that records are loaded through when being authenticated. Subclass # this method to customise the load conditions. # # Returns ActiveRecord::Relation define_method(:"#{model_name}_auth_scope") do model_name.to_s.classify.constantize.all end # Creates a boolean method to check if a current_ has been authenticated # or not. # # Returns Boolean define_method(:"current_#{model_name}?") { send(:"current_#{model_name}").present? } define_method(:"#{model_name}_signed_in?") { send(:"current_#{model_name}?") } define_method(:"#{model_name}_failed_authentication_url") do send(:"new_#{model_name.to_s.pluralize}_session_url") end helper_method :"current_#{model_name}" helper_method :"current_#{model_name}?" helper_method :"#{model_name}_signed_in?" protected :"current_#{model_name}" protected :"current_#{model_name}?" protected :"#{model_name}_signed_in?" protected :"authenticate_#{model_name}" <%- if options[:two_factor] -%> # This is included if the authentication generator is run with --two-factor=true if options[:tfa] == true include TwoFactorAuthentication define_tfa_methods(model_name) end <%- end -%> end end end