Devise gem User Authentication

This is my code for my index.html.erb scaffold as you can see the if else stops a user to "show, edit or destroy" the entries. However, they can create a new Rota entry by clicking New Rotum. I can get rid of the admin part in Show, edit, destroy and everyone will be able to do everything. But I want a user to be able to only show edit destroy their OWN entry and not everyone elses too because that is what happens when I authenticate a user to do this?

     <h1>Listing rota</h1>

     <table id = "tabletest">       <thead>         <tr>       <th>Name</th>       <th>Mobile</th>       <th>Email</th>       <th>Category</th>       <th>Other</th>       <th colspan="3"></th>        </tr>      </thead>

     <tbody>        <% @rota.each do |rotum| %>         <tr>         <td><%= rotum.name %></td>         <td><%= rotum.mobile %></td>         <td><%= rotum.email %></td>         <td><%= rotum.category %></td>         <td><%= rotum.other %></td>

     <% if current_user.try(:admin?) %>         <td><%= link_to 'Show', rotum %></td>         <td><%= link_to 'Edit', edit_rotum_path(rotum) %></td>         <td><%= link_to 'Destroy', rotum, method: :delete, data: { confirm: 'Are you sure?' } %></td>       </tr>        <% end %>              <% end %>      </tbody>     </table>

    <br>        <% if user_session %>     <%= link_to 'New Rotum', new_rotum_path %>       <% end %>

What does the controller look like?

Try googling for "devise with cancan"

class RotaController < ApplicationController       before_filter :authenticate_user!, except: ( :Welcome)   before_action :set_rotum, only: [:show, :edit, :update, :destroy]

  # GET /rota   # GET /rota.json   def index     @rota = Rotum.all     @is_admin = current_user.try(:admin?)   end

  # GET /rota/1   # GET /rota/1.json   def show   end

  # GET /rota/new   def new     @rotum = Rotum.new   end

  # GET /rota/1/edit   def edit   end

  # POST /rota   # POST /rota.json   def create     @rotum = Rotum.new(rotum_params)

    respond_to do |format|       if @rotum.save         format.html { redirect_to @rotum, notice: 'Rotum was successfully created.' }         format.json { render :show, status: :created, location: @rotum }       else         format.html { render :new }         format.json { render json: @rotum.errors, status: :unprocessable_entity }       end     end   end

  # PATCH/PUT /rota/1   # PATCH/PUT /rota/1.json   def update     respond_to do |format|       if @rotum.update(rotum_params)         format.html { redirect_to @rotum, notice: 'Rotum was successfully updated.' }         format.json { render :show, status: :ok, location: @rotum }       else         format.html { render :edit }         format.json { render json: @rotum.errors, status: :unprocessable_entity }       end     end   end

  # DELETE /rota/1   # DELETE /rota/1.json   def destroy     @rotum.destroy     respond_to do |format|       format.html { redirect_to rota_url, notice: 'Rotum was successfully destroyed.' }       format.json { head :no_content }     end   end

  private     # Use callbacks to share common setup or constraints between actions.     def set_rotum       @rotum = Rotum.find(params[:id])     end

    # Never trust parameters from the scary internet, only allow the white list through.     def rotum_params       params.require(:rotum).permit(:name, :mobile, :email, :category, :other)     end end

Jason Fb wrote in post #1159167:

What does the controller look like?

class RotaController < ApplicationController       before_filter :authenticate_user!, except: ( :Welcome)   before_action :set_rotum, only: [:show, :edit, :update, :destroy]

  # GET /rota   # GET /rota.json   def index     @rota = Rotum.all     @is_admin = current_user.try(:admin?)   end

  # GET /rota/1   # GET /rota/1.json   def show   end

  # GET /rota/new   def new     @rotum = Rotum.new   end

  # GET /rota/1/edit   def edit   end

  # POST /rota   # POST /rota.json   def create     @rotum = Rotum.new(rotum_params)

    respond_to do |format|       if @rotum.save         format.html { redirect_to @rotum, notice: 'Rotum was successfully created.' }         format.json { render :show, status: :created, location: @rotum }       else         format.html { render :new }         format.json { render json: @rotum.errors, status: :unprocessable_entity }       end     end   end

  # PATCH/PUT /rota/1   # PATCH/PUT /rota/1.json   def update     respond_to do |format|       if @rotum.update(rotum_params)         format.html { redirect_to @rotum, notice: 'Rotum was successfully updated.' }         format.json { render :show, status: :ok, location: @rotum }       else         format.html { render :edit }         format.json { render json: @rotum.errors, status: :unprocessable_entity }       end     end   end

  # DELETE /rota/1   # DELETE /rota/1.json   def destroy     @rotum.destroy     respond_to do |format|       format.html { redirect_to rota_url, notice: 'Rotum was successfully destroyed.' }       format.json { head :no_content }     end   end

  private     # Use callbacks to share common setup or constraints between actions.     def set_rotum       @rotum = Rotum.find(params[:id])     end

    # Never trust parameters from the scary internet, only allow the white list through.     def rotum_params       params.require(:rotum).permit(:name, :mobile, :email, :category, :other)     end end

I will take a look at it, thanks for the advice

The before_action :set_rotum is where you want to put the access control.

Despite what I said earlier, you don't actually need cancan, but as an alternative to this implementation you can use something like cancan for access control.

In your example, you would do something like this (obviously this example assumes you have the rotem object belonging to the user object)

def set_rotem   @rotem = current_user.rotems.find(params[:id])   if @rotem.nil?     render :html => "Not authorized", :status => 401   end end

or something like this:

def set_rotem   @rotem = Rotem.find(params[:id])   if @rotem.user != current_user     render :html => "Not authorized", :status => 401   end end

-Jason

I am using rails-devise-pundit, It works perfect. However, I tried to include this code in my controller, but it shows me

undefined method `set_rotum' for #<RotaController:0x000000050413e8>

I'm trying to fix this as we speak, However if you have any suggestions. Please try and help. Thanks.

Rashid