Restrict access to page using devise - ruby-on-rails

I have installed devise and would like to restrict access to certain pages depending on whether the user has authenticated.
My first approach was to open each view, and add:
<% if mpuser_signed_in? %>
#rest of code
<%end>
(My model is called mpusers)
But I thought there maybe is a more elegant solution?
Dario

Set before_filter :authenticate_user! in the controller for the actions that require an authenticated user. In this example, we need the user to be authenticated for creation, edit and destroy actions.
class YourController < ApplicationController
before_filter :authenticate_user!, only: [:new, :edit, :update, :destroy]

Related

How to prevent unauthorized users from registering in Devise?

I want to allow authorized users to create (and destroy) user accounts. I have gotten this part working according to hints I found in this and other questions.
But I also want to prevent unauthorized users from creating and destroying accounts.
I have my own registration_controller:
class RegistrationsController < Devise::RegistrationsController
skip_before_action :require_no_authentication, only: [:new, :create, :destroy]
skip_before_action :authenticate_scope!, only: [:destroy]
before_action :authenticate_user!, only: [:new, :create, :destroy] # why doesn't this work?
def new
super
end
def sign_up(resource_name, resource)
# don't sign in as the new user
end
def destroy
User.find(params[:id]).destroy
redirect_to(users_path)
end
end
And have directed my routes to use it in routes.rb:
# Standard devise setup but allow registration when logged in
# https://stackoverflow.com/a/31946248/1404185
devise_for :users, controllers: {:registrations => "registrations"}
# Work around already-existing session controller
# https://stackoverflow.com/a/21024350/1404185
devise_scope :user do
post '/sessions/user', to: 'devise/sessions#create', via: :post
delete '/users/:id', to: 'registrations#destroy', via: :delete
end
# Show and index for users
# https://stackoverflow.com/a/32056094/1404185
resources :users, :only => [:show,:index]
For some reason before_action :authenticate_user! does not work... unauthenticated users can still invoke these actions. I've also tried prepend_before_action :authenticate_user!, and I've tried putting the filters in different orders-- invoking the before_action first in my controller.
I've just upgraded my app to rails 6.0.3.5 and added devise 4.7.1.
Why do I want this unusual setup? This is a hobby project and only my girlfriend and I are users. We don't want just anybody on the internet to sign up. But we occasionally may want to give another person access, who will be sitting next to us (pandemic permitting) when creating their account.
I do have a workaround for now: Since the site will have an obfuscated URL and since it is an extremely low value target (I can't imagine anyone would be interested in our home inventory) I simply don't provide a link to the signup page unless someone is logged in. This opens the possibility that a knowledgeable hacker could craft a request manually, but the risk is very very low.
But I still like to do things the "right" way, so I am asking this question. I have looked at devise_invitable but that seems way too complex for my needs.
UPDATE: One experiment I tried was instead of instead of inheriting from Devise::RegistrationsController and overriding methods, I just copied it to my registrations_controller and edited it. Then I deleted the :require_no_authenticaton and :authenticate_scope! prepend_before_actions and replaced them with prepend_before_action :authenticate_user!
This should eliminate doubt about whether the before_actions were being processed in the wrong order and ensure that only :authenticate_user! was being called.
The experiment failed. Apparently :authenticate_user! always returns true at this point whether or not a user is really authenticated. Why?
Apparently this has been an issue with devise for a long time.
The workaround is to change the before_action to:
prepend_before_action -> {authenticate_user!(force:true)}, only: [:new, :create, :destroy]
as suggested in this issue comment.

devise: how to allow unauthenticated access to some pages?

I have implemented Rails with devise authentication. As part of the process I added a "global" before_action :authenticate_user! in the application_controller that requires that all pages must be authenticated.
# app/controllers/application_controllers.rb
class ApplicationController < ActionController::Base
before_action :authenticate_user!
end
How do I allow some controller#actions to be accessed without requiring the user to log in first.
This is useful when sending out mass emailings, and the email contains the link to a #show action which usually requires authentication.
Put skip_before_action :authenticate_user! inside your controller to allow all actions for that controller.
You can also use the only and except keywords in combination with it to only allow or forbid specific actions.
# skips authentication only for "index" and "show"
skip_before_action :authenticate_user! only: %i[index show]
# requires authentication only for "update" and "destroy"
skip_before_action :authenticate_user! except: %i[update destroy]
In the controller just mention the action that required log in:
before_action :authenticate_user!, :only => [:new, :create, :edit]
For example if you have the action 'send_mail' in the controller you can accessed without log in.

Exclude a controller from before_action

I am using the before_action filter to call authenticate which is a method that will redirect users back to their home page if they aren't authorized to be on the page requested.
I would like to exclude a page from this step, just for testing purposes.
What I have seen so far is that I can use except to exclude certain controller actions from being subject to the before_action filter so like:
before_action :authenticate, except: :demo_login
I can also exclude more than one action at a time like this:
before_action :authenticate, except [:demo_login, :demo_show]
How can I exclude all actions in a specific controller?
Use skip_before_action :authenticate in the relevant controller.
The format of this method is the same as before_action so if you want to skip calling :authenticate for a specific controller action, use:
skip_before_action :authenticate, only: [:show, :index]
The except: keyword can also be used.

Devise rubygem - How do you filter actions for authenticated/non-authenticated users?

I am new to Rails and I need to create a simple Rails project with these conditions:
there must be page with some articles (title + body)
anyone can read those articles
only authenticated users can create/edit/delete those articles
I used scaffold to generate a controller for articles and the gem Devise to create the authentication system. But I dont know how to implement the necessary conditions.
Thanks for the reply.
If your user model is called user, then you would include the following in your controller:
before_filter :authenticate_user!
If it not called user, you would replace the word user in authenticate_user with whatever it is.
You would add this directly under your controller declaration, like so:
class ArticlesController < ApplicationController
before_filter :authenticate_user!
#rest of code
end
If you want to restrict only certain actions in the controller to logged in users, you can use except to exclude some actions. Here, index and show can be seen by anyone:
before_filter :authenticate_user!, :except => [:index, :show]
or only to include specific actions. Here, only authenticated users can do the listed actions:
before_filter :authenticate_user!,
:only => [:new, :edit, :create, :update, :delete]

Devise::RegistrationsController#show

I have a controller which inherits from Devise::RegistrationsController. I have added a show action to the controller. The problem is that even when the user is logged out they can access this action even though at the top of my controller I have:
before_filter :authenticate_user!, :except => [:new, :create]
Why isn't authenticate_user! disallowing access to my show action?
I tested this with one of my application. The filter authentication_person! (it's person in my case) works well for all other controllers but doesn't work for controller inherited from Devise::RegistrationsController. This may be an issue or limitation with devise. Needs to be added to issues discussion at github.
The other workaround can be to create a filter method should_be_logged_in? into the application controller and then checking for person_signed_in? helper and redirecting accordingly.
Might be an issue with auth scope..
try adding the following to you controller:
prepend_before_filter :authenticate_scope!, :only => [:edit, :update, :destroy, :show]

Resources