Newbie with Rails devise and view of the user - ruby-on-rails

I'm looking into RoR some way to: login into the system with DEVISE, (it's working), but i'm needing something than keeps always the view of this logged user, and avoid than this user looks another views.
http://xx.xx.xx.xx:3000/user/1
And this user cannot look the content of:
http://xx.xx.xx.xx:3000/user/2.
Please, sorry if this is a silly question, but, i was looking 2 days and i don't know how i can name this feature.
Thanks!

There are gems available for this Authorization. I prefer can can which is one of the best Authorization gems available
Here is the gem=> https://github.com/ryanb/cancan
And here is the rails cast tutorial using it=> http://railscasts.com/episodes/192-authorization-with-cancan
EDIT: If you want to manually implement this then you just need to make a method with following logic
def check_authorization
# Assuming user ID is coming in params[:id]
if current_user.id == params[:id]
return
else
# render or redirect to some page with access denied message
end
end
And call this method just before any action in which you want to check for authorization.

Related

Make 301-redirects administratable by the user in Rails?

we are currently relaunching a bigger website from PHP (Magento with a quite exhaustive forum) into a Rails-app while keeping the forum.
During this undertaking we will migrate quite a lot of content to new URLs, which means we'll have to 301 redirect a lot of them.
Now we all know about Apache/NGINX-rewrites. I also found https://github.com/jtrupiano/rack-rewrite for RACK.
But is there a good way to make 301-redirects administratable by our users with Rails? (I'm basically looking for a GEM or RACK-app, where our users can log in, then see and edit the existing redirects).
Thanks for any help.
You could store all redirects in a model with attributes "from" and "to". Then, you can manage this redirects from your admin area as you want.
Then, in your ApplicationController, you can wrap your actions in a around filter as it says here:
around_filter :catch_not_found
private
def catch_not_found
yield
rescue ActiveRecord::RecordNotFound
redirect = Redirect.where(from: request.original_fullpath).first
redirect_to "#{request.base_url}#{redirect.to}" if redirect
end

how to redirect the user to their own page (ROR and Devise Gem)

ok, bear with me here, please.
i'm asking a question in which i'm not fully conversant of all the technical details, etc. (in other words, please take it easy on me for not being fully up on the par).
i've created a ROR application with Devise's gem ... it allows you to sign in, sign up, and log out.
it's very simple, and it just has a page in which you fill in your name, favorite hobby, & book. (hey, it's just an example)
i've also used their redirect code to go this page:
def after_sign_in_path_for(resource)
posts_path
end
the thing is that ... this page is public to everyone who logs in.
how do i redirect the user to their own page? and not see everyone's else "notes."
i've looked around ... and Devise has a link on sessions_controllers ...
do i use that? i don't fully understand the purpose of it.
if yes, how? still trying to figure out how all the puzzle pieces fit together, and it's hard to do that when you don't have full understanding of the topic itself.
or is there another way that's simpler?
if this question is too broad, please let me know ... but i'm not really quite sure how to break it down.
in essence, what i'm really asking is how do i have a user be directed to their own page and not see anyone else's page.
thanks in advance for any help/advice/pointers/etc.
First, let's assume your User model has_many :posts. In your PostsController index action (the default RESTful route would be posts_path) you can put something like this:
#posts = current_user.posts
and when visiting the index view you will only see the current user's posts.
That being said, you are not limited to the index view. You can customize any view you'd like and have a corresponding Controller action with declared instance variables which you can manipulate in your views.
Does that makes sense?
Try with:
def after_sign_in_path_for(user) # note: user or w/e your model is named
users_path(current_user)
end

authenticate_user! from Devise, in spree (spree commerce), does not work as expected when used as a before_filter

I am using Rails (3.2.6) with devise (2.1.2) and have a controller where I would like to make sure users are authenticated before proceeding.
Optimistically, I tried...
module Spree
class MyAppController < Spree::BaseController
before_filter :authenticate_user!
...remainder of MyAppController code...
and I am NOT redirected to a login or sign-in page. I am redirected to the 'products' page, with a polite message at the top saying I need to sign-in or sign-up to continue.
What I would like to happen is that I am redirected to sign-up / sign-in and when that is completed successfully, the original controller path resumes.
Searching around, I have read that authenticate_user! from Devise interacts with Spree in such a way as to cause an infinite redirection, so something in Spree disables this, resulting in the lame behavior I describe above.
Has anyone managed to get this to work or have suggestions for a good work-around?
I have found a work around, but I am not an experienced enough Rails developer to know how reasonable this solution is.
I wrote a method to do the filtering and used it instead of authenticate_user!...
def require_authentication
unless current_user
# setting this in the session allows devise to return us to
# the original invocation path, once sign up / sign in is complete
session[:user_return_to] = request.env['PATH_INFO']
redirect_to new_user_session_url and return
end
end
did you try adding
before_filter :check_authorization
to your controller?
I think that may do what your looking for.
Thanks
Ash

RoR testing controllers

I use RoR 3 and i guess something changed in controller's tests.
There is no
def test_should_create_post
but
test "should create user" do
...
end
Is there any decription how is that mapping etc? Because i dont get it.
And second thing. How to program (what assertion) use to test login?
so the test "something here" style is rails way of helping us out. It is fundamentally the same as def test_as_you_want but they helped us out by taking away those nasty '_(underscores)' and wrapping the actual test wording in a string. This change came back, phew... maybe 2.3.x. that fact has to be checked but at least a year and a half ago.
Your second thing is a little more harder to answer man. What plugin are you using, or are you one of those guys who are writing their own auth system?
Either way, check out how the 'famous' auth plugins do it. from Restful Auth to Devise, basically you want test that you can:
Signup for the User account
all of your confirmation emails are sent etc..
Most of these 'cheat' or take the easy way out by passing a helper called signed_in users(:one) for instance. Assuming you are cool and using fixtures.
Basically here is what a helper method looks like if your Auth plugin/gem doesn't have one, like Clearance which didn't have it when i was first writing my tests... not sure if it has it now but it sheds light on how it should look. Notice I've commented out Restful Auth and how he/they did it:
#login user
def login_user(user = users(:one))
#Restful Auth Example
# #request.session[:user_id] = user ? users(user).id : nil
# Clearance
#controller.class_eval { attr_accessor :current_user }
#controller.current_user = user
return user
end
Actually i think i stole this from their shoulda login helper... that's probably what i did. Either way it shows you how to fake login a user.
Now when you are testing, just pass this login_user method to your test when you need a user logged in and start testing the rest of the method without worrying about them actually signing in. That is what the plugin is supposed to do and the 1000 people following it on github would scream if it didn't at least LOG that guy in.
cheers

Rails user authorization

I am currently building a Rails app, and trying to figure out the best way to authenticate that a user owns whatever data object they are trying to edit.
I already have an authentication system in place (restful-authentication), and I'm using a simple before_filter to make sure a user is logged in before they can reach certain areas of the website.
However, I'm not sure the best way to handle a user trying to edit a specific piece of data - for example lets say users on my site can own Books, and they can edit the properties of the book (title, author, pages, etc), but they should only be able to do this for Books that -they- own.
In my 'edit' method on the books controller I would have a find that only retrieved books owned by the current_user. However, if another user knew the id of the book, they could type in http://website.com/book/7/edit , and the controller would verify that they are logged in, then show the edit page for that book (seems to bypass the controller).
What is the best way to handle this? Is it more of a Rails convention routing issue that I don't understand (being able to go straight to the edit page), or should I be adding in a before_find, before_save, before_update, after_find etc callbacks to my model?
check out the following gems:
cancan
devise
authlogic
and don't miss Ryan's great railscasts on the above
this will give access to anyone who changes the value in the address bar
#book = Book.find(params[:id])
but if you go through the association of the logged on user rails (ActiveRecord) will automatically update the sql query
#book = current_user.books.find(params[:id])
of course this assumes that your books table has a user_id column
You may need an authorization plugin. I had some experience use this plugin a while back. This article also has an overview:
You might also take a look at Declarative Authorization
Hey I have recently done this myself. The easiest way to do this is to have the edit feature display on the page but incase it in a method such as the following:
<%if current_user %>
<% if current_user.id == wishlist.user_id %>
<div id="text3"><%= link_to 'Edit', edit_wishlist_path(#wishlist) %></div><br />
<%end%>
<%end%>
Is this what you were hoping for?

Resources