Multi tenancy ASP.NET core - authentication

I'm trying to build ASP.NET core api where I have a few group of users. These groups have a common database, but from there they can only see the records assigned to them.
For example the user XYZ calling the controller returning the values from the Products table sees only those that were assigned to his group. And the same when he adds a new Product, only the users of his group see it, and other groups do not know about the existence of this Product.
I would like to ask you to explain to me how to do it in ASP.NET core, what libraries I could use, because unfortunately I don't know how to do it.
Thank you in advance for your help.

I don't think you need to search for a library or a framework to build this out, you can do the implementation as follows,
Create a table that reads as ProductPermissions
Make an entry for recordid, groupid, roleid in this table
After a user is assigned a group, the relevant tables should have the values like UserDetails, UserGroups, UserRoles etc
When I want to see the list of products that are accessible to me, I make a request to the GetProducts API.
The API gets my userid from the authentication process, roles and group ids
Now, you have to join the products table and the ProductPermissions table with the keys and filter by the groupid that I have been assigned.
The same logic applies for all the entity operations that I do, any action will be validated against the ProductPermissions table.
Note
In order to get a generic table than redundant ProductPermissions, you can have the table as EntityPermissions and then have the entityId (ex: Product, Category etc) as a column and that will be used a filter during joining so that you have a single table for all entities.

Related

Laravel - HasManyThrough in a different way

In the laravel docu is the following example for has-many-through relationship: Country has many posts through user.
But in my case i need something like this:
User has many roles through customer.
I would like to have the has-many-through relationship from user to role.
Is there a way to get it working this way?
EDIT
I solved my problem with a collection method:
public function roles() {
$roles = $this->hasMany('SC\Customer')->get()->each(function($item) {
return $item->role();
});
return $roles;
}
It all depends on what you're trying to accomplish.
In most cases where someone needs to define roles, creating a separate pivot table that joins tables would be a good way to do it.
Luckily, Laravel's documentation covers this pretty well, you will likely find the answer in this section: http://laravel.com/docs/5.1/eloquent-relationships#many-to-many
Keep reading through that section and all the way down, Taylor goes deeper into the subject and various solutions for different scenarios..
Let's say you have many users and many roles (admin, user, moderator) etc. Many of these users can have different roles and perhaps other attributes, such as if they are a customer or not. You start by creating the user, roles tables (or whatever else needed).
You can then create a joining pivot table, let's say role_user. In it, you can specify foreign keys like user_id which represents id from the user table and role_id which represents id from the role table.
By specifying the foreign keys, you attach a user to a role and then to whatever attribute you would like in another column. So if you have another column in the pivot table that is "customer", which can 1/0 (is customer / is not customer) or maybe you want to add another foreign key which can be customer_id that represents id column in a customer table.
It all depends on what you're trying to accomplish, but it's easy to get snowed in. Using a UML software to model it all out before actually coding to get a abstract overview, could be a good idea. I would recommend StarUML.
Then in your User model you can just bind them by specifying the relationships, something like this:
return $this->belongsToMany('App\Role')->withPivot('column1', 'column2');

Database design relations in User and Profile

I'm designing a web application for a school. So far, I'm stuck with the database which has these tables:
users
id
username
password
profile
user_id (FK)
name
last_name
sex
group_id (FK)
(other basic information)
... And other tables irrelevant now, like events, comitees, groups and so on.
So, the users table stores basic information about the login, and the profiles table stores all the personal data about the user.
Now, the *group_id* column in the profile table has a foreign key that references the ID column of the group in which the user is currently enrolled, in the groups table. A user can only be enrolled in one group at once, so there's no need for any additional tables.
The thing is that it doesn't make much sense to me declaring a relation like group HAS MANY profiles. Instead, the relation should be group HAS MANY users, but then, I would have to put a *group_id* column on the users table, which doesn't really fit in, since the users table only stores auth information.
On the other side, I would like to list all the users enrolled in a group using an ORM and getting the a users collection and not profiles. The way I see it, is that the users table is like the 'parent' and the profiles table extends the users table.
The same problem would occur when setting attendances for events. Should I reference the profile as a foreign key in the events_attendance table? Or should I reference the user ID?
Of course both solutions could be implemented and work, but which of them is the best choice?
I have dug a little and found that both solutions would comply with 3NF, so in theory, would be correct, but I'm having a hard time designing the right way my database.
This is a question of your own conventions. You need to decide what is the main entity, right after that you can easiy find a proper solution. Both ways are good, but if you think of User as of the main entity while Profile is a property then you should put GroupId into User, otherwise, if you mean User and Profile as a single entity, you can leave GroupId in Profile, and by this you're not saying group HAS MANY profiles but group HAS MANY users.
By setting a proper one-to-one relation (User-Profile) you can force your data integrity good enough.

Table with user activities - design issue

On my site user can make some items and those items goes in Items table.
Users can also follow each other and those data I store in Followings table.
Now I need one table that keep track of user activities, so I have created:
Users{UserId, Username, FirstName, LastName}
Items{ItemId, Title, CreatedByUserId}
Activity{ActivityId, ActivityTypeId, UserId, ItemId}
Here ItemId can be or ItemId from Items table or UserId from Users table.
Is this design good or there is better approach to do this?
Edit: I have added table structures. The point is that I wan't to add record to that Activity table every time when user create item or start to follow some user. So I can always track what user did on the site.
Here ItemId can be or ItemId from Items table or UserId from Users table.
This will prevent the DBMS from enforcing the foreign key. If you go down that route, better separate these fields (so you can make foreign keys towards their respective tables) and use a CHECK to ensure exactly one of them is non-NULL:
CHECK (
(ITEM_ID IS NOT NULL AND FOLLOWED_USER_ID IS NULL)
OR (ITEM_ID IS NULL AND FOLLOWED_USER_ID IS NOT NULL)
)
The ACTIVITY PK is crafted so it is easy to query for a "timeline" of a specific user and is friendly to clustering.
(You may or may not need ACTIVITY.TYPE depending on what exactly you want to track.)
The alternative would be to have a separate table for each kind of activity:
(And you could add a TYPE field in FOLLOW_ACTIVITY to distinguish between "follow" and "unfollow".)
Another alternative would be to inherit users and items from a common parent "class" and then link to that class:
This design is probably an overkill in this case, but could be useful if you later add many other kinds of objects that could be tracked.
Items{ItemID,descr,UserIDCreator,date-time}
User{UserID,descr}
Followings{UserIDFollowed,UserIDFollower,date-time}
now if you wont all items created by eser use user code on items
the same on followings I add date-time for chrono select
You can create atriggered table or a view this depends on cardinality of data
If the same object can be share between users
Items{ItemID,descr,}
UserItems{UserID,descr,ItemId,date-time}
User{UserID,descr}
Followings{UserIDFollowed,UserIDFollower,date-time}
I hope to be useful

Associate users and roles added to ASPNET SQL Database tables with existing user information

I have added a series of ASPNET database tables for roles, user and membership management to my existing SQL database using aspnet_regsql.exe.
There is already a user table in the existing database which contains information (ID, Name, Address, Postcode, etc) for a number of users. What I want to achieve to associate the new aspnet_Users table with the existing user table.
Is there any option or options for recommendation please? Thanks
Cheers,
Alex
The UserKey, called UserId in the ASPnet membership tables, is the GUID which identifies a user. You can add a UserKey column to your Users table and then start doing dangerous things like:
select *
from Users as U inner join
aspnet_Users as aU on aU.UserId = U.UserKey inner join
aspnet_Membership as aM on aM.UserId = aU.UserId
where U.UserId = #UserId
No warranty, expressed or implied, is provided by Microsoft (or me) if you want to fiddle about directly in their tables.
We had a similar situation on a project I worked on a couple years ago. What we ended up doing was storing the primary key of the related user record from the external user table as a Profile Property of the ASPNET Membership model.
The benefit was that we didn't have to change anything about the schema of the external database to create the relationship and we could use the built in ASPNET Membership profile objects to easily obtain the related key from within the web code-behinds.
The initial population of this profile property was accomplished via a utility we wrote specifically for the task using ASPNET Membership Profile objects and was made easier by the fact that both our Membership setup and external table stored the email address of the user making it the key for the one time task.
The downside of this approach is that the ASPNET Membership Profile table is very much NOT denormalized (or realy normalized for that matter). It stores the Profile Properties as either xml data or serialized binary. In older versions it was serialized with the property names stored as names and character position of a single value string containing all values. This makes it hard (if not impracticle) to write queries, joins, etc from the aspect of your external table.
For us this wasn't a big deal because we were only working with the external user data on a case by case basis from the website. So, grabbing the key from the ASPNET profile using built objects and then looking it up in the external database was easy.
If your project is going to do a lot of relational queries or batch processes then I would probably recommend instead storing the ASPNET UserId GUID as a foriegn key in your external user table or if emails are going to be unique using those.

use of views for validation of an incorrect login-id or an unidentified user

I read this on msdn:
Views let different users to see data in different ways, even when they are using the same
data at the same time. This is especially useful when users who have many different interests and skill levels share the same database.
For example, a view can be created that retrieves only the data for the customers with whom an account manager deals. The view can determine which data to retrieve based on the login ID of the account manager who uses the view.
My question:
For the above example , i would have to have a column named Userid/LoginId on my table on which the view is created so that i can apply a check option in the view for this column. and then if a user with a name not in that column tries to enter data , then he/she is blocked.
Yes, you are right. You should
add a column with the user's login or database user name (say you call it username),
each row should have username populated with the login or database name of the person who is allowed to see that row
you can then build a view where you use the builtin functions SUSER_SNAME() (for logins) or USER_NAME (for database names) in your WHERE clause to filter only the rows the user is allowed to see
See Granting Row-Level Permissions in SQL Server (ADO.NET).
You don't have to add a column to the table: it could be more appropriate to instead add a new table to model the relationship.
There's a deisgn rule of thumb that states a table should model an entity or a relationship but not both. Let's say the table in question models the companies a customer owns (i.e. an entity table) and the business rule states the the account manager can only see companies relating to customers he looks after.
Is account manager an attribute of a company? No, so account_manager should not be a column (attribute) in the Companies table.
Is there a direct relationship between account_manager and a company? No, so a relationship table between is not due here (because the relationship is indirect).
Rather, the direct relationships are between account manager and customer, and between customer and company respectively. There should be two tables whose sole purpose is to model these relationships.