users#edit needs to be different depending on who views it - ruby-on-rails

I made a website where people can subscribe to a service.
Currently, users#edit is for the users themselves to edit information like passwords.
However, I want admins to be able to visit the edit page to be able to edit things like expiry_date. Obviously users themselves can't be allowed to edit their own expiry date for the subscription, so I want to limit this only to admins. I'm thinking something like using <%= if current_user.admin? %> and putting the expiry date form fields into there is good enough, but am I mistaken?

No, you're right. To make it simple, display the form field only if current_user is admin.
Create a method admin? in you application_helper.
def admin?
current_user.admin?
end
And then in your form partial, add
<% if admin? %>
<!-- display the field -->
<% end %>
However if you run into a situation where a lot of actions require only admins to view, I would suggest you to create a separate namespace for admins.
For more, see http://guides.rubyonrails.org/routing.html#controller-namespaces-and-routing

Related

I want to change the page view based on whether the user is an admin

In rails, I have a model for users which has a flag for admins (yes, no). If the logged_in user is an admin, I'd like to be able to show different elements of the page using erb.
I'm currently doing this with logg in users vs non logged in users using this code
<% if current_user %>
But how would I specify if current_user is admin in the erb?
Or, is erb the best place to do this since it is exposed to the browser? If not, any suggestions for other ways to accomplish this in the model or controller?
I'm not using Devise for the user authentication currently.
When you say they have a flag, does that mean they have an attribute called admin?
If so, any model with a boolean in rails, you can check with:
<% if current_user.admin? %>
If there is another way of determining whether the user is an admin or not, you'll need to add an admin? method to the user class, which you can use to determine their status in the view.
You can use user is_admin column name in views.
<% if current_user.is_admin? %>

Show view for different Users types

I am planning an application with a User model + different User subtypes (such as Students, Teachers, ...) with a dedicated model for each.
I am planning to authenticate on Users level directly in rails, with no specific gem.
My problem is about handling the Users Show view file:
should I show the users directly in the Show file of the User
controller (adding a lot of conditions in my view file, depending of
the User subtype) or
should I use the User show controller action as a gateway
redirecting the a controller dedicated to each subtype, ...then having a
more straightforward show view.
Your view should be almost free of that kind of logic. That would break MVC and lower the maintainability of the app. You should at least leave that to the controller, something like:
def show
render proper_view_by_user
end
private
def proper_view_by_user
# Define this user_type on your own
# on devise you'd do something like current_user.class_name
switch user_type
when 'Admin' then
'admins_show' # template found in your views folder
when 'NormalUser' then
'normal_show'
else
'normal_show'
end
end
Unless this a learning project, really consider using devise and not rolling your own auth system. Read this.
One way to do this is to use partials, and then render the partial that has the same name as the user subtype:
<%# users/show.html.erb %>
<%= render partial: user.user_subtype %>
<%# users/_admin.html.erb %>
<h1>Admin</h1>
<%# users/_student.html.erb %>
<h1>Student</h1>
<%# users/_teacher.html.erb %>
<h1>Teacher</h1>
As an aside, if you're dealing with access levels I would highly recommend using the Pundit gem. It will save you a lot of headaches.

Rails issues with authentication

I am building my first app using rails and i am struggling to give an account to each user. Its a simple app where a user creates a post and saves it. this post can be seen on index page. Until now we are ok. when i sign out, i register a new user and i log in. when i go to the index page, i can see what other user has saved. I want to have a private index page for each user where no one can see what users are saving in their app. I am using Gem 'Device" to authenticate my app, but i don't know how to make private their account? any ideas?
You have implemented authentication. Now you need to build authorization.
You have to define what data can be accessed by user.
Take a look at:
CanCanCan
With devise authentication technique, after logging in the user you can write a clean piece of code to render the posts of the logged in user. You can use session data to do it. the current_user helper method returns the model class relating to the signed in user. With devise, it ensures after authentication that, it has the helper methods ready to be used. So, the error with no such user with that id can be avoided.
#web/controller/post_controller.rb
before_filter :authenticate_user!
def list
#posts = current_user.posts
end
And then, use #posts in the list view to render the posts of the logged in user only.
<% #posts.each do |post| do%>
<%= post.content %>
<% end %>

application with multiple "accounts", each containing multiple users

I am trying to build an application with multiple "accounts", each containing multiple users.
I've started with the gem Devise to create user authentication, and I've created Accounts and Preferences MVC's with scaffolding.
The Account model has_one Preferences, and has_many Users
The User model and Preferences model belongs_to my Account model
I've tested these relationships in the console and they seem to work..
What I would like to do, is make sure that when users are logged in, they can only view records associated with their account. From what I've seen, the current_user helper can be used, but I would like to use something like a "current_account".
1. First question is, is there a resource, Gem, method that can help me to create this current_account variable?
2. Second question would be, what do I need to put in my View for this to work? For instance, if a user wants to update his Preferences associated with his account, how would we call this in the _form partial, would if be something like this?
<%= #account.preference.opt_in %>
and if they wanted to see all of the users in the account, would it be something like this?
<% #customer.user.each do |account| %>
<%= user.email %>
<% end %>
Please let me know if I'm overlooking anything major, I've been working on this the last few days.
If I understand correctly, you are looking for a multi-tenancy solution. If so, you don't need to come up with your own solution, as there are well established patterns out there.
You can try the Milia gem, which fits in nicely with devise.

Making sure I got the idea . - Ruby on rails login system

I am currently reading a book, and learning ruby on rails. (Agile Web Development with Rails 4th Edition) .In the book it says how to write a simple product list and display it. I am modifying this idea, to create a user login system.
I am only working on the views now.
So I just need to make sure that my idea is right. My idea is:
The show.html file from the USER model, show data for one user. (given of course its ID)
for example : http://localhost:3000/users/980190974 will give me the html page for the current user right? Now I can allow the user to edit his/her information by using the
<%= link_to 'Edit', edit_user_path(#user) %> link or restrict him from viewing other users by removing the <%= link_to 'Back', users_path %> << that lists all the users from the database. But before the user views his/her details he must login, using his email and password. So by making an html page, that takes 2 strings (username, and password) searches my mySQL database and return the user ID , that I then use to "render" the user's HTML page.
Is my way of thinking correct? Or am I just completely irrelevant on how Ruby on Rails works? O_o
You are heading in the right direction. One thing to point out is that simply removing the link <%= link_to 'Back', users_path %> is not sufficient to avoid other users from accessing the /users path. In the (user) controller you have to use something like:
class UserController < ApplicationController
def index
unless current_user.is_admin
redirect_to user_path(current_user)
return
end
... rest of code here
end
end
where current_user could be a method returning the user object

Resources