Rails: How to restrict actions to only certain users? - ruby-on-rails

I am currently doing a project for uploading pics. There are users, albums, and pics. I added a friendship model so that people can friend each other like a social network. However, I noticed that I put a lot of <% if current_user.friends.include?(#user) %> in the view to check if the user of the page I'm showing is a friend of the logged in client, and therefore allowing them to have certain privileges and forms and etc.. Is there a better way or place to do this than to pollute my views with if/else statements ? Also, I don't feel like my method is very secure since someone could always manually enter the url and mess with info that they're not supposed to.

You want an authorization framework such as CanCan.
In an ability file, you configure it that a user can, say, view something or edit some other thing, only if the user is a friend of the owner. Then in the view or the controller, you can just check that the user is authorized to do the appropriate action.
For specific details about setting up an ability based on details of the models (i.e. whether the owner is a friend of the current user), go to this documentation and look for "Hash of Conditions".

Consider using something like the mosaic-access gem, which allows you to white/blacklist controllers and specific actions for the currently logged in user.

Related

User settings and access control in rails

I have a webapp build with rails. Nothing complicated so far. Now I would like to restrict some areas for the user. I would like to implement two roles, User and Admin. Clearly the admin can do much more, like use DELETE in some of the controller methods. But there is even more. The user should be able to set some settings. For example he can set his profile to private, so only his friends can see his content. I am not sure how to build all of this with rails.
I did some research and found those two:
https://github.com/elabs/pundit
https://github.com/ledermann/rails-settings
Maybe a combination of those two would get me to the way I want the app to be?
If the app is going to be used used by real users i would go for the devise gem(https://github.com/plataformatec/devise) It allows user to create accounts, retrieve lost passwords etc. By default it allows users to edit their "profile"(rather their personal data), it should be easy to add a checkbox to toggle public/private profiles.
In conjunction with cancancan(https://github.com/CanCanCommunity/cancancan) you can assign roles to users, without having two different classes(Users and Admins for example).

create a profile page for user to view as if logged out

I'm making a Rails application using Devise. On the user profile page, it provides links for the user to update and delete certain elements of their profile. The links are obviously only visible to the signed-in user whose profile it is. The one disadvantage of this is that it doesn't allow the user to view their profile page from the perspective of a visitor, unless they want to log out and navigate to their profile. Some websites offer a "view your profile" link which allows users to view a page from the perspective of someone else. Is there a way to accomplish this with Rails and Devise?
Sure. You are able to create UsersController with show action. Where you will able to display the information you want.
If you want to manage users through CRUD interface there is a wiki page that may help you.
The url to user's profile can looks like /users/:id or you can define custom route such as /user/unique-username (the last example you can achieve using friendly_id gem)

Rails superuser resource context

The app I'm working on revolves around users belonging to organisations, and only being able to access resources in those organisations. That much is fine, and pretty straight forward.
The system also has users outside of any organisation, who are able to view anything within the system. When one of these users logs in, they get given a list of organisations that they would like to view. Selecting one should then give them a view of the system as if they were logged in as a standard user, but retain their superuser privileges.
Is there a nice way I can have the system know that a particular organisations has been selected and not have to have a nested resource for every path?
So for example, I want to login as superuser, and view organisationA. I want to be able to select the organisation, and simply to go
/subjects
rather than having to go to
/organisations/1/subjects
Is there any nice way of doing this?
If you don't pass the context through the url, you could store the selected organisation in the session. The problem with the session approach is, that you lose the ability to link to these pages directly since you rely on data stored in the session.

Two different logins and usernames from the same table

I need two kinds login if they refer to different controllers, example:
site.com/consumers
site.com/panel
site.com/consumers login is to make comments and site.com/panel is for the administrative part of advertisers and users.
I'm all consumers and advertisers in the same table users in the database.
Could anyone help me to make two logins do validation on the same table and after login, sends to different views and controllers?
In my route I was trying to use:
devise_for :panel, :class_name => "User"
But the layout of the login is the same, and would need to be different.
== UPDATE ==
I have three classes of people.
1) Consumer
2) advertiser
3) Administrator
The records are in the same table. But each record has a column "type" arrow you like (consumer, advertiser or administrator) So far I've managed to solve.
The problem is this:
When the user accesses via: www.site.com/comment
This user can login to make a comment on the site.
When the user accesses via: www.site.com/panel
This user can login to access the panel from him, he may be, (consumer, advertiser or administrator).
I would like to make two types of logins, one for / comment with the layout of the site and one for the / panel with the panel layout, but doing validation on the same table, in this case (Users).
Your question is a little hard to understand. It looks like your using devise. I am not sure if you are trying to use two different models, and have two different kinds of devise users, perhapse with different permissions? Or if you are trying to direct people to different pages depending on who they are after they login?
I would recommend you checkout after_sign_in_path in devise. You can define it in your application controller. If you are trying to send someone back to a different section of the site depending on where they signed in you could set a session variable and then use it in that function to decide where to send someone.
If you rewrite your question I will try and give a better answer.

Ruby on Rails private link sharing: Google Docs Style

What would be the best way to go about giving users the ability to share a private link that enables anyone who clicks it to view a certain page/document/item that have privacy restrictions in place?
In my case:
A User creates events which are limited to certain groups of relationships in the database (namely: friends, friends of friends, etc.) I have a :before_filter in the event controller that checks the eligibility of the current logged in user to make sure that that user has permission to see the event. If they don't they get booted to the root page with an error message.
However, I want a special scenario to exist where a user can create an event with those same privacy settings and IN ADDITION, be able to share a special link with his or her friends via e-mail, facebook, etc. Those users do NOT need an account (but will need to make one in order to sign up for the event). This is important because there is also a :before_filter in the application_controller which makes sure a user is logged in.
I'm thinking there is something I could do with routing here... Right now I just have the simple /events/72 setup. Should each event have two different links: a normal one, and a "special code" version which enables them to bypass those two :before_filter?
What are people's thoughts?
I agree with David Lyod's answer (separating this concern in a different controller).
But for creating the hash I strongly recommend you salting the hash with some secret phrase.
require "digest"
Digest::SHA512.hexdigest("#{created_at}#{user_id}.mysupersonicsecretSALT")
Doing this it is not possible, without the knowlegde of the secret phrase, to calculate the hashes and test them against your system until it hits an existing one.
If you're handling sensitive data you should not be lazy.
Cheers,
Lukas
I would have a separate controller that uses a hash value to reference the event.
Something simple like the created_at + user_id hashed to create a unique reference.
You could also simply skip the check on a certain action but I would much prefer the first solution .

Resources