pelle / oauth-plugin

Rails plugin for OAuth
http://stakeventures.com/articles/2009/07/21/consuming-oauth-intelligently-in-rails
MIT License
716 stars 216 forks source link

Mongoid::Errors::InvalidCollection in OauthConsumersController#index #91

Closed mgodwin closed 12 years ago

mgodwin commented 12 years ago

Using the latest version of mongoid and oauth-plugin on rails 3.1, and I'm getting this error

Mongoid::Errors::InvalidCollection in OauthConsumersController#index

Access to the collection for ConsumerToken is not allowed since it is an embedded document, please access a collection from the root document.

Looking at the OAuthConsumersController, it seems like this is the problem

@consumer_tokens=ConsumerToken.all :conditions=>{:user_id=>current_user.id}

Well that makes sense, since consumer_tokens is an embedded document inside of user. Changing it to:

@consumer_tokens=current_user.consumer_tokens

Fixes the problem but there are other instances of this throughout the controller files. Does mongoid work for anyone? Did these files change at some point? I can't imagine you were ever able to query against embedded documents in mongoid?

mgodwin commented 12 years ago

I was able to fix this by overriding the index and load_consumer methods in app/controllers/oauth_consumers_controller.rb

def index
  @consumer_tokens=current_user.consumer_tokens
  @services=OAUTH_CREDENTIALS.keys-@consumer_tokens.collect{|c| c.class.service_name}
end

protected

def load_consumer
   throw RecordNotFound unless OAUTH_CREDENTIALS.include?(consumer_key)
   deny_access! unless logged_in? || consumer_credentials[:allow_login]
   @consumer="#{consumer_key.to_s.camelcase}Token".constantize

   type_token = eval "current_user." + "#{consumer_key.to_s}_token"
   @token=type_token.first if logged_in?
 end

Also something that is extremely ambiguous for mongoid is that you need to do embeds_many in your user.rb (model file) for whatever type of token you're using... for example:

class User
  include Mongoid::Document
  # Include default devise modules. Others available are:
  # :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  embeds_many :consumer_tokens
  embeds_many :google_token
end
mgodwin commented 12 years ago

Going to make an addendum to this. You should use this instead for load_consumer:

def load_consumer
  throw RecordNotFound unless OAUTH_CREDENTIALS.include?(consumer_key)
  deny_access! unless logged_in? || consumer_credentials[:allow_login]
  @consumer="#{consumer_key.to_s.camelcase}Token".constantize
  @token=current_user.consumer_tokens.where(_type:"#{consumer_key.to_s.camelcase}Token").first if logged_in?
end
mgodwin commented 12 years ago

And a further addendum, you don't need the

embeds_many :google_token