why devise is generating this format of confirmation URL? - ruby-on-rails-4

devise keep on generating this format of confirmation URL
http://something.com/users/confirmation/divyanshu-rawat?confirmation_token=CV3zV1wAWsb3RokHHEKN
I don't know why it is not generating something like this.
http://something.com/users/confirmation?confirmation_token=CV3zV1wAWsb3RokHHEKN
This is how my confirmation_instructions.html.haml looks like.
%p Welcome #{#resource.first_name}!
%p You can confirm your account email through the link below:
%p= link_to 'Confirm my account', user_confirmation_url(#resource, :confirmation_token => #resource.confirmation_token)

In Devise gem, routes for confirmation are created as below,
# # Confirmation routes for Confirmable, if User model has :confirmable configured
# new_user_confirmation GET /users/confirmation/new(.:format) {controller:"devise/confirmations", action:"new"}
# user_confirmation GET /users/confirmation(.:format) {controller:"devise/confirmations", action:"show"}
# POST /users/confirmation(.:format) {controller:"devise/confirmations", action:"create"}
So if you want to create url like,
http://something.com/users/confirmation?confirmation_token=CV3zV1wAWsb3RokHHEKN
Use
user_confirmation_url(confirmation_token: #resource.confirmation_token)`
Instead of
user_confirmation_url(#resource, confirmation_token: #resource.confirmation_token)`
Also check routes.rb
If you want to pass user_name or name db attribute of #resource in confirmation url (as you asked by passing 'divyanshu-rawat' in your url), You can create own custom route which will point to same controller & action as below,
# config/routes.rb
devise_for :users
as :user do
get '/users/confirmation/:name' => "devise/confirmations#show", as: 'user_confirm'
end
And if in your case, #resource.user_name = 'divyanshu-rawat', update confirmation_instructions.html.haml as below,
%p Welcome #{#resource.first_name}!
%p You can confirm your account email through the link below:
%p= link_to 'Confirm my account', user_confirm_url(name: #resource.user_name, confirmation_token: #resource.confirmation_token)
Which will produce url like,
http://something.com/users/confirmation/divyanshu-rawat?confirmation_token=CV3zV1wAWsb3RokHHEKN

Related

Ror: cancancan hide index page on specific users type

I got an issue with cancancan gem and inherited tables on Ruby on rails.
My account model has multiple inherited models Teacher < Account, Director < Account which have different abilities.
Here are my rules: "in ability.rb"
if account.director?
can :manage, Account, profile: [ :teacher, :director ]
end
if account.teacher?
can :manage, Account, profile: [ :teacher ]
end
My route file looks like:
resources :directors, controller: :accounts, profile: :director
resources :teachers, controller: :accounts, profile: :teacher
When I'm logged in as a teacher and I go to /directors (index page), Cancan should raise a Unauthorized::AccessDenied message instead of displaying the directors page.
I probably missed something in the doc. Is someone could enlighten me?
Thanks
Accouding to this:
can :read, Project, :active => true, :user_id => user.id
Something like that inside Ability class should match Rails STI sub-class:
can :manage, Account, type: 'Teacher'

Specific Rails routes password protected

I want a password site wide just like Rack's Basic AUTH
/config.ru
use Rack::Auth::Basic, "Restricted Area" do |username, password|
[username, password] == ['admin', 'admin']
end
run Rails.application
But I don't want it to block paths /API and /mailgun/incoming_email with password access. Can I accomplish this in Rack? Or should I implement a scope within the routes.rb that almost all resources are behind a Rack (enter once) password?
For the record I am using Devise within the site... that's separate. I need a sitewide password before it.
[Revised Question]
Specific Routes
I would like to password protect only the root path / and /visitors with the Rack like password. I've seen something used in a Rails routes.rb file before with a lambda condition requiring the password. I'm not having luck finding that information at the moment.
My website already redirects unauthenticated Devise users to /users/sign_in. So I only needed to password protect /, /users/sign_in, and /users/sign_up. This is how I did it.
config.ru
class RootSiteAuth < Rack::Auth::Basic
def call(env)
request = Rack::Request.new(env)
if ['/', '/users/sign_in', '/users/sign_up'].include? request.path
super
else
#app.call(env)
end
end
end
use RootSiteAuth, "Restricted Area" do |username, password|
[username, password] == ['admin', 'admin']
end
run Rails.application
And it works. Every controller that has before_filter :authenticate_user! redirects to the Rack password page. After authentication we're good to go. Anything without the filter permits outside access as planned. ^_^

Rails 4 Devise 3 multiple New Registration pages

Using Rails 4 and Devise 3, I would like to have different registration pages based on the URL my user is given.
As an example, each of the following should be directed to a different view that acts as devise registration.
www.mydomain.com <-- current root to registrations#new
www.mydomain.com/user_type_1
www.mydomain.com/user_type_2
www.mydomain.com/user_type_3
How would I do this? I can copy app/views/devise/registrations/new.html.erb to capture the form but how would I make the routing work?
My routes are currently set up as such (I close each session so the user can sign up a friend, but that is not relevant to this question)
devise_scope :user do
authenticated :user do
root :to => 'devise/sessions#destroy', as: :authenticated_root
end
unauthenticated :user do
root :to => 'devise/registrations#new', as: :unauthenticated_root
end
end
So you want three different url paths that point to three different views, but you want the forms to all send their info to the same REST endpoint in the same controller (users#create)? That sounds simple. You have GET requests to get the html/erb files for each registration page (welcome#index, welcome#cool, welcome#coolest), and routes for each to send the GET request to the right controller action.
Then you set up the forms to all send their info to POST to users#new, and one route from there.
Does that make sense?

How to re-use the root path for the landing page and as the default path for logged in users?

I want foo.com/ to show the landing page when the user isn't logged in, and foo.com/ to show the dashboard of the user when the user is logged in, just like in Facebook.
I was going to do it the following way:
def index
if user_signed_in?
#posts = current_user.posts
render 'home/dashboard'
else
render 'home/landing'
end
end
But then quickly realized that I'd need to use before_filter :authenticate_user! in order to get current_user, so Devise will require to sign in.
Maybe there's a way to do this more cleanly using routing. Please advice.
authenticated :user do
root to: "users#index", as: :authenticated_root
end
unauthenticated do
root to: "main#index"
end
https://github.com/plataformatec/devise/issues/2393#issuecomment-17298414

Access token from devise+omniauth-facebook authentication for using in fb-graph

I used devise and omniauth-facebook in my Rails 3 app for Facebook authentication, based on this tutorial: Adding Facebook auth to Rails 3.1 app, and it's working great!
But now I want to have full Facebook integration in my app, with which I can access the user's photos, friends, etc., and for that I am thinking of using fb_graph. fb_graph requires a token, and I wanted to know how to edit my user model to save the token and use it in fb_graph. Any help regarding this matter will be highly appreciated.
This is how my User model looks like right now:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :omniauthable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me
has_many :photos
has_many :scrapbooks
def self.find_for_facebook_oauth(access_token, signed_in_resource=nil)
data = access_token.extra.raw_info
if user = User.where(:email => data.email).first
user
else # Create a user with a stub password.
User.create!(:email => data.email, :password => Devise.friendly_token[0,20])
end
end
def self.new_with_session(params, session)
super.tap do |user|
if data = session["devise.facebook_data"] && session["devise.facebook_data"]["extra"]["raw_info"]
user.email = data["email"]
end
end
end
end
You can do this:
User.create!(:email => data.email, :password => Devise.friendly_token[0,20], :authentication_token => access_token.credentials.token)
You will also need to add :authentication_token or whatever you named it to the attr_accessible
I was looking for the same thing. I tried to implement James Robey{s answer and felt into the same error: OAuthException :: An active access token must be used to query information about the current user. Then I realized authentication_token was not being saved this way. After looking a while I found in FbGraph + OmniAuth + Facebook Graph API on Rails application a way to do it with session variables, by implementing the token saving during omniauth callback and then using it when calling fb_graph. So it might be something like this:
omniauth callback (app/controllers/users/omniauth_callbacks_controller.rb)
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def facebook
#user = User.find_for_facebook_oauth(request.env["omniauth.auth"], current_user)
if #user.persisted?
flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => "Facebook"
# this part is where token is stored
auth = request.env['omniauth.auth']
token = auth['credentials']['token']
session[:fb_access_token] = token
#
sign_in_and_redirect #user, :event => :authentication
else
session["devise.facebook_data"] = request.env["omniauth.auth"]
redirect_to new_user_registration_url
end
end
end
Then when calling fb_graph
#fb_user = FbGraph::User.new('me', access_token: session[:fb_access_token]).fetch
I don't know if it's the best way, but works so far.
ill refer you to https://github.com/nov/fb_graph/wiki/Page-Management
where nov states: You need the page’s access token to manage your page.
Your (an user’s) access token doesn’t work here.
follow his link to the facebook developers site for more info
you'll need the users access_token and i do this through omniauth-facbook https://github.com/mkdynamic/omniauth-facebook
which you retrieve the use by first inputting this initializer into your app
Rails.application.config.middleware.use OmniAuth::Builder do
provider :facebook, ENV['FACEBOOK_KEY'], ENV['FACEBOOK_SECRET'],
:scope => 'email,user_birthday,read_stream', :display => 'popup'
end
(note you can change the permissions on the scope here check facebook developers login permissions for more
there are some inner workings to omniauth and omniauth-facebook but the jist is
when you get the callback from facebook you have a rack omniauth hash from the request
omniauth = request.env["omniauth.auth"]
from that has you can access the users access token like this
facebook_user_token = omniauth['credentials']['token']
you can then feed that token into your fb_graph page call
page = FbGraph::Page.new('FbGraph').fetch(
:access_token => facebook_user_token,
:fields => :access_token
)
then you will simply be able to create a note by calling your desired method without a reference to the access token
note = page.note!(:subject => #title, :message => #message, :link => #url)