I have this route setup in a Rails 3.1.12 app:
get '/compte/activer/:username/:token' => 'create_user#activate', :as => :create_user_activate
Here's the request spec:
describe "#activate with valid token" do
it "activates the account" do
user = User.create_basic("conradk", "email#email.com", "Conrad K.", "password", "password", "Hello world!")
visit create_user_activate_path(:username => user.username, :token => user.activation_token)
page.should have_content(I18n.t('activerecord.success.messages.account_activated'))
end
end
Here's the controller:
class CreateUserController < ApplicationController
def activate username, token
end
end
When I run the specs, I get this error:
Failure/Error: visit create_user_activate_path(:username => user.username, :token => user.activation_token)
ArgumentError:
wrong number of arguments (0 for 2)
What did I do wrong?
Try this
class CreateUserController < ApplicationController
def activate
end
end
Your controller method should be defined like below:
class CreateUserController < ApplicationController
def activate
#params will have your username and token
user_name = params[:username]
token = params[:token]
end
end
Related
I have created an app with a facebook login using :
gem "koala"
gem 'omniauth'
gem 'omniauth-facebook', '1.4.0'
gem 'fb_graph2'
I want to get access to user friends who use the app too.
But I don't know how to do that and how to have the 'access token' because I don't understand what is the access token ...
Right now, here is the code that I have.
models/ user.rb
class User
include Mongoid::Document
include Mongoid::Timestamps
field :provider, type: String
field :uid, type: String
field :name, type: String
field :picture, type: String
field :auth_token, type: String
has_many :parties
has_many :invitations, :class_name => 'Invite', :foreign_key => 'recipient_id'
has_many :sent_invites, :class_name => 'Invite', :foreign_key => 'sender_id'
has_many :friends
# TODO: Ajouter les amitiƩs
# TODO: Ajouter les recherches d'amis (livereload)
def self.create_with_omniauth(auth)
create! do |user|
user.provider = auth['provider']
user.uid = auth['uid']
user.auth_token = auth['credentials']['token']
if auth['info']
user.name = auth['info']['name'] || ""
user.picture = auth['info']['image'] || ""
end
end
end
def large_image
return "http://graph.facebook.com/#{self.uid}/picture?type=large"
end
def normal_image
return "http://graph.facebook.com/#{self.uid}/picture?type=normal"
end
end
controllers / sessions_controller.rb
class SessionsController < ApplicationController
def create
auth = request.env["omniauth.auth"]
user = User.where(:provider => auth['provider'],
:uid => auth['uid']).first || User.create_with_omniauth(auth)
session[:user_id] = user.id
redirect_to root_url, :notice => "Signed in!"
end
def destroy
reset_session
redirect_to root_url, :notice => 'Signed out!'
end
def new
redirect_to '/auth/facebook'
end
def failure
redirect_to root_url, :alert => "Authentication error: #{params[:message].humanize}"
end
end
initializer / omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
provider :facebook, '<public_key>', '<private_key>'
end
And my friends controller :
class FriendsController < ApplicationController
def index
if params[:code]
session[:access_token] = session[:oauth].get_access_token(params[:code])
end
# auth established, now do a graph call:
#api = Koala::Facebook::API.new(session[:access_token])
#user_profile = #api.get_object("me")
#friends = #api.get_connections(#user_profile['id'], "friends")
end
end
It don't work, I have this error :
type: OAuthException, code: 2500, message: An active access token must be used to query information about the current user., x-fb-trace-id: BeOG6OGemO9 [HTTP 400]
I imagine that it's because my code is not correct, so I hope someone should help me improve my code and get access to user friends !
The token that you saved in users.auth_token field is what you need. So when initializing a new Koala instance pass users auth_token - #api = Koala::Facebook::API.new(current_user.auth_token) and then try to get friends list, like you do currently.
Regarding what access token is you can read about it here (in Facebook context) https://developers.facebook.com/docs/facebook-login/access-tokens
I am implementing Devise and Cancan for user authentication and permissions. Everything works great so far except I am not able to redirect users to the login page when they are not allowed to access a specific feature.
My test is:
feature 'A signed in user' do
before(:each) do
user = FactoryGirl.create(:user)
visit "/login"
fill_in "user_email", :with => user.email
fill_in "user_password", :with => "ilovebananas"
click_button "Sign in"
end
scenario 'should not have access to admin dashboard' do
visit '/admin'
page.should have_content 'Log in'
end
end
And I get the following failure:
Failures:
1) A signed in user should not have access to admin dashboard
Failure/Error: visit '/admin'
CanCan::AccessDenied:
You are not authorized to access this page.
To be clear, all my permission management works as expected so far, except the redirection to login page.
Here is how things are set up:
ApplicationController:
check_authorization :unless => :devise_controller? # Cancan
rescue_from CanCan::AccessDenied do |exception|
redirect_to login_path, alert: exception.message
end
UsersController
class UsersController < ApplicationController
load_and_authorize_resource # Cancan
def queue
...
end
...
end
AdminsController
class AdminController < ActionController::Base
authorize_resource :class => false # Cancan, used because AdminController doesn't have an associated model
...
end
ability.rb
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user, not logged in
can :queue, User
if user.has_permission? :super_admin
can :manage, :all
elsif user.has_permission? :network_admin
end
end
end
What am I missing?
you must pass class name as string. try quoting it. or try
rescue_from CanCan::AccessDenied , :with => :login_page
private
def login_page
redirect_to login_path
end
You should to add "controller.authorize_resource" to admin/register.if abilities without conditions.
controller.authorize_resource
Example: can :manage, :all
If conditions are,
controller do
load_and_authorize_resource :except => [:update,:index, :show, :edit]
def scoped_collection
end_of_association_chain.accessible_by(current_ability)
end
end
Example: can :manage, Master::Country, :organization_branch_id => each_branch.id
i hope it help you
My Admins Controller was not < ApplicationController, so it did not load the ApplicationController rescue_from method.
Making the change solved my issue.
Here is my test:
require 'test_helper'
class SessionsControllerTest < ActionController::TestCase
setup do
#request.env["devise.mapping"] = Devise.mappings[:user]
#u = Factory :user, :password => :mypass, :password_confirmation => :mypass
end
test 'log in page loads' do
get :new
assert :success
end
test 'log in with devise password' do
post :create, :user => {:email => #u.email, :password => 'mypass'}
ap session
end
end
gives this output, indicating that the sign in failed:
Loaded suite test/functional/sessions_controller_test
Started
.{
"action" => "create",
"locale" => "en",
"controller" => "sessions",
"user" => {
"password" => "mypass",
"email" => "458286#email.com"
}
}
{
"flash" => {
:alert => "Invalid email or password."
}
}
.
Finished in 0.49123 seconds.
This is my session controller:
#this is an extension of the devise controller for sessions
class SessionsController < Devise::SessionsController
before_filter :set_title_h1, :only => :new
before_filter :debug, :only => :create
before_filter :old_password_system_fix, :only => :create
private
def set_title_h1
#layout[:show_h1] = false
title 'Sign in Or Register'
end
def after_sign_in_path_for(resource)
#override Devise default sign in path /opt/local/lib/ruby/gems/1.8/gems/devise-1.1.2/lib/devise/controllers/helpers.rb
#edit_user_registration_path
'/en/main/index' #forces locale to be defined
end
def after_sign_out_path_for(resource)
#override Devise default sign out path /opt/local/lib/ruby/gems/1.8/gems/devise-1.1.2/lib/devise/controllers/helpers.rb
main_index_path
end
def old_password_system_fix
#purpose is to bring old users into the new system by setting their old password to the new format
require 'digest/md5'
email = params[:user][:email]
pw = params[:user][:password]
#get user
u = User.find_by_email email
return if u.nil?
#if they don't have a devise-style pw, authenticate with old
if u.encrypted_password.blank? && u.old_password.present?
#if [params pw] == md5 [old pw] then create devise-style pw & salt, store it, and let them through to devise auth action
if u.old_password == Digest::MD5.hexdigest(pw)
set_devise_style_pw(u, pw)
#if no match, give "invalid email or pw" message.
else
#flash[:notice] = "Sign in failed."
flash[:notice] = t 'devise.failure.invalid'
#render :new
redirect_to new_user_session_path
end
end
end
def debug
ap params
end
end
What am I missing and how can I test a new session via a functional test?
Turns out you have to use an integration test, not a functional test. Don't ask me why...
I'm working through Hartl's book and I'm up to chapter 8. I've written some tests that I believe should be passing. I've quadruple checked my code against what's in the book, and double checked it against what's in the book's github repo, but I'm stumped. I'm getting the following errors from RSpec:
Failures:
1) UsersController POST 'create' should redirect to the user "show" page
Failure/Error: response.should redirect_to(user_path(assigns(:user)))
ActionController::RoutingError:
No route matches {:action=>"show", :controller=>"users", :id=>#<User id: nil, name: nil, email: nil, created_at: nil, updated_at: nil, encrypted_password: nil, salt: nil>}
# ./spec/controllers/users_controller_spec.rb:93:in `block (3 levels) in <top (required)>'
2) UsersController POST 'create' should have a welcome message
Failure/Error: flash[:success].should =~ /welcome to the sample app/i
expected: /welcome to the sample app/i
got: nil (using =~)
# ./spec/controllers/users_controller_spec.rb:98:in `block (3 levels) in <top (required)>'
Finished in 0.83875 seconds
46 examples, 2 failures
Like I said, I've checked the code again and again. Restarted spork, restarted rails server, ran without spork. I've checked it against the code in the book and in the github repo. I've even copy/pasted the spec and controller code in the github repo, but all to no avail.
I'm stumped. It's late and I need to crash. :)
Hopefully one of you guys can see something I'm not. Here's what I've got so far...
users_controller_spec.rb
require 'spec_helper'
describe UsersController do
render_views
# ...
describe "POST 'create'" do
# ...
describe 'success' do
before(:each) do
#attr = { :name => 'New User', :email => 'some-email#gmail.com', :password => 'foobar', :password_confirmation => 'foobar' }
end
it 'should create a new user' do
lambda do
post :create, :user => #attr
end.should change(User, :count).by(1)
end
end
it 'should redirect to the user "show" page' do
post :create, :user => #attr
response.should redirect_to(user_path(assigns(:user)))
end
it 'should have a welcome message' do
post :create, :user => #attr
flash[:success].should =~ /welcome to the sample app/i
end
end
end
users_controller.rb
class UsersController < ApplicationController
def new
#user = User.new
#title = 'Sign up'
end
def show
#user = User.find params[:id]
#title = #user.name
end
def create
#user = User.new(params[:user])
if #user.save
flash[:success] = 'Welcome to the Sample App!'
redirect_to #user
else
#title = 'Sign up'
render 'new'
end
end
end
user.rb
class User < ActiveRecord::Base
# Virtual properties (don't exist in db)
attr_accessor :password
# Accessible properties
attr_accessible :name, :email, :password, :password_confirmation
email_regex = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :name, :presence => true,
:length => { :maximum => 50 }
validates :email, :presence => true,
:format => { :with => email_regex },
:uniqueness => { :case_sensitive => false }
validates :password, :presence => true,
:confirmation => true,
:length => { :within => 6..40 }
before_save :encrypt_password
# Return true if the user's password matches the submitted password
def has_password?(submitted_password)
# Compare encrypted_password with the encrypted version of submitted_password
encrypted_password == encrypt(submitted_password)
end
# Static/Class methods
def self.authenticate(email, submitted_password)
user = find_by_email email
return nil if user.nil?
return user if user.has_password? submitted_password
end
# Private functionality.
# Anything after the 'private' pragma will be inaccessable from outside the class
private
def encrypt_password
self.salt = make_salt if new_record? # Using ActiveRecord goodness to make sure this only gets created once.
self.encrypted_password = encrypt(password)
end
def encrypt(string)
secure_hash("#{salt}--#{string}")
end
def make_salt
secure_hash("#{Time.now.utc}--#{password}")
end
def secure_hash(string)
Digest::SHA2.hexdigest(string)
end
end
routes.rb
SampleApp::Application.routes.draw do
#get '/users/new'
resources :users
match '/signup' => 'users#new'
match '/about' => 'pages#about'
match '/contact' => 'pages#contact'
match '/help' => 'pages#help'
root :to => 'pages#home'
end
Thanks in advance. If you guys really want to dig through or if I've missed something in my post, here's my code.
I'm very new to rails, and absolutely love it so far. Any help will be greatly appreciated.
Look closely at your users_controller_spec "success" spec: when will it create #attr? Before each test, or just before the "should create a new user" test? You use it in all the "POST 'create'" tests...
Once you make that non-spec-specific your tests will pass.
(By the way, having the code up in git is handy, but only if the code you're posting is actually checked in, otherwise... not as much ;)
your
it "should redirect to the user show page"
and
it "should have a welcome message"
is outside of the
describe "success" do
loop
I want to test my User Session Controller testing that a user session is first built then saved. My UserSession class looks like this:
class UserSession < Authlogic::Session::Base
end
The create method of my UserSessionsController looks like this:
def create
#user_session = UserSession.new(params[:user_session])
if #user_session.save
flash[:notice] = "Successfully logged in."
redirect_back_or_default administer_home_page_url
else
render :new
end
end
and my controller spec looks like this:
describe UserSessionsController do
it "should build a new user session" do
UserSession.stub!(:new).with(:email, :password)
UserSession.should_receive(:new).with(:email => "some_email#gmail.com", :password => "foobar")
post :create, :user_session => { :email => "some_email#gmail.com", :password => "foobar" }
end
end
I stub out the new method but I still get the following error when I run the test:
Spec::Mocks::MockExpectationError in 'UserSessionsController should build a new user session'
<UserSession (class)> received :new with unexpected arguments
expected: ({:password=>"foobar", :email=>"some_email#gmail.com"})
got: ({:priority_record=>nil}, nil)
It's although the new method is being called on UserSession before my controller code is getting called. Calling activate_authlogic makes no difference.
This worked for me when I was getting extra :new messages on UserSession with ({:priority_record=>nil}, nil)
UserSession.should_receive(:new).at_least(1).times.with({ :email => "some_email#gmail.com", :password => "foobar" })