What I'm trying to achieve is a follow button that is toggled when the user clicks it. This goes in the users_helper.rb helper. Here's what I have.
The line I need help with is "elsif current_user != #user"
What I'm trying to do here is to remove the follow button for the user's own profile, since he cannot follow himself.
Any help is appreciated, thanks!
def render_follow_conditionally
if user_signed_in?
follow_toggler
else
button_to "Follow", new_user_session_path, class: 'btn btn-lake'
end
end
def follow_toggler
if current_user.following? #user
button_to "Followed", unfollow_user_path(#user), class: 'btn btn-default'
elsif current_user != #user
button_to "Follow", follow_user_path(#user), class: 'btn btn-default'
end
end
You should compare users by their ids
elsif current_user.id != #user.id
Related
So I'm obviously confused with boolean flow because I run into a problem each time. NOTE: I am teaching myself to program, you are all my only hope in learning! I am trying to define a method that checks if a user is an admin, so that I can display certain objects in views to ONLY admins simple enough...or not, for some reason it's not recognizing that I'm an admin (when I truly am, I've checked!). With this all being said, I am a newb so go easy on me!
helpers/sessions_helper is used by both my User and Blogpost models:
def current_user #determines if user is logged out or is the current user of the session/cookie of profile
if (user_id = session[:user_id])
#current_user ||= User.find_by(id: user_id)
elsif (user_id = cookies.signed[:user_id])
user = User.find_by(id: user_id)
if user && user.authenticated?(cookies[:remember_token])
log_in user
#current_user = user
end
end
end
def current_user?(user)
user == current_user
end
def is_an_admin
if current_user && current_user.admin?
end
end
<div class="col-xs-12">
<h1><%= #blogpost.title %></h1>
<p><%= #blogpost.content %></p>
<% if is_an_admin %>
<%= link_to "Return to blog", blogposts_path %>
<%= link_to "Edit Post", edit_blogpost_path, class: 'btn btn-primary' %> |
<%= link_to "Delete Post", blogpost_path(#blogpost),
method: :delete, data: {confirm: "Are you sure?"}, class: 'btn btn-danger' %>
<% else %>
<%= link_to "Return to blog", blogposts_path %>
<% end %>
</div>
I'm unsure if maybe I have the method in the wrong place? I have tried placing it inside my applications controller and my user controller to no avail. I must be missing something.
Your sintax got messed up, but I think you're always returning nil on the is_an_admin method:
def is_an_admin
if current_user && current_user.admin?
end
end
It does nothing if the condition is true so it's always returning nil
Change it to something like:
def is_an_admin?
current_user and current_user.admin? # or shorter: current_user.try('admin?')
end
I'm trying to allow users to show the edit button only if the profile belongs to them. Currently, they're only allowed to edit the profile if it belongs to them but I can't seem to hide the button. I have this so far
<% if request.original_url == request.base_url + "current_user.id" %>
<%= link_to "Edit Profile", edit_user_path(current_user), class: "btn btn-primary btn-xs" %>
<% end %>
This is what I'm trying to compare:
request.original_url => localhost:3000/users/random_user
request.base_url + "users/" + current_user.id => localhost:3000/users/current_user
Thanks in advance.
Authorization
To give you some perspective, you'll be looking for something called authorization.
This is different from authentication because it deals with permissions, rather than identifying your identity. I'll get into how this works in a minute.
To solve your problem, here's what you need to do:
<%= link_to "Edit Profile", edit_user_path(current_user), class: "btn btn-primary btn-xs", if user_signed_in? && current_user == #user %>
I'm guessing you're showing this on a user#show action, which can be invoked using the following code:
#app/controllers/users_controller.rb
class UsersController < ApplicationController
def show
#user = User.find params[:id]
end
end
This means that if you have the following routes:
#config/routes.rb
resources :users
you'll have access to #user and current_user. It's important to note that current_user != #user. Although weezing's answer is succinct, it does not validate whether the user is the one which owns the page authorized; just that the user is authenticated
Thus, you have several specifications:
You need to know if the user is actually logged in
You need to make sure your logged-in user has the authorization to edit the profile (IE is it theirs)
I would highly recommend looking into the use of gems such as CanCanCan or Pundit. I'll show you CanCanCan:
#app/models/ability.rb
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
can :edit, Article, id: user.id
end
end
#app/views/users/show.html.erb
<%= link_to "Edit", edit_user_path(#user) if can? :edit, #user %>
There is a great resource here.
This should work (little bit simpler):
<% if current_user %>
<%= link_to "Edit Profile", edit_user_path(current_user), class: "btn btn-primary btn-xs" %>
<% end %>
I am trying to setup so that users will get a "not authorized" message if they click edit for a profile that is not theirs. This message should of course not appear for admins since admins can edit all profiles. I previously done this on Permission.rb, however I got rid of the file to go with a more basic user roles/authorization.
I don't see how I can implement what I had previously on Permission.rb for my current files. I have tried some solutions but they don't add up. If someone could point me in the right direction that will be great. Also I am doing this all from scratch, user authentication/authorization.
index.html.erb:
<% #users.each do |user| %>
<li>
<% if current_user.admin? || current_user == #user %>
<% end %>
<%= link_to "Edit #{user} profile", user %>
| <%= link_to "delete", user, method: :delete,
data: { confirm: "You sure?"} %>
</li>
<% end %>
Why are you giving the chance for users to edit other peoples profiles?
First, you should have a if statement in your view where you show the link for the edit page. I guess this is showing up on a profile of every user, so i suppose the code in your controller is something like this:
def show
#user = User.find(params[:id])
end
Then in your view you should have something like this:
<% if current_user.admin? || current_user == #user %>
<%= link_to 'Edit Profile' , edit_user_path(#user) %>
<% end %>
There is also a case if someone tries to 'force' their way in, just like trying to type a url www.yourapplication.com/users/6/edit you could write a before_filter method in your controller:
before_filter :check_privileges, only => [:edit, :update]
and then write a method in called check_privileges
def check_privileges
unless current_user.admin? || current_user.id == params[:id]
flash[:warning] = 'not authorized!'
redirect_to root_path
end
end
EDIT: After the questioner edited his code, i'm showing the mistake:
You are putting the end too soon:
<% #users.each do |user| %>
<li>
<%= link_to user.name, user %>
<% if current_user.admin? || current_user == #user %>
<%= link_to "Edit #{user} profile", user %>
| <%= link_to "delete", user, method: :delete,
data: { confirm: "You sure?"} %>
<% end %>
</li>
<% end %>
I have two user models one is
1. User.rb (this is my own authentication system which handles users that just sign up within my site.
Authenticate.rb (this is the OmniAuth authentication for users that want to signup through facebook.
Im having a hard time handling both models.....for example here is the code for my navigation
- if fb_signed_in?
.nav.pull-right.padding-top
%li
- if fb_signed_in?
%li#fat-menu.dropdown
%a.dropdown-toggle{"data-toggle" => "dropdown", :href => "#"}
%span
Signed in as
= fb_current_user.email
%ul.dropdown-menu
%li= link_to "Profile", "#"
%li.divider
%li= link_to "Sign out", leave_path, method: "get"
- else
.nav.pull-right
%span.light_color Already a Member?
= link_to "Sign in", signin_path, class: 'light_color'
%span.light_color or
= link_to "Sign up", signup_path, class: 'light_color'
- else
.nav.pull-right.padding-top
%li
- if signed_in?
%li#fat-menu.dropdown
%a.dropdown-toggle{"data-toggle" => "dropdown", :href => "#"}
%span
Signed in as
= current_user.email
%ul.dropdown-menu
%li= link_to "Profile", "#"
%li.divider
%li= link_to "Sign out", signout_path, method: "get"
- else
.nav.pull-right
%span.light_color Already a Member?
= link_to "Sign in", signin_path, class: 'light_color'
%span.light_color or
= link_to "Sign up", signup_path, class: 'light_color'
So i have defined a fb_signed_in? adn a signed_in? which basically does the same thing though..also with current_user and fb_current_user but heres the code for both
current_user
def current_user
#current_user = #current_user ||
User.find_by_remember_token(cookies[:remember_token])
end
and this is for fb_current_user
def fb_current_user
#fb_current_user ||= Authenticate.find(session[:user_id]) if session[:user_id]
end
so they do do different things....but is there a way to make those two one...since it will be a lot cleaner and im trying to create a comment system that will print users name and gravatar image and im getting confused on how to write the code for that since it uses gravatar_for #user and i would also have to do gravatar_for #authenticate for fb users.
Im basically using Hartl's authentication and trying to integrate Omniauth with it
Please let me know if the question is confusing or unclear and i will try to explain better
Thank You
How about:
def current_user
if session[:user_id]
#current_user ||= Authenticate.find(session[:user_id])
else
#current_user ||= User.find_by_remember_token(cookies[:remember_token])
end
end
def signed_in?
current_user.is_a?(User) || current_user.is_a?(Authenticate)
end
Although this may cause problems in other places since you don't know what a current_user is without testing its type.
In my projects I have just one User model which has many Authorizations, where I put the omniauth-related stuff (so current_user is always a User).
From what I understand it would create a security flaw if I were to let my admin boolean in my users model be listed in attr_accessible. However I want a link on my show page that lets existing admin users grant admin privileges to other users. I was wondering how to go about doing this? My code in my show view for a user at the moment includes:
<% if current_user.admin? && #user.admin == false %>
<%= link_to "Make Administrator", '#',
data: { confirm: "Make this user an admin?" }, class: "btn btn-large btn-primary" %>
<% elsif current_user.admin? && #user.admin%>
<%= link_to "Remove Administrator", '#', class: "btn btn-large btn-danger" %>
<% end %>
I'm not entirely sure what to put instead of the '#'? #user.toggle!(:admin) doesn't seem to work so any pointers would be appreciated. Thank you in advance!
First, since this is an action this should be a button, not an link.
<%= button_to user_path(#user), :method => :put ... %>
controller code
def update
if params[:admin]
user.update_attribute(:admin, true)
redirect_to ...
end
...
end
or if you prefer to keep your logic in the model
def update
...
if params[:admin]
#user.make_admin
end
...
end
model code
def make_admin
self.update_column(:admin, true)
end