Skip to content

Instantly share code, notes, and snippets.

@leahgarrett
Last active April 22, 2019 17:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save leahgarrett/24476700469b9c2146b56448face56af to your computer and use it in GitHub Desktop.
Save leahgarrett/24476700469b9c2146b56448face56af to your computer and use it in GitHub Desktop.
Authentication and Authorisation

Authentication and Authorisation

Have you been authenticated?

Usually you login in to be authenicated on a web app.

Defintion of authenticate
'prove or show (something) to be true, genuine, or valid.'
'COMPUTING (of a user or process) have one's identity verified.'

Are you authorised?

Authenticated users may not be authorised to see all the content on a website.

For example, an admin user will see a lot more features.

Defintion of authorise
give official permission for or approval to (an undertaking or agent).

References

https://guides.railsgirls.com/devise https://www.sitepoint.com/devise-authentication-in-depth/ https://www.pluralsight.com/guides/implementing-a-custom-devise-sign-in-and-actioncable-rails-5


There is a gem for that

Add the following lines to the end of the gemfile

/Gemfile

gem 'devise'
gem 'cancancan'

Then at the command line run
bundle install

Run the devise generators
rails generate devise:install
rails generate devise User
rails generate devise:views

Now lets update the database with the new user table
rake db:migrate


Adding links to devise forms

Add the following code between body tags as shown below: /app/views/layouts/application.html.erb

[...]
<body>
 <div class="container">
    <div id="navbar">
    <ul class="nav navbar-nav">
      <li><%= link_to 'Home', root_path %></li>
    </ul>
    <ul class="nav navbar-nav pull-right">
      <% if user_signed_in? %>
        <li class="dropdown">
          <a class="dropdown-toggle" data-toggle="dropdown" href="#">
            <span class="caret"></span>
          </a>
          <ul class="dropdown-menu" role="menu">
            <li><%= link_to 'Profile', edit_user_registration_path %></li>
            <li><%= link_to 'Log out', destroy_user_session_path, method: :delete %></li>
          </ul>
        </li>
      <% else %>
        <li><%= link_to 'Log In', new_user_session_path %></li>
        <li><%= link_to 'Sign Up', new_user_registration_path %></li>
      <% end %>
    </ul>
  </div>
  <% flash.each do |key, value| %>
    <%= value %>
  <% end %>
  
  <%= yield %>
  </div>
  </body>
  [...]

Add users using the devise forms

Add a test user

  • click Sign-up
  • enter test user details
  • click profile to review

Add Authorisation

We will be using the can can gem we added earlier.

Create the Ability class from CanCanCan rails generate cancan:ability

Uncomment the simple user test as follows

/app/models/ability.rb

class Ability
  include CanCan::Ability

  def initialize(user)
    # Define abilities for the passed in user here. For example:
    #
      user ||= User.new # guest user (not logged in)
      if user.admin?
        can :manage, :all
      else
        can :read, :all
      end
    #
    # The first argument to `can` is the action you are giving the user
    # permission to do.
    # If you pass :manage it will apply to every action. Other common actions
    # here are :read, :create, :update and :destroy.
    #
    # The second argument is the resource the user can perform the action on.
    # If you pass :all it will apply to every resource. Otherwise pass a Ruby
    # class of the resource.
    #
    # The third argument is an optional hash of conditions to further filter the
    # objects.
    # For example, here the user can only update published articles.
    #
    #   can :update, Article, :published => true
    #
    # See the wiki for details:
    # https://github.com/CanCanCommunity/cancancan/wiki/Defining-Abilities
  end
end

Add an admin column to the User table rails generate migration AddAdminToUser admin:boolean

Open the migration generated to verify the column being added.

Add an admin user using seeds.rb by calling the User constructor as follows:

[...]
puts 'Creating an admin user'
User.new({ :email => 'admin@admin.com.au', :password => 'password321', :password_confirmation => 'password321', :admin => 'true'}).save

puts "Seeding Over"

Apply Authorisation to view

Add a CanCan check around the edit link in the index page as follows:

/app/views/restaurants/index.html.erb

<h1>Restaurants</h1>

<ul>
    <% @restaurants.each_with_index do |restaurant, index| %>
        <li>
            <%= restaurant.title %> - <%= restaurant.food_type %> 
            <%= link_to "show", restaurant_path(restaurant.id) %>
            <% if can? :update, restaurant %>
             <%= link_to "edit", edit_restaurant_path(restaurant.id) %>
             <% end %>
            <p>Reviews: <%= restaurant.reviews.count %></p>
        </li>
    <% end %>
</ul>

Apply Authorisation to controller actions

Unauthorised users may try to access links that are not visible eg: http://localhost:3000/restaurants/4/edit

Add a call to authorize_resource method in the restaurant controller to authorize it automatically for every action in that controller.

class RestaurantsController < ApplicationController
  authorize_resource
  [...]

Next Steps

  • Add CanCanCan checks so only admin users can edit, update and delete

  • Add a CanCanCan check for user around the Add Review link. If not logged in display a message to say must login to create a review and add a link to the login and sign up forms

  • Add a moderator user that can delete reviews but cannot edit or delete restaurants

  • test while logged in as each user type

  • test while not logged in

  • Add Bootstrap (if you don't already have it) and update the layout for the devise logina nd sign-up forms and profile page

  • continue working on the additional steps to the restaurant app from previous challenge:
    https://gist.github.com/leahgarrett/9100cfdbc2a2b0765c1de5c810d1f785

  • Add devise and CanCan to the book app

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment