I have a Rails 4.1.8 app which was developed by a third party; it already uses Devise with a User model. I want to use Alchemy just to manage a few mostly-static pages like "about us" etc.
So I followed the directions for installing Alchemy CMS 3.1.0-rc1 into the existing app, and set Alchemy.user_class_name in the initializer. I mounted Alchemy under the /p/ path for now to avoid collisions with my existing paths.
Everything seems to be working fine, except when I try to view an Alchemy page while logged out, my application.html.erb throws the following error:
undefined method `new_user_session_path' for
#<#<Class:0x007fe4c6833ee0>:0x007fe4cb5b8940>
This happens because my app uses new_user_session_path in application.html.erb, to show a Login link for the guest user. In the regular app, it works fine, and also works fine when I view an Alchemy page when logged in.
I'm not familiar enough with Devise and Alchemy to figure out where the problem exists. I'm guessing it's one of two things:
when there is no logged-in User, the app is creating a "guest" User (for access to other methods on the User model), and Devise doesn't know about this user so it doesn't create the new_user_session_path helper.
I have some problem in my routing, and because Alchemy is a mountable engine, there is maybe some logic in my application controller that isn't getting called.
I'd prefer to not post my entire routes.rb or application controller, but here's the relevant devise section from the former.
devise_for :users, :path => "auth", :path_names => { :sign_in => 'login', :sign_out => 'logout',
:password => 'secret', :confirmation => 'verification', :registration => 'register' },
:controllers => {
:registrations => "authentication",
:passwords => "passwords",
:omniauth_callbacks => "omniauth_callbacks",
:sessions => "sessions"
}
devise_scope :user do
# several get/post definitions here to change various urls
end
I don't think it's #2, because even if I define a devise_scope for a custom path like:
devise_scope :user do
get 'login', to: 'devise/sessions#new'
end
I get the same problem: it works in the main app, and when users are logged in, but not on Alchemy pages with guest User.
Common rails routing proxy problem. Since the Alchemy views don't know your main apps routes, you need to use the 'main_app' routing proxy object.
So calling 'main_app.new_user_session_path' should fix your problem.
Read more about routes in engines in this Rails guide: http://guides.rubyonrails.org/engines.html#routes
Related
I have an existing Rails 3 site. This site uses Devise to log in.
Now I need to add a subsite with a separate login. Let's say that it is at mysite.com/special. Everybody that go to /special need to sign in with a different set of credentials than the main site. These credentials are not valid for the main site but they must, in parallel, be able to log into the main site and stay logged in both.
To complicate the picture a bit, 'special' users are able to impersonate a subset of regular users. If they do impersonate, sign out of the impersonation and so forth, they must remain logged into the special site until they explicitly sign out there.
My initial idea was to use a separate session cookie for this entire subsite but I don't know how to do that. I tried setting something like this up but it is almost guesswork at this point.
scope '/special' do
devise_for :special_users, :controllers => { :sessions => "special/sessions" }, :skip => "registrations", :module => "special_users"
unauthenticated do
as :special_user do
root :to => 'special/sessions#new'
end
end
end
Unfortunately, I'm a bit new to Rails and this seems to be rather complicated. Is it even possible with Devise and if so, do anyone have any pointers as to how to go about it?
As it turns out, this is what scopes are for. Everything makes much more sense when you know what they call it ;) Anyway, Qumaras' comment above was actually on the right track), and the tutorials and wikis are generally good sources of information. One possible approach:
devise_for :spuser, :controllers => { :sessions => "sp/spusers/sessions"}
as :spuser do # as = equiv. to devise_scope
# add spuser specific items here, such as:
unauthenticated :spuser do
root :to => 'sp/spusers/sessions#new'
end
end
Then if you want to sign in another tab as a regular user, you could do this in a controller.
def impersonate
#user = User.first
sign_in(:user, #user)
redirect_to '/main'
end
And wire the impersonate action up in routes.rb
resources :regularcustomers do
member do
get :impersonate
end
end
and then you can call it in a view:
<%= link_to #customer.name, impersonate_regularcustomers_path(#customer), :target => 'impersonationtab' %>
I am using Devise with multiple models (three to be exact) and each role has some different interactions. For example, after the user model signs up I override a devise method to redirect them to a specific welcome path, where with the employer model I take them to a credit card form, etc.
As a result, I need to namespace everything. Namespacing the views and controllers are not tough, however, I was wondering if there is a way to namespace the controllers without having to specify EVERY devise controller.
For example, is there a way to basically do this:
devise_for :employers, :controller => "employers"
Instead of having to do this:
devise_for :employers, :controllers => {
:registrations => "employers/registrations",
:sessions => "employers/sessions",
:confirmations => "employers/confirmations",
:passwords => "employers/passwords",
:unlocks => "employers/unlocks",
:mailer => "employers/mailer"
}
Might seem trivial but when you have three models to maintain it could get a bit much.
Take a look at the following answer from Devise within namespace. Simply namespacing in the routes.rb will not produce the desired results. You'll have to generate controllers for each action you want. For sessions for example, You will have to create a new controller called Sessions in the controller Employer namespace:
bundle exec rails g controller employer/sessions
then subclass the new session controller from devise session controller to bring in all the Devise methods required to properly handle sessions:
class Employer::SessionsController < Devise::SessionsController
end
and change your 'devise_for :employers, :controller => "employers"' line in config/routes.rb to the following:
devise_for :employers, :controllers => { :sessions => "employer/sessions" }
Finally, as an optional step, you can generate views to app/views/employer/sessions directory. You can do this my setting "config.scoped_views = true" inside config/initializers/devise.rb and running the following to generate views scoped to employers:
rails generate devise:views users
This should generate templates at app/views/employer/sessions/new. Otherwise, the new session controller will just use the default view templates.
Hope this helps!
Will it work by just saying: devise_for :employers, :path => "employers" ?
I am currently using Rails 3.2.5 with the latest devise gem.
Currently users can access their profile page at...
example.com/users/john-doe
I want to remove the users portion of the url, so the url would be example.com/john-doe. Is this possible with devise?
Right now in my routes file I have the following...
devise_for :users, :controllers => {:omniauth_callbacks => 'omniauth_callbacks'}
Just add a route for it. You will probably want it to be the last one in the routes file.
Something like:
match '/:user' => "users#show", :as => :user_profile
I am creating a rails app. And i have login in such a way that, users are directed or redirect to /login for signing in. And when users/sign_in is passed the it embeds the sign in form into the application layout which i don't want users to see. Is there a way i can redirect users/sign_in to /login or restrict access to it ?
thanks
The following will replace the routes:
devise_for :model_name, :path => '',
:path_names => {:sign_in => 'login', :sign_out => 'logout'}
It will replace the users/sign_in and users/sign_out routes with login/logout, and the redirects will take them to those routes accordingly as well.
try this. It should works. ;)
config/routes.rb
# change :devise_model to :user, or :admin or any name of your devise model
devise_scope :devise_model do
get '/login' => "devise/sessions#new"
end
and you can use this in view like this.
link_to 'Login', login_url
PS. if you have override devise controller. You should tell the router first, and change devise controller to your override controller name.
go to this link and see Configuring controllers content.
I have built an application which allows a user to authenticate against Active Directory using omniauth-ldap. If this is a new user, the successful authentication creates a user for them based on information returned from AD. If the user already exists, it just logs them in. Users do not register for the application, they just log in with AD credentials. And I never want the user to log in with database credentials.
I can't figure out how to get rid of or change around some of the routes. For example if a user visits /sign_in they get the database authentication. And if the user visits sign_up they are taken to a page to register for the site. I would like for users that visit /sign_in to be taken to the LDAP login which is /users/auth/ldap. I think I need to make a custom route, but I'm not sure which controller I need to direct the user to. And I want to make the sign_up page go away entirely.
Right now I have a link that allows users to log in using ldap, and the path for that is user_omniauth_authorize_path(:ldap). I'm just not sure how to translate that into something that my config/routes.rb file understands. This is what I have in routes right now.
devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" } do
get 'sign_in', :to => 'devise/sessions#new', :as => :new_user_session
get 'sign_out', :to => 'devise/sessions#destroy', :as => :destroy_user_session
end
When I run rake routes I do not see any route for user_omniauth_authorize_path which I presume is because that route is being generated by devise. So I think I need to have my routes point to a devise controller, but I can't seem to find the right path.
Try to add
:skip => [:sessions, :registrations] to your routes.rb
Something like this:
devise_for :users, :skip => [:sessions, :registrations]
This How To article might be helpful, and also here is one more link to go through.