Home > Software engineering >  Rails: Why user authentication based on two columns in database doesn't work?
Rails: Why user authentication based on two columns in database doesn't work?

Time:11-11

I'm building a white-label service and we need a logic where users should have a chance to authenticate with the same email through different domains (example1.com, example2.com).

I'm using ruby-on-rails 6.1.7, ruby 2.7.0p0 and device 4.8.1

I have tried to do that by using this documentation and I have added to my devise initializer this line config.authentication_keys = [ :email, :domain ]. After that, I created a migrations file where I'm adding indexes:

add_column :users, :domain, :string, null: false, default: 'example.com'
remove_index :users, :email
add_index :users, [:email, :domain], unique: true

also added to Users model:

devise :database_authenticatable, :registerable,
       :recoverable, :rememberable, :trackable, :validatable,
       :confirmable, authentication_keys: [:domain, :email]

def self.find_for_authentication
  where(domain: warden_conditions[:domain], email: warden_conditions[:email]).first
end

and registration controller where I create a new account looks like this:

def create
    build_resource(sign_up_params)
    resource.domain = request.domain
    puts
    puts '*' * 100
    p resource
    puts '*' * 100
    puts
    resource.save

    yield resource if block_given?

    if resource.persisted?
      if resource.active_for_authentication?
        sign_up(resource_name, resource)
      else
        render json: { success: true, location: '/registrations/success' }
      end
    else
      render json: { errors: resource.errors.messages }, status: 422
    end
  end

now I am faced with a problem. In the database, I have an account with the email [email protected] and the domain example1.com, so now when I'm trying to create a new account for the same person with the same email, but from a different domain example2.com I'm getting an error that user with this email exists. I see that devise does the wrong query to the database and this query looks like this User Exists? (1.6ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = $1 LIMIT $2 [["email", "[email protected]"], ["LIMIT", 1]], but it should look like this User Exists? (1.6ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = $1 AND "users"."domain" = $2 LIMIT $3 [["email", "[email protected]"], ["domain", "example.com"], ["LIMIT", 1]]

That I've missed? Thanks for any help.

CodePudding user response:

From the linked page

Check that you do not have :validatable in the devise call on the Model

If you do, :validatable will prevent more than one record having the same email, even in different subdomains.

CodePudding user response:

I think this link would help. https://dev.to/casseylottman/adding-a-field-to-your-sign-up-form-with-devise-10i1

You need to override the create function.

  • Related