Devise sign up either by email or by mobile number

前端 未结 2 1863
忘掉有多难
忘掉有多难 2021-02-06 14:53

I can register a user getting both email address and mobile number in my application. But what I really want is to register user using either email or mobile as a primary authen

相关标签:
2条回答
  • 2021-02-06 15:48

    Yes, you can do easily with minor setting.

    like this

    Modify your application_controller.rb

    class ApplicationController < ActionController::Base
      before_action :configure_permitted_parameters, if: :devise_controller?
    
      protected
    
      def configure_permitted_parameters
        added_attrs = [:mobile_no, :email, :password, :password_confirmation, :remember_me]
        devise_parameter_sanitizer.permit :sign_up, keys: added_attrs
        devise_parameter_sanitizer.permit :account_update, keys: added_attrs
      end
    end
    
    Create a login virtual attribute in the User model
    
    Add login as an attr_accessor:
    
      # Virtual attribute for authenticating by either username or email
      # This is in addition to a real persisted field like 'username'
      attr_accessor :login
    or, if you will use this variable somewhere else in the code:
    
      def login=(login)
        @login = login
      end
    
      def login
        @login || self.mobile_no || self.email
      end
    

    Modify config/initializers/devise.rb to have:

    config.authentication_keys = [ :login ]
    

    You can refer this link for more reference.

    https://github.com/plataformatec/devise/wiki/How-To:-Allow-users-to-sign-in-using-their-username-or-email-address

    0 讨论(0)
  • 2021-02-06 15:56

    Aha! I did it. I followed Devise sign in using username or email address, I changed username to mobile and was able to sign in using the mobile number. But the problem I figured is that I was unable to sign up with mobile. So, based on the suggestion of @Hardik, I used some jQuery in my sign up form to accept either mobile or email address.

    Since I have allowed Users to set their password themselves after confirming their email address, it became a problem for the mobile number so I checked for the presence of email in request and skipped the confirmation and set a dynamically generated password which I had declared as a instance variable on registrations_controller.rb file which which inherits form Devise Registrations Controller.

    User Model

    before_save :check_email
    
    
    def check_email
      if !self.email.present?
        skip_confirmation!
      end
    end
    

    Hence, I am able to skip confirmation and I provide a default password.

    Now the application accepts both email address and mobile number. User who register with email address can set their password but for the mobile users, they cannot set their password. So, I used Pilvo SMS api to send their password in their mobile number. For this I used the Pilvo gem and their API and overwrite the Devise Registration Controller.

    Gemfile

    gem 'phonelib'
    gem 'plivo', '~> 0.3.19'
    

    I used Phonelib for the validation of Mobile Numbers.

      require 'rubygems'
      require 'plivo'
      include Plivo
    
    class RegistrationsController < Devise::RegistrationsController
      prepend_before_action :require_no_authentication, only: [:new, :create, :cancel]
      prepend_before_action :authenticate_scope!, only: [:edit, :update, :destroy]
      prepend_before_action :set_minimum_password_length, only: [:new, :edit]
    
      AUTH_ID = "PLIVO AUTH ID"
      AUTH_TOKEN = "PLIVO AUTH TOKEN"
      # GET /resource/sign_up
      def new
        super
      end
    
      # POST /resource
      def create
        if !sign_up_params[:email].present?
            @password = Devise.friendly_token.first(8)
        #begin register
            build_resource
            resource.password = @password
            resource.mobile = sign_up_params[:mobile]
            if resource.save
              if resource.active_for_authentication?
                  set_flash_message :notice, :signed_up_mobile if is_navigational_format?
                  #redirect_to root_path
                  respond_with resource, :location => after_sign_up_path_for(resource)
                        p = RestAPI.new(AUTH_ID, AUTH_TOKEN)
                        # Send SMS
                        params = {
                          'src' => '+9779855065526', # Sender's phone number with country code
                          'dst' => '+'+ sign_up_params[:mobile].to_s, # Receiver's phone Number with country code
                          'text' => t('sms.register', :password => @password.to_s).html_safe, # Your SMS Text Message - English
                          'method' => 'POST' # The method used to call the url
                        }
                        response = p.send_message(params)
              else
                  set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_navigational_format?
                  expire_session_data_after_sign_in!
                  respond_with resource, :location => after_inactive_sign_up_path_for(resource)
              end
            else
                clean_up_passwords resource
                respond_with resource
            end
        else
          super
        end
      end
    
      protected
       def after_sign_up_path_for(resource)
          root_path # Or :prefix_to_your_route
        end
        def after_update_path_for(resource)
          if admin?
            control_index_path
          elsif merchant?
            merchants_path
          elsif customer?
            customers_path
          end
        end
    end
    

    It worked, and I am getting SMS but I am not sure if it is a good or secure approach or not. If this is not a secure approach, please suggest me a favourable way.

    0 讨论(0)
提交回复
热议问题