rosstex / lab9

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Lecture/Lab 9: Authentication

The app from last week is functional but has huge security issues! Let's fix them in our extended lab for this week.

First, find a partner! You and your partner will alternate between questions. Pretend it's your actual project by branching, commititng, making a pull request, and having your partner merge it in before starting on the next question.

Designate one person as person A, and the other as person B. Have person A fork this repo on Github, go to Settings -> Collaborators, and add person B to the repo.

Person A: Ross Teixeira

Person B: Allan Tang

Now both partners should run

git clone https://github.com/<your username>/lab9

to start working on the app. There is a written portion of this lab, so write down your answers in lab9.txt and submit them through the form!

  1. Make your first pull requests! Both teammates should edit the README.md file so that the blank "Person A:" lines have the person's name. At the end the two blank lines above should look like:

    Person A: Sam Lau

    Person B: Jessica Lin

    Start with git checkout -b <readme-A or readme-B>. The -b option to git checkout tells git to make a new branch and switch to it right away. Then make your changes, add, commit, and push to person A's Github. Make a pull request for your changes, and have the other person merge it into master. Congratulations! You just made your first pull request.

  2. (Person A codes) Remember how we included devise in step 2 of the lecture app? We never actually had the user sign in at any point! Since devise is already set up we should be able to log in. Test it out by first finding the route that ends in /sign_in using rake routes and visiting it in your browser.

    a. What happens when you log in? What happens if you try to log in again? Does it work as you expect?

    Let's now add log in and log out links to the navbar so it's easier to see when we're logged in. Devise has some helpers that allow you to check if a user is signed in or not, we'll have to use them now.

    b. What is the helper that devise creates that checks if a user is logged in or not?

    Add two <li> elements below the existing link to 'Users' in application.html.erb that link to the sign in/out paths depending on if the user is signed in (only one of those li elements will be visible at any time to the user). You should add 5-6 lines of extra code.

  3. (Person B codes) So now we have logging in and out. Now we want to make sure that if a user is not signed in that we only allow them to view the sign in page - all pages should redirect to the sign in page if there isn't a signed in user.

    a. How would you go about implementing this with the knowledge you have now? (If you know about before_filter you can't use it - that's coming up.)

    Luckily Rails provides a handy before_filter method! It takes in a procedure name as a symbol as an argument and runs that procedure before any of the actions in the controller are hit (if you want to limit the methods that it runs before, before_filter takes in another argument, except. See the docs for more info.) which is exactly what we need! Devise also has a handy method to redirect someone to the log in page if they aren't logged in; how convenient. Write one line of code in application_controller.rb that enforces a signed in user. Hint: you should probably check the devise docs again.

    b. Why does that line of code work for all actions in all controllers?

  4. (Person A codes) As you may have noticed, the app isn't very informative when you try to visit a page without signing in: it just throws you back to the sign in page without any explanation. And, if you log in with bad credentials nothing shows up to tell you you messed up. It turns out that devise is trying to tell the user that something messed up but you aren't showing it! Stick a <%= 1/0 %> somewhere in application.html.erb and try visiting the home page while not logged in.

    a. In the console in the error page, check the value of flash. What do you notice about it?

    In general, we use flash to store temporary messages we want to show the user only once. We've actually used it in quits_controller.rb to tell the user that a quit was updated. flash is a hash where the key is the type of message and the value is the message. Devise does flash[:alert] = '<some message>' when you try to visit a page while not logged in, so let's show the user that message.

    Write 3 lines of code right above the yield statement in application.html.erb that loops through each key-value pair in flash and outputs the following code where key is the key and value of each thing in flash:

     <%= content_tag(:div, value, class: "alert alert-#{key}") %>
    

    You should now see pretty messages when you log in, update a quit, and more!

  5. (Person B codes) Remember how we allowed user_id to pass through in the params and how it caused problems in the past? In fact, the way we implemented quit creation in general isn't ideal since we're forced to pass the user_id through the form. Since we're always going to create/update quits in the context of a specific user, it makes more sense to route our app to make this easier.

    a. Check the Rails Guides for something related to routes that are made for a belongs_to/has_many relationship. What was the section title?

    Change routes.rb so that quits are nested under users. To verify that your answer is on the right track, the URL for a new quit should look like /users/:user_id/quits/new now (all the other quit routes will be changed too). You should have to modify/add very few lines of code, 2-3 at max.

    b. A lot of routes will now be broken! Why?

    Update the routes everywhere in the controllers/views so that they use the new routes which you just created. This is a difficult question since it involves multiple views/controllers! Start by changing all the old routes to new ones. If you're not sure if the routes work or not, you can always check them with a 1/0 and using the console that better errors starts.

    Hint: just like how we could do edit_quit_path(@quit) before, now we can do edit_user_quit_path(@user, @quit) given that @user and @quit are defined.

    Hint 2: Notice that a lot of routes have :user_id. That means you can get the user related to that URL with User.find params[:user_id] and not have to worry about setting it manually in your routes.

    Hint 3: You'll get an error of 'undefined method `quit_path'' when you try to render the form view for a quit. To fix this, use simple_form_for [@user, @quit], .... Of course, this only works if @user and @quit are not nil.

    Hint 4: You'll make changes to 1 line in each view in the quits folder, and 2 line changes in users/show.html.erb. In quits_controller.rb, you only have to add one line to the edit action and a one line addition + one line modification in the create action.

    Now you should be able to stop permitting :user_id in the quit_params method of quits_controller.rb. Verify that all actions still work correctly.

  6. (Person A codes) So we have some basic authorization going on since we require a user to sign in before viewing quits. But, a logged in user can still create/edit quits for other people! Verify this is true. Make changes to quits_controller.rb so that a person can only create/modify quits that belong to him. If a person tries to create/change a quit that belongs to another person, redirect hiim to the root_path with an alert message in flash "Can't create/edit a quit for another person!".

    a. Why don't we need to make changes to application_controller.rb?

    b. Why don't we need to make changes to users_controller.rb?

  7. (Person B codes) Now, if we have administrators, they should be able to create and edit quits at will. First, we'll have to designate some users as administrators. Create a migration that adds the :admin attribute to users, and default it to false. After migration, create one admin in your seeds. You can now do something like User.first.admin?, which returns true or false. Then make the necessary changes so that users who are admins can create and edit quits of all users.

You made it! Submit the written portion of the lab here.

About


Languages

Language:Ruby 93.5%Language:CSS 5.0%Language:JavaScript 1.5%