Rails App Single Sign In for Multiple Organization - ruby-on-rails

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.

Related

Rails multi tenant app

I'm creating a multi tenant app that something like project management software.
In my structure, there is a User table that excluded from multi tenant.
User comes my sign-up page, fills the subdomain field called Company then I create a schema for this user. So, they can access their account as companyname.example.com. Everything is okay so far.
I also have an Account table to store subdomains with a creator user.
Now, I also created a table for Account permissions. This table includes Account_id and user_id. I did something like that because, user could join more than one Company with same email address.
Conclusion;
User table
Account table
Account_permissions (to check when someone try to login to specific company. Because, they have more then one company.)
Does this make sense ? Do you have any idea in this case ?

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.

rails 3 - devise block user to login

i have something in mind, i have some user types, Building owner, building manager.
I want to create user as building manager, but i dont want they have access to login system. this user are only for some selectbox in my website, but i need to show them in my user index page.
what i think i can do is create normal user and with a before_save i create a new data in another table.
In a request i need to be able to setup in my building form more than one building manager. maybe the best are with nested form.. I think i will need to add building id to my user table. maybe they can be assigned more than one building.
for now, my db structure are like this :
table users with user data (username, password, email, first and last name, phone)
table usertype have userid, typename and accesslvl
But this problem give me some managing problem. They will not be associated with user data.
How can i resolve this? Does Device can block some user? I searched in the Devise docs, but nothing found.
Thanks for your help.
There is an approach where admin users can approve other user accounts for login. You could use a similar approach but programmatically approve the accounts you actually want to allow logins for. Details are here:
https://github.com/plataformatec/devise/wiki/How-To:-Require-admin-to-activate-account-before-sign_in

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