Best approach to a customer portal in ASP.NET MVC - 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).

Related

Multiple users authenticating and authorizing

I am a bit confused with Authorizing and Authenticating at the moment.
First I need to tell you about my project. It will have two main models: Users and Pros. Users are people requesting a service. Pros are people offering services. Pros can have very different jobs and thus very different type of data stored in my project. I plan to have different models for different types of jobs held by the Pros (photographers, wedding planners..). Those models will have relationships and "own" different other models (images added with paperclip, links to websites...).
I guess I need to use gems for both Authentication and Authorizing (I have Devise and Pundit in mind)
now my questions:
I would like to have all Users and Pros login through the same form.
I guess this is very a Devise thing. Though after having read a bit about Devise, it seems there is a login for each of the Models. but this thread mentions Devise "groups"
https://gorails.com/forum/devise-with-multiple-user-models-with-single-login-form
Will it definitely solve my problem of a single form login ?
I would like to have each of the Pros submodels show a preview of their records to any type of users or even guests. But when a Pro is logged in they can access to an extended profile view with more information (all personnal data that can be changed, price requests from users, etc...). Can you confirm this is Pundit job here ?
Pundit is the perfect choice for achieving your second point. You can limit certain actions (such as edit/update) to be achievable only by the Pro who owns the account. The code for those actions in the ProPolicy would look something like:
def edit?
update?
end
def update?
record.pro == user
end
In terms of your question about multiple user model authentication using Devise, can you explain why you are set on having just one login form for both users? You could have a dropdown on the login button where the user can select if he is a normal User or a Pro. Or you could even have a checkbox/select on the form where they select which type of login they want to use.
If not, then you will somehow have to check your database to see if the login exists in either the Pro or User tables. However, I suppose that would mean that you cannot have both a Pro and a User account using the same email.

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

Roles based authorization in MVC4

I am new to MVC and want to understand the authentication mechanism in MVC
I have these tables in SQL, Users table, Roles table and UserRoles table which maps user id column to role id column. Now as soon as I add an attribute Authorize(Roles = "Customer") I want the access to be given only to the users having customer priviliges. Now what is is that I have to do to create a link between these two. I am looking for a step by step explanation or a link which points me to do this exactly, as I found a number of articles googling out on this and was unable to find the matching one.
Thanks in advance.
If you take the out of the box MVC template, you don't need to do anything to enforce this behavior. A database will be created for you as soon as you launch your application with a number of tables (Users, roles, mapping between users and roles, ...). Check your web.config for the connection string.
The only thing for you to do is to populate the ROLES table and then match those entries with the Authorize attribute in code. So if you have a role named "Admin" in the database, you can protect your actions and controllers with following code:
[Authorize(Roles="Administrators")]
You could also take it further to limit access by users but I wouldn't consider that as a best practice. Next, create a user in the UI and then match this user to a role you specified in the DB. Login as this user and you'll notice you have access to the restricted action/controller.
For more information, he best articles are those from Microsoft themselves, like this one.

Securing web application on the data access level

Please consider the following setup:
Multi-tenant webapp.
Tenants create company accounts and company accounts have user accounts under them.
Users have roles, there's a special role "Owner" (the user who created the company account).
I'd like to have users to edit other user accounts (some admin tasks), but two conditions must be met:
Noone may edit owner's data (except for owner, when he's editing his own profile, and own profile editing is the same user editing).
Users may access user data and edit users only within their company account.
The app uses MVC architecture. Currently I check for those two conditions in the web layer and it works for me, but I have some concerns. If I go with some sort of API or some other type of data consumer, I may "forget" to re-inforce these conditions. Also, there will be other objects in the app with similar functionality requirements and which will have similar restrictions on them, so it's better for me to come up with some sort of pattern which will enforce my restrictions on data access level.
Could anyone recommend some approach worth looking into?
Thanks!
I beleive aspects or interceptors should be able to help you. If you work with objects you should be able to intercept requests containing your business data and check wether your user is allowed to work on it. The interceptor could then stop or proceed the execution.

Resources