ROR 3 conditions in routes.rb - ruby-on-rails-3

Is there a way to specify conditional statement inside routes.rb - I would like the root_path to depend on whether the user is signed in or not. perhaps there are other ways of accomplishing this?
Thanks!

Actually I think you can using advanced constraints it is documented here...
You would define a def matches?(request) to check if the user is signed in, and use two routes one when with a constraint of signed in and one when not.
Although I am not sure if the session is available when that custom constraint is executed.
Although I agree with SpyrosP it would be better to do it in the Controller.

No, you cannot do that. The routes do not rely on conditions that are based on model code. Anybody can call a route, so you cannot depend on that anyway.
Instead, just add a "before_filter :authenticate"(using sessions) on the controllers that you want to protect. If somebody tries to access your admin controller without being an admin, they will be redirected to login or anywhere you like.

I think the previous answers (suggesting a before_filter in the controller is more appropriate) are missing the OP's use case slightly. There are still advantages to doing it as a conditional route/advanced constraint. It doesn't replace having a before filter in the controller to prevent unauthorized direct access. But, for instance, having a redirect_to root_path route directly to e.g. a user's profile when he is signed in, or the front page when not, preserves flash messages that would otherwise be lost in a second redirect in the before filter. More elegant IMHO to use the advanced constraint approach (assuming of course that the session is in fact available when the custom contraint is tested). Not to mention, in this type of instance, why not save the extra redirect (since it involves a whole other HTTP(S) transaction)?
UPDATE:
If you're using Devise, this article describes an even better approach. Just implemented it myself and it works great, and it's clean.
Also, comments to explain down votes are always appreciated, not just for the author but for others who read the answer so they know why it might not be a reasonable response.

Related

In IdentityServer4, how do you securely store the ReturnUrl?

I am developing an identity server 4 dotnet core application so this is as much as a dotnet question than and IDS4 question. One example of state I need to maintain between pages (login, signup etc...) is the returnUrl. The application I'm migrating from used to store it in a session variable but, as I understand, unless I run a persistent session strategy, this won't scale well.
So currently, I'm passing it around as a field in each View Model used by each view so it can be returned. Is this a sound approach? I'll be needing other fields to be passed around as well so I'm wondering whether this is a secure and logical way to do it.
So currently, I'm passing it around as a field in each View Model used by each view so it can be returned. Is this a sound approach?
Yes, how you choose to pass it around is up to you, I choose this same approach. You could use TempData, Sessions or even localStorage as an alternative. I think having it in the models (view models) is a good approach because you are explicitly specifying where you want the return url to exist, otherwise it might persist in context that you wouldn't want.
Now the security question because obviously you might be able to see the return url in the browser address field.
As part of Identity Server 4 setup you specify which return url's you are allowed to redirect back to, so I don't think there is any harm in having the users see the redirect url.
Something to consider is what if the user would share the url to someone else in the middle of the authentication process, would they be able to resume from that part of the process that the initial user has stopped? is this something you want in your app?
If you mean reliably instead of securely, write tests which will provide you with confidence that your code works.

Restful API design: how should user's and authority's endpoints be?

Based on similar questions, i came to the conclusion that the most convenient way to design this endpoints to GET requests should be something like:
GET /v3/users/
GET /v3/users/{userId}
GET /v3/users/{userId}/authorities
GET /v3/users/authorities/{authId}
My question is how should be the next endpoints:
1. Create authorities
POST /v3/users/authorities
POST /v3/users/{userId}/authorities
2. Update authorities
PUT/PATCH /v3/users/authorities/{authId}
PUT/PATCH /v3/users/{userId}/authorities/{authId}
3. Delete authorities
DELETE /v3/users/authorities/{authId}
DELETE /v3/users/{userId}/authorities/{authId}
What do you think? Intuitively, i go with first option on all cases but maybe is not the nicest thing passing the userId from body (i see it nicer passing it from url). Or should i implement both endpoints maybe?
Second approach is cleaner and more standard.
PUT/PATCH/POST/DELETE.. /v3/users/authorities/{authId} - [1]
PUT/PATCH/POST/DELETE.. /v3/users/{userId}/authorities/{authId} -[2]
Here, for example, if you pass authId in uri, why not userId ? The standard you will be following here is "resource/{uniqueId}/attribute/{uniqueId}". Ideally in your back-end code, you first look up for the specific resource, and then look up specific attribute(s) for the same resource with the keys/ids passed in the uri. Id is omitted when the action is going to affect all the resources!
If you use the approach [1], it looks like you are trying to add/update/delete an authority for ALL users! Definitely that is not the case.
It is doable to send the userId in the form/post data, but not the correct approach. In your form/post data, you should send the values that are going to be added/updated (in case of PUT/POST). Something like {authType: 'Admin', isGlobal: true, effectiveFrom: '12/12/2015'}. Obviously, userId does not fit here.
First, let me say that I agree with the answer Arghya placed, but I do think there could be a case made for shortening those UPDATE and DELETE urls down to v3/authorities/{authId}.
Of course, this would assume that the authId is unique for that Authority across the application. I personally don't see a point in specifying a user. Either the person that is hitting that route has access to the resource or not.
Just remember that RESTful is just an architectural style. You should do what fits best into your technology stack and makes the most sense for you and the clients interacting with this API.

Authorization with Devise and multiple levels

I need some help with the authorization. So far I was trying to solve it with the internal rails authorization combined with devise.
I have a user who is posting a request. If this request is private only a group of "reader" can see and answer the request. (This is number one)
Then the user give a rating to the answer of the reader. This should be accesible only for the user which received the answer and the "reader" who gave an answer.
So far I was using the following to limit access to the hidden requests:
before_filter :require_reader!, only: [:open_requests]
But if the request is not hidden, than still only the reader should be able to answer the request (but all can see it). Here I do not know how to manage this. Any Ideas?
To continue... I could not manage to solve the second problem (that the rating is seen only be the one who was placing the request and the reader).
Any ideas here?
Is cancancan maybe an option?
Best
witali
What you're doing does not quite follow the 'admin' pattern that's commonly setup with tools like Railsbricks. The 'admin' permissions pattern is typically a whole set of actions/views that are available only to admins, so often the entire Controller, or family of controllers, have the :require_admin! filter applied before every single action and view. Very simple permissions logic, and it depends only on the user and view.
Instead, what you've got is views with permissions that depend on your object's state as well as the user's status and the view. So you're going to have to write your own filter to use instead of using 'require_reader!'.
For example, you might have a RequestsController, and you could add to it:
before_action :must_be_able_to_view_request, except: [:index, :new, :create]
Then define that filter in the controller:
private
def must_be_able_to_view_request
if !current_user.is_reader? && !#request.ispublic
head :forbidden
end
end
If you need to use the same filter in other Controllers, then you can define it in your ApplicationController.

Rails 3 - Model related to current user in controller

We assume an authentication system is setup and we have access to a variable current_user, e.g.: using the Devise gem.
We have two models, User and Thing, User has one Thing.
In the controller, what's the best practise in order to get the right Thing to create/delete if we assume that a User can only create/delete his own Thing.
Eg for create action.
OPTION 1 (standard) :
#thing = Thing.new(params[:thing])
#thing.save
And we set the user_id in the view.
OPTION 2 :
#thing = current_user.create_thing
And we don't bother about setting the user_id in the view.
Both works but I would like to know if one must be avoid or is better and why.
Thanks!
I personally think the second option is better because (as you say) you don't have to mess around with a user_id (neither in the view nor specifically within the controller).
The first option is only useful if you want to allow users to set things for other users than themselves. If you don't want to allow this, the first option even introduces a possible vulnerability. Malicious users can try exploiting the user_id field in the view. So, assuming users can only set their own things: definitely option 2.
If you are using devise gem, Its better to play with current_user. This will be more secured than passing users id.

rails3, params[:id] encryption

I trying to prevent url hacking, I passing an id to the url that the forms need, it works fine but if the user changes that value on the url it will send values to the wrong table.
<%= link_to '+ New Event',
{:controller =>'events', :action =>
'new', :company_id => company.id} %>
On the php world I used to encrypt that id ...how can I do this on rails3 or is there a better way ??
needless to say I sort of new to rails and I know a little bit of php
any help or suggestions will be greatly appreciated.
Even though this is an older question, it's a very worthwhile question. It is absolutely worthwhile to conceal the ID in the URL for, among other things, prevention of information disclosure.
For example, an application has a robust security model allowing users to only view resources to which they have rights. However, why should a user be able to look at the value of the ID in the URL and use it to deduce how many resources there are or, as the original questioner suggests, start trying to poke around with forced browsing.
The solution to this in rails turns out to be pretty simple. What I find works best is overriding to_param in the models, usually via a module in the lib directory and a before_filter in the application controller that decrypts the IDs.
For a walkthrough, have a look at this: http://www.youtube.com/watch?v=UW_s9ejrCsI
Rather than trying to encrypt or hide your company.id value, ask yourself what exactly it is that you want to prevent users from doing.
If you just want to prevent users from creating events associated with non-existant companies (by setting the id to a really high value for instance), then a simple
validates_presence_of :company
On the Event model would be fine.
If you only want users to be able to create events associated with companies that they work for, or have access for in some way, then you should create custom validations to verify that.
F