Restricting a link to just admin users

21 views
Skip to first unread message

David Merrick

unread,
Jul 4, 2018, 4:10:55 AM7/4/18
to Ruby on Rails: Talk
I only want the link <li><%= link_to "Users", users_path %></li> to be seen by admin users

Header File 

<header class="navbar navbar-fixed-top navbar-inverse">
  <div class="container">
    <%= link_to "sample app", root_path, id: "logo" %>
    <nav>
      <ul class="nav navbar-nav navbar-right">
        <li><%= link_to "Home", root_path %></li>
        <li><%= link_to "Help", help_path %></li>
         <% if logged_in? %>
          <li><%= link_to "Users", users_path %></li>
          <li class="dropdown">
            <a href="#" class="dropdown-toggle" data-toggle="dropdown">
              Account <b class="caret"></b>
            </a>
            <ul class="dropdown-menu">
              <li><%= link_to "Settings", edit_user_path(current_user) %></li>
              <li class="divider"></li>
              <li>
                <%= link_to "Log out", logout_path, method: :delete %>
              </li>
            </ul>
          </li>
        <% else %>
          <li><%= link_to "Log in", login_path %></li>
        <% end %>
      </ul>
    </nav>
  </div>
</header>

users controller is shown below

class UsersController < ApplicationController
  before_action :logged_in_user, only: [:index, :edit, :update, :destroy,
                                        :following, :followers]
  
  before_action :correct_user,   only: [:edit, :update]
  before_action :admin_user,     only: :destroy
  
  def index
    @users = User.where(activated: true).paginate(page: params[:page])
  end
  
  def show
    @user = User.find(params[:id])
    redirect_to root_url and return unless @user.activated?
  end

  def new
    @user = User.new
  end

  def create
    @user = User.new(user_params)
    if @user.save
      @user.send_activation_email
      flash[:info] = "Please check your email to activate your account."
      redirect_to root_url
    else
      render 'new'
    end
  end  

  def edit
    @user = User.find(params[:id])
  end

  def update
    @user = User.find(params[:id])
    if @user.update_attributes(user_params)
      flash[:success] = "Profile updated"
      redirect_to @user
    else
      render 'edit'
    end
  end
  
  def destroy
    User.find(params[:id]).destroy
    flash[:success] = "User deleted"
    redirect_to users_url
  end

  
  private

    def user_params
      params.require(:user).permit(:name, :email, :password,
                                   :password_confirmation)
    end
    
    # Confirms the correct user.
    def correct_user
      @user = User.find(params[:id])
      redirect_to(root_url) unless current_user?(@user)
    end
    
    # Confirms an admin user.
    def admin_user
      redirect_to(root_url) unless current_user.admin?
    end
    
end

users model is shown below

class User < ApplicationRecord                               
                                                                    
  attr_accessor :remember_token, :activation_token, :reset_token
  before_save   :downcase_email
  before_create :create_activation_digest
  
  validates :name,  presence: true, length: { maximum: 50 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :email, presence: true, length: { maximum: 255 },
                    format: { with: VALID_EMAIL_REGEX },
                    uniqueness: { case_sensitive: false }
  has_secure_password
  validates :password, presence: true, length: { minimum: 6 }, allow_nil: true

  # Returns the hash digest of the given string.
  def User.digest(string)
    cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST :
                                                  BCrypt::Engine.cost
    BCrypt::Password.create(string, cost: cost)
  end

  # Returns a random token.
  def User.new_token
    SecureRandom.urlsafe_base64
  end
  
  # Remembers a user in the database for use in persistent sessions.
  def remember
    self.remember_token = User.new_token
    update_attribute(:remember_digest, User.digest(remember_token))
  end
  
  # Returns true if the given token matches the digest.
  def authenticated?(attribute, token)
    digest = send("#{attribute}_digest")
    return false if digest.nil?
    BCrypt::Password.new(digest).is_password?(token)
  end

  # Forgets a user.
  def forget
    update_attribute(:remember_digest, nil)
  end
  
  
  # Activates an account.
  def activate
    update_columns(activated: true, activated_at: Time.zone.now)
  end

  # Sends activation email.
  def send_activation_email
    UserMailer.account_activation(self).deliver_now
  end
  
  # Sets the password reset attributes.
  def create_reset_digest
    self.reset_token = User.new_token
    update_attribute(:reset_digest,  User.digest(reset_token))
    update_attribute(:reset_sent_at, Time.zone.now)
  end

  # Sends password reset email.
  def send_password_reset_email
    UserMailer.password_reset(self).deliver_now
  end
  
  # Returns true if a password reset has expired.
  def password_reset_expired?
    reset_sent_at < 2.hours.ago
  end
  
  # Returns a user's status feed.
      
  private

    # Converts email to all lower-case.
    def downcase_email
      email.downcase!
      #self.email = email.downcase
    end

    # Creates and assigns the activation token and digest.
    def create_activation_digest
      self.activation_token  = User.new_token
      self.activation_digest = User.digest(activation_token)
    end
  
end

index.html.erb is shown below

<% provide(:title, 'All users') %>
<h1>All users</h1>

<%= will_paginate %>

<ul class="users">
  <%= render @users %>
</ul>

<%= will_paginate %>

Is it possible to alter the index file so that only admin users see it and the link in the header file?

Cheers Dave




Colin Law

unread,
Jul 4, 2018, 4:17:12 AM7/4/18
to Ruby on Rails: Talk
On 4 July 2018 at 09:10, David Merrick <merri...@gmail.com> wrote:
> I only want the link <li><%= link_to "Users", users_path %></li> to be seen
> by admin users
>
> Header File
>
> <header class="navbar navbar-fixed-top navbar-inverse">
> <div class="container">
> <%= link_to "sample app", root_path, id: "logo" %>
> <nav>
> <ul class="nav navbar-nav navbar-right">
> <li><%= link_to "Home", root_path %></li>
> <li><%= link_to "Help", help_path %></li>
> <% if logged_in? %>

Test the role of the current user here and only show the next line if
the role is admin.

> <li><%= link_to "Users", users_path %></li>

Colin

David Merrick

unread,
Jul 4, 2018, 4:32:13 AM7/4/18
to Ruby on Rails: Talk
Thanks Colin


--
You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-talk+unsubscribe@googlegroups.com.
To post to this group, send email to rubyonrails-talk@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/rubyonrails-talk/CAL%3D0gLsLrziQNJWn5foz1Csrag12SNxt8O%3DEAcYnKkr2PGYQAg%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.



--
Dave Merrick

Tutor Invercargill

Website http://tutorinvercargill.co.nz/

Email merri...@gmail.com

Ph   03 216 2053

Cell 027 3089 169

Mike

unread,
Jul 5, 2018, 4:13:36 AM7/5/18
to Ruby on Rails: Talk
It depends on how complex your permissions are, you could define a method in the user model called (for example) is_admin? That returns a Boolean, and then surround the links in a

<% if current_user.is_admin? %>
(Link here)
<% end %>


If your needs are a bit more complex then I would look at the ‘rolify’ gem, which can give you some fine grained role control, even down to an individual record

So you can have a ‘global’ admin, or a table (model) admin, or a (user) record admin.

I have used this in the past to make me a global admin, but when a user record is created, I make the user an admin (well manager anyway) of that record so they can update it

That may be too complex for your needs but the functionality is there

Reply all
Reply to author
Forward
0 new messages