Giving admin different fields to edit - ruby-on-rails

My app has Users and it has Chefs. A user can be a chef and a chef can be a user. Chefs have the ability to create meals, and get paid for there meals, users do not have this ability. A user can become a chef if they request and are approved.
The plan is to have one User model with a boolean field for being a chef. If the chef field is true, the chef will have more functionality than the normal user, such as creating a meal and getting paid for the meal. Where I am confused is how I structure the models so that only a chef can create a meal.
Do I create roles? Such as the post below is suggesting, or do I create two separate models one for Chefs and one for Users. My thought is that I have only one model so people do not have to sign up for two different accounts.
Rails model structure for users, or is there another alternative.
Thoughts/Advice?

I'd strongly suggest checking out pundit which will allow you to run permissions based on settings for a given user. For example, if you want to allow a User with a property chef set to true, you could set up your MealPolicy#create to check for user.chef?

Related

Single model reading and writing to several tables in Rails

When registering to my website, users have to specify which company or group they are working for and then all the users are placed in one db table called users. I was wondering if it's possible to create a new table for every single company that registers and then put all users from that company to that one specific table while still having a single user model and a single controller.
I think you need multi-tenant application.
Here Each company/group can act as a tenant - all users are members of the tenant.
A simple library for this purpose is Milia
Please check the documentation and use accordingly.
It will save all companies users to the same table - But while retrieving apply the scope to find users of a particular tenant.
You don't need to create a table for each company. You need to create tables called Companies and Users that are in relation with each other. So User belongs_to company. Then when you are creating a user you pass company_id to that user. You can read more about it here: http://guides.rubyonrails.org/association_basics.html

Rails App Single Sign In for Multiple Organization

Background
Devise User contain the organization_id as association belongs_to Organization.
Currently sign in url for user in Rails App is
http://localhost:3000/users/organizations/1/sign_in
Above Url help me to find the user on basis of username & organization while sign_in session.
User Model validates username unique in scope of organization.
Need to achieve
http://localhost:3000/users/sign_in
As Sign in Url for the all organization.
Current sign in url is Org dependent after acheiving above it will be converted to organization independent.
Can any one suggest a possible solution, which allow me to create the multiple user having same username in different organization, so on sign in it allows user to go their respective organization.
Other solution are also Welcome.
I assume that you have multiple organization and you want to separate data between them. If that is the case you may want to consider multi-tenancy. Simple implementation of that is acts_as_tenant gem.
Than you simply scope that "membership" that would contain your username for that particular organization. records scoped with organization will have default scope on organization_id, so they can duplicate everything else and stay "clean"
Maybe not the fastest setup, but if you want to have multiple organizations - the easiest I have tried.

How to remember the organization a user is logged in for? Switching between organizations

Background:
User and Organization have a many-to-many relationship through Relationship. So a user can be part of multiple organizations.
But a user can only be logged in for 1 organization.
Therefore the user has a screen where he can switch between the organizations he belongs to.
Also, user has a default organization, which is the organization the user initially logs in for. This is implemented using a has-one through relationship.
How to know/remember which organization a user is currently logged in for?
Now I'm a bit in a pickle how to implement how the app should know/remember which organization a user is currently logged in for. I see three options and am hoping for advice which should work best:
An additional column in the User db that stores the id of the organization (or relationship?) for which the user currently is logged in. A helper method logged_in_for could then find the organization based on the value in that column and return the organization the user is logged in for. Implementation using a db column also enables validation so that a user can't set the organization it is logged in for to an organization it is not even part of.
Use a cookie: session[:logged_in_for] that defines/sets the organization the user is currently logged in for. However, 1) I have doubts whether this is secure (not sure why), 2) I think the first option facilitates validation better, 3) I also don't think this would work in combination with the log in "remember me" option?
Implement an additional has-one through relationship that defines the organization a user is logged in for. This is basically an extension of the first option that adds a relationship. Since I already have so many relationships I don't prefer this option. Or is there no way around this addition for the first option?
Is the first option indeed an effective way to know/remember which organization a user is currently logged in for?
It really depends on which experience you're looking to create for the end user. In your cases:
This will allow remembering of organization between logins, which in your application, can be useful or complete non-sense. If indeed it's useful to remember an organization (i.e, the logistics of user choosing an organization after login is non-frequent), then this could create a better user experience.
session is secure, and you can use it like a hash and it would not collide with other features in your app (unless you use the same key). This case is suited for your application when user should always choose an organization after login, and thus it should be session based.
Ref: http://guides.rubyonrails.org/security.html
Like you mentioned, this is non-ideal, as you already know.
You can store the information in sessions hash, but not use cookie store, instead use Active Record store

Rails: complicated design choice: polymorphism? STI?

I have been trying different techniques while designing this application, which to me is very complicated as there are many solutions to chose from. Deciding which of these solutions is the best has become my full time job for the last few weeks.
Background:
I have a User model which contains some very basic authentication functionality. The application will have three different types of users; admins, buyers, and sellers. The user type will be determined during sign up, where a check box will ask if the user is a seller. If the box is checked, the user is a seller, and if the box is unchecked, it's assumed their just a buyer. I would rather not have a drop down menu to select the user type (Buyer, Seller). Easy so far.
Details:
Sellers have a profile, and users who visit the site will be able to browse through the different sellers and view their profile. Buyers do not have a profile, and should not be listed on the site for users to see. If that's not complicated enough, buyers should have the option to change their account type and become a seller. Similarly, sellers can change their account type and "deactivate" their seller account, removing them from the list of sellers.
Design options:
Single table inheritance:
What I came up with when attempting to implement this using STI was suboptimal. I was faced with two options: a messy controller, which made the decision of what type of user to create based on the check box mentioned above (one controller - UsersController), or two different sign up forms that were identical (two controllers - BuyersController, SellersController).
has_one or "has_none" Profile association:
class User < ActiveRecord::Base
has_one :profile # only if the user_type or role is "seller"
end
class Profile < ActiveRecord::Base
belongs_to :user
end
Here I would use something like CanCan or declarative_authorization, and let the user chose his/her role via the check box mentioned above. This introduces a security risk, as there will be an admin role and I don't want this to be open for mass assignment.
I guess either way you look at it I'll have a messy controller with conditionals on how to create the user. Unless I choose to have two check boxes ("I am a seller," and "I am a buyer"), but this seems redundant. It also seems as though whichever design I choose, I'll be faced with some hackish solutions.
Maybe introduce some model that lies between the User and user type?
Any opinions?
I don't really think you need either STI or Polymorphism. A single user model should suffice. I would add three methods to your user model (administrator?, buyer?, seller?) and also add scopes that will return only buyers, only sellers, or only admins.
In your case, it sounds like you have a real minimal number of roles for users (2 now, expanding to 3 with admins). I would probably use the technique Ryan discusses in the "Embedded Associations" Railscast.
I've done something very similar in my latest project, and then used CanCan (in my case, the 2.0 alpha branch, as I find it simpler) on top of that. Your ability class would look something like this (in 2.0 syntax, but you can do the same with 1.x, I'm sure)
class Ability
include CanCan::Ability
def initialize(user)
if user.seller?
can :create, :profile
else
...
end
end
end
So far it sounds like you have a flag that indicates their user type, or a column with type string, etc.
You haven't indicated any behavior that depends on this--not showing up in listings etc. can be handled with scopes. Admin can be handled with a flag.
I don't see the problem yet, at least not a problem of a few weeks scope.
A 3rd option.
...buyers should have the option to change their account type and become
a seller. Similarly, sellers can change their account type and
"deactivate" their seller account, removing them from the list of
sellers.
Have you considered not allowing switching of accounts? If a buyer wants to become a seller, then they create a new "seller" account. It would work the same for seller to buyer. It would mean having 2 controllers for the signup, etc. but it would keep the separation you're looking for. If the two must be mutually exclusive you could do a rudimentary email check to verify the user doesn't already have an account and if they do, they must de-activate the existing account prior to creating a new one.

Best approach to a customer portal in ASP.NET MVC

The problem: client needs a website to serve 10+ customers, each customer has 5-10 people they wish to grant access using login & user name, once "logged in" the user can download files specific to their company.
The files will be uploaded to a directory under the customer name, and displayed as a list. Currently using membership for all of the users, it's just the "by customer" segmentation I'm wondering about. the question being under ASP.NET MVC what is the cleanest or simplest approach to solving the customer segmentation, trying to avoid customer membership provider so was going to use the roles to assign customer group.
Thoughts appreciated.
In the past I tried to avoid the membership and role providers as well since I don't like the way they are implemented. So just use the old school way. Create two tables on your db, one stores the customers the other the users.
Just build a simple relationship like: User n ----- 1 Customer
Now if a user logs in first authenticate him/her against the User table, then authorize on the Customer table.
The provide the right downloads, just create an additional table File, which has a n:1 relationship to the Customer table (like the User table).

Resources