Devise sign up either by email or by mobile number

前端 未结 2 1862
忘掉有多难
忘掉有多难 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条回答
  •  闹比i
    闹比i (楼主)
    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.

提交回复
热议问题