We're building an application for product support. The idea is to have multiple subdomains, each for supporting other organizations products. We call this Account - each account is tied to exactly one subdomain.
Users also have roles - but, user can have one role on account1, and other role on account2.
Basically, there are two problems:
1) many validations are based on the role current user has. Since it depends on current_account (which is session data), I cannot do these kinds of validations in the model. This leads me to some ugly controller code (ugly, in the sense that it really feels out of place). I thought of storing current_account after in the model class variable, but I read that this is not thread safe. Any recommendations?
2) almost every database record is specific to the current account; so, almost every table should have an account_id column and the model should have a belongs_to account association. I want to avoid that. The first (obvious) thing is to have a seperate database for every account, but
a) there are shared tables
b) the boss says this solution is unacceptable (there will be many accounts, with relatively low number of users). Is there a third way?
If anyone runs into similar problem:
The problem described is called multitenancy; understanding default_scope should help. Also, there is the multitenant gem which worked for me nicely.
Related
If I want to build a Rails app that has two different types of users, let's say one type is called players and the other one is owners, what is the best and most efficient approach to modeling the app?
Things to take into account:
There should only be one Login, but different Registration forms that Owners/Players can use.
Owners can have access to a control panel but Players cannot.
Owners cannot share any of Players capabilities, but both need to be able to perform Login/Registration.
I am not using Devise, so please do not suggest it.
Different Approaches I've considered:
Using cancancan gem, but it does not really seem to meet my needs in the sense that I am not looking to create a user/admin hierarchical approach but rather a if you're a Player, then you can see these pages and perform these actions but Owners cannot and vice versa. Almost like splitting the app in two. cancancan seems that it would treat Owners as "Players with extra privileges", not different privileges entirely.
Creating separate models with separate login and registration forms, which seems like a disaster waiting to happen. One small mixup between a Players table and the Owners table, especially with the primary keys, and that will be a world of trouble where people could end up logging in to the wrong accounts.
Creating a polymorphic or has_one relation toward an Account model, which so far, seems like the best way to probably go about it. If I created a polymorphic Account model, I can store different types of Players/Owners, but how could I compare login credentials against all types?
I had been trying to find something on this matter regarding how to map this out and was surprised to not find an information on how to do this without using Devise. If anyone has any good links they can point me to that also address this matter (without Devise), please leave them in your answer! Thanks.
I'd suggest one User class with a type attribute that determines whether the user is a Player or an Owner (single table inheritance). This way you keep the registration logic in one place but can customize the forms depending on the user's class.
There must be alternatives to cancancan that help with what you want to do, or you can implement helpers yourself:
def can_access_control_panel?
current_user.is_a?(Owner)
end
You have to have a way to separate one user from another. One way is to add an attribute to the User table so you can call current_user.role and it will return "owner" or return "player".
I have used Pundit gem in the past. It lets you define which controller actions the current user is allowed to access. So as you create resources for your application, you can add a policy that specifies who is allowed to that given resource. This is the repo to the application.
This answer might help you.
I'm trying to build a rails app similar to a CRM, where I have users, and each use has many "clients".
Initially, I created a model for a user and one for client, but while writing unit tests I realized these two are very much the same.
So my question is: was my original design decision to model them separately correct? Or is there a better way of reusing the code, even though I don't foresee Clients ever being able to actually log into the system?
I've looked at similar questions but they all apply to different user types and roles. In this case, Clients only exist as a model and will never actually BE users.
In any CRM application, User and Client there are similarities and differences between them. Let's put some details
The Similarities
Both of Users and Clients share various attributes, especially those related to personal information (name, contact info, ...etc.)
Both (mostly) represent one and only one person who has a relation to the system. One obvious exception are system users.
The Differences
A user accesses the system. This implies security needs such as authentication, identification and authorization, which in turn implies some validation (passwords, certificates, ...etc)
In CRM, a Client usually has various relationships such as with Account, Company, Team, Account Manager, and others, a User doesn't. Even though this is not handled by the model, but you might choose to do some model-level validations on some fields
Therefore, the choice of separating Users and Clients in two different models, combining them, or subclassing from a parent is a choice based on your actual need. There are some systems (such as OpenERP, if I remember correctly) treat Client and User in the same manner, while defining an is_system_user property. Personally I'd choose to separate them for the differences mentioned and for security reasons. If you're not sure about your need, it's safer (while not DRY'er) to separate them.
Maybe you should give a type to users (by creating a Type model and making a has_many/belongs_to ActiveRecord association for example): so a user can be a client or anything else you want.
Then, you can manage user permissions with cancan (a very great gem), depending of their type.
Question
I have a User model with authorisation and authentication logic built.
Now I realise I have three different types of users. I want to store different information about each of them.
What is the best way to handle this in Rails?
Thoughts based on current reading
I've looked at STI but from what I've read feel it is inappropriate because I'll end up with a lot of NULL fields in my database.
Ideally I'd like to not duplicate the authentication / authorisation logic for each of the three user types.
Each user will also have different functionality within the application.
You can try using polymorphic associations and creating table users with data that all types of users have and putting other data in seperate tables. Railscast epizode covering this topic.
There are lots of ways to do this. Here's one approach:
Instead of thinking of different types of users, you could think of roles that a user has.
For example, if a user could be a butcher, baker, or candlestick maker, you could have four tables: users, butchers, bakers, candlestick_makers. The latter three role tables each have a user_id column; they "belong to" the user.
If you need to enforce that a particular user has only one role, you will have to do that in the application (since this database schema would allow multiple roles for a single user).
This method is good if there is a lot of stuff that would belong in those role tables. If not, leaving some NULL columns on the users table probably won't kill you.
I'm building a Rails app that has Etsy.com style functionality. In other words, it's like a mall. There are many buyers and many sellers.
I'm torn about how to model the sellers. Key facts:
There won't be many sellers. Perhaps less than 20 sellers in total.
There will be many buyers. Hopefully many thousands :)
I already have a standard user model in place with account creation and roles.
I've created a 'role' of 'seller', which the admin will manually apply to the proper users. Since we'll have very few sellers, this is not an issue.
I'm considering two approaches:
(1) Create a 'store' model, which will contain all the relevant store information. Products would :belong_to :store, rather than belonging to the seller. The relationship between the user and store models would be: user :has_one store. My main problem with this is that I've always found has_one associations to be a little funky, and I usually try to avoid them. The app is fairly complex, and I'm worried about running into a cascade of problems connected to the has_one association as I get further along into development.
(2) Simply include the relevant 'store' information as part of the user model. But in this case, the store-related db columns would only apply to a very small percentage of users since very few users will also be sellers. I'm not sure if this is a valid concern or not.
It's very possible that I'm thinking about this incorrectly. I appreciate any thoughts.
Thanks.
I would definitely use a relationship between a store and a user. This provides a lot more flexibility and is a much cleaner data design.
I have never had any issues using any of the basic associations in Rails/Active Record.
What do you mean by "funky"?
I have the need for a user and a contacts model, both have common attributes like first name, last name, sex etc. It thus seemed reasonable to create a model individual and have user and contacts inherit from that model.
class Individual < ActiveRecord::Base
end
class User < Individual
end
class Contact < Individual
end
My question is, what type of security problems would I open up by having the above setup? I'm using authlogic and all of its required fields are within the individuals table. The above method seems easy, and yet I'm worried I may open myself up to unforeseen security issues, any thoughts? Just to be clear a user can login and a user will have many contacts.
Using STI doesn't open you up to any new security issues as they are orthogonal..
However, STI may upset your DBAs as you will have null fields within that table. (attributes that are present in one sub classed model and not the other)
As from the design stand point, what are you achieving by having such a model relationship. If the only distinction between a User and a Contact is that a User can log in and can have numerous contacts then you can simply have an individual that can have many contacts (which map to Individuals) AND can possibly have login credentials
Remember that a contact may be shared by numerous individuals which stipulates either a has_and_belongs_to_many or has_many :through
hth
Conceptually I wouldn't mix them. The underlying intent/function of each model is substantially different, so the fact that they look similar in shape is a red-herring.
Potentially you'd run into a problem where someone could figure out a way to authenticate with a Contact, although it doesn't seem very likely, given its unlikely that you assign a username to a contact, or the secret hash stuff. But it would be possible if there is a bug in AuthLogic, or if someone tried hard enough to hack your setup and you weren't anal about protecting against injection attacks.
Also, there are performance reasons to not do this if your app grows a lot. Basically, I think its a bad design to have these two models rely on the same table for fairly superficial reasons.