Skip to content

Mongoid support #1198

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
8 tasks done
dks17 opened this issue Aug 1, 2018 · 16 comments
Closed
8 tasks done

Mongoid support #1198

dks17 opened this issue Aug 1, 2018 · 16 comments
Labels

Comments

@dks17
Copy link
Contributor

dks17 commented Aug 1, 2018

Hello.
I would like bring Mongoid gem support for the gem. Now the gem is not working with Mongoid as fact.

General plan is:

References:

@MaicolBen
Copy link
Collaborator

Check #15, we might put a bounty on this issue

@dks17
Copy link
Contributor Author

dks17 commented Aug 2, 2018

Check #15, we might put a bounty on this issue

It is old issue. Now situation is more complicated then it was in 2014. I have encounted with many other issues including this.

The gem is hardcoded on ActiveRecord. And when the concern DeviseTokenAuth::Concerns::User is included in Mongoid model it influences nothing because of the gem is already initialized with ActtiveRecord.

@dks17
Copy link
Contributor Author

dks17 commented Aug 12, 2018

devise use the same :locked_at field as mongoid-locker. They both use the same field for different purposes. Allow customizing locked_at field (clash with Devise)

class LockableUser
  include Mongoid::Document
  include Mongoid::Timestamps
  include Mongoid::Locker

  # many fields here

  ## Lockable
  field :failed_attempts, type: Integer, default: 0 # Only if lock strategy is :failed_attempts
  field :unlock_token,    type: String # Only if unlock strategy is :email or :both
  field :locked_at,       type: Time

  # Include default devise modules.
  devise :database_authenticatable, :registerable, :lockable
  include DeviseTokenAuth::Concerns::User

  include Mongoid::Locker
end

When Mongoid::Locker is included there is warn in console

WARN -- : Overwriting existing field locked_at in class LockableUser.

I have already pulled patch into mongoid-locker and hope it will be accepted (Customizable :locked_at and :locked_until fields). Or we should care about another solution for it.

Update
Fixed in new 1.0.0 version of mongoid-locker gem.

@dks17
Copy link
Contributor Author

dks17 commented Aug 26, 2018

@MaicolBen
I would like replace find_resource method

  def find_resource(field, value)
    # fix for mysql default case insensitivity
    q = "#{field.to_s} = ? AND provider='#{provider.to_s}'"
    if ActiveRecord::Base.connection.adapter_name.downcase.starts_with? 'mysql'
      q = 'BINARY ' + q
    end

    @resource = resource_class.where(q, value).first
end

by

def find_resource(field, value)
  @resource = resource_class.where({"#{field}": value, provider: provider}).first
end

With my implementation all tests passed except with mysql.
Is there another way to check adapter name and avoid 'BINARY' using?

Update
I'm looking for suitable implementation for both ORM and ODM.

The gem is tuned to work with Mongoid without ActiveRecord.

NameError:         NameError: uninitialized constant DeviseTokenAuth::Concerns::ResourceFinder::ActiveRecord

@MaicolBen
Copy link
Collaborator

@dks17 I don't know the reason of the BINARY, maybe @lynndylanhurley knows. Try to avoid making a huge PR for mongo

@dks17
Copy link
Contributor Author

dks17 commented Sep 2, 2018

Does anyone else need mongoid for this gem?

@dks17
Copy link
Contributor Author

dks17 commented Sep 2, 2018

@MaicolBen I have almost finished.

Should I add generator for mongoid user model and documentation in upcoming pr?

I should write description about changes. How should do it better?

  • Should I add some UPGRADE.md file? (by default you must have devise config file or specify ORM)
  • Should I put description in separate file i.e. MONGOID.md, about using the gem with mongoid.

@MaicolBen
Copy link
Collaborator

MaicolBen commented Sep 3, 2018

Why UPGRADE.md ? I would recommend adding a section mongo in https://github.com/lynndylanhurley/devise_token_auth/blob/master/SUMMARY.md and add the doc under docs, if you want to see examples: click the docs link in the readme

@dks17
Copy link
Contributor Author

dks17 commented Sep 3, 2018

Why UPGRADE.md ?

Upcoming changes may break initialization order of the gem. I just want users be informed about it. We discuss it when I pull changes. Hope for your help.
Thanks.

@dks17
Copy link
Contributor Author

dks17 commented Sep 6, 2018

@MaicolBen need your help.
This two methods in rescue block are never fired. It looks like duplicate of functionality in else block which is above.

begin
# override email confirmation, must be sent manually from ctrl
resource_class.set_callback('create', :after, :send_on_create_confirmation_instructions)
resource_class.skip_callback('create', :after, :send_on_create_confirmation_instructions)
if @resource.respond_to? :skip_confirmation_notification!
# Fix duplicate e-mails by disabling Devise confirmation e-mail
@resource.skip_confirmation_notification!
end
if @resource.save
yield @resource if block_given?
if @resource.confirmed?
# email auth has been bypassed, authenticate user
@client_id, @token = @resource.create_token
@resource.save!
update_auth_header
else
# user will require email authentication
@resource.send_confirmation_instructions(
client_config: params[:config_name],
redirect_url: @redirect_url
)
end
render_create_success
else
clean_up_passwords @resource
render_create_error
end
rescue ActiveRecord::RecordNotUnique
clean_up_passwords @resource
render_create_error_email_already_exists
end
end

This piece of code is not covered with tests.

describe 'Existing users' do
before do
@existing_user = create(:user, :confirmed)
post '/auth',
params: { email: @existing_user.email,
password: 'secret123',
password_confirmation: 'secret123',
confirm_success_url: Faker::Internet.url }
@resource = assigns(:resource)
@data = JSON.parse(response.body)
end
test 'request should not be successful' do
assert_equal 422, response.status
end
test 'user should have been created' do
assert_nil @resource.id
end
test 'error should be returned in the response' do
assert @data['errors'].length
end
end

Value of @data['errors'] in tests is:

{"email"=>["has already been taken"],
 "full_messages"=>["Email has already been taken"]}

response.status is also 422.

I need to avoid ActiveRecord constant in the code. What should I do with it? Can I remove this rescue block and render_create_error_email_already_exists method?

Update
rescue block and render_create_error_email_already_exists method were removed in #1209 PR.

@MaicolBen
Copy link
Collaborator

@dks17 it makes sense, save without bang won't raise exceptions

@MaicolBen
Copy link
Collaborator

@dks17 is there any tasks missing for completing this support?

@dks17
Copy link
Contributor Author

dks17 commented Oct 25, 2018

@MaicolBen It's completed. Thanks.

@dks17
Copy link
Contributor Author

dks17 commented Dec 10, 2018

I got bounty for this. Thanks to the community.

@luzioluna
Copy link

luzioluna commented Feb 27, 2019

Hello! So is devise_token_auth compatible with mongoid now? I am still only able to get it to run at all with the BunHouth/devise_token_auth.git', branch: 'mongoid' version but it is throwing the Unpermitted parameters: :format, :session errors.
as well the ybian mongoid branch is incompatible with my rails gem. any help would be appreciated

@dks17
Copy link
Contributor Author

dks17 commented Feb 28, 2019

@luzioluna hello.
It looks like you use some old fork of the repository.

Please, see How do I use the gem with Mongoid? #1263

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants