Rails 4 Devise 3 multiple New Registration pages - ruby-on-rails-4

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?

Related

Handling Django Registrations for Duplicate Entries

Question PART 1:
Project => App => forms.py
![User Creation Form using default Django Structure]
Project => App => urls.py
![URL Routes defined in urls.py of Django App]
Project => App => views.py
![User Authentication using default Django Structure]
Instead of using SQLite, I am using MongoDB Database and the entries are being stored in the auth_user table but I wanna get rid of duplicate entries (i.e. same username/email). If the user enters a same username/email, the page gives a DatabaseError Exception which I believe is handled by Django itself.
Question PART 2:
Project => settings.py
![Have included MessageTags into settings.py]
Also how to give specific redirect locations to messages in Django !? Once the user completes registration, the success message is displayed and he is redirected to the login page to access the dashboard and other features. But when the user logs in successfully, he is redirected to the dashboard but the Success Message is being displayed when he logs out (in the logout page).
Approach PART 1:
Can I, using try catch, handle the exception and allow the user to change the entered values to something unique and get his details saved into the database !?
Approach PART 2:
Sometimes the messages are appearing onto different pages than specified pages while using render/redirect for views.py functions(i.e routes). I tried redirecting each message to specific routes but I guess it overwrites to the last render/redirect route.
Regards,
Joe.

why devise is generating this format of confirmation URL?

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

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. ^_^

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

Omniauth - choose provider dynamically

Say I have a restful resource, UserSession
> POST /user_sessions.json
{
"user_session": {
"user": {
"some_key": "some_value",
"some_other_key": "some_other_value"
}
}
}
I'd like to choose the provider in the UserSessions#create based on the params supplied, rather than using the /auth/:provider OmniAuth normally uses. Is it possible to do this?
i am using a technique to set some omniauth options into the user-session.
i guess that this might work for your solution as well. you still have use the /auth/:provider routes though!
so i am basically linking all login urls to my auth_path
# routes.rb
get '/auth/login/:provider', to: 'sessions#auth', as: :auth
once i extract the data and put it into the session, i redirect the user to the right login path. in your case, it would need to extract the data from the params and then redirect:
# sessions_controller.rb
def auth
session[:omniauth_keys] = Usergroup.omniauth_keys(params[:provider], request)
redirect_to "/auth/#{params[:provider]}"
end