Filtering queries by by user and role / scoping data - asp.net-core

I am using ABP Commercial to implement a custom CRM system. I am looking for an example, a best practice, a library, or even a framework for scoping data according to user IDs and roles.
Simple scoping like just showing entities created by a certain user is fairly straightforward. But what about showing increasingly more broad data based on a hierarchy of user roles.
For example, I might have a basic user role that can only see data created by the user in that role. Then, I might have a manager role that can see his own data and all the data created by the basic users he manages. Contemplating any decent size organization, you can see how this hierarchy might get quite deep.
So can anyone tell me whether there is a facility or module within ABP Commercial or ABP Framework to facilitate this kind of pattern or if there is third party best practice, library, or framework that might work in conjunction with my code to realize this functionality?
In the past I have written my own implementations but I am looking for a DDD or clean architecture based solution.
EDIT
A more specific example of what I'm trying to do is to create an extension of the user class and role class or to add additional entities managed by a domain service that would allow for:
users to have a collection of roles they manage and a collection of specific users they manage, and…
roles to have a collection of other roles they manage (think composite pattern)
These relationships would be used to filter all kinds of queries within my application.
Here are some use cases:
return a list of contacts associated with the clients of my direct reports
return a flattened list of all users managed by me or my reports
return the total revenue of all sales made by users managed by me or my reports

Related

Is it possible to add permissions on object at field level

Within the implementation of MDM based on the PIMCORE solution, we wish to segregate data according to user rights. The goal is to restrict access to the attributes of an object according to predefined roles.
The different possibilities were to go through either perspectives or customer views but it is not possible to add more detailed restrictions at the attribute level. The other possibility would be to do specific development in PIMCORE, but this is still a bit expensive.
In your opinion, is there a native way to manage this data segregation in PIMCORE? Or do you have a way to do this on a specific development?
There are the following possibilities:
Custom layouts
Custom Layouts give you the possibility to define different views on data objects for certain users. You can hide certain fields from the admin backend to certain users which is a great way to achieve what you want. The drawback is that this is not suited for "high-security scenarios" as the full data objects are still sent in the background.
So if the data is highly secure it might be readable within the communication streams (https://pimcore.com/docs/6.x/Development_Documentation/Objects/Object_Classes/Class_Settings/Custom_Layouts.html).
Encrypted fields
Maybe you could use encrypted fields to further improve security. A combination of custom layouts and encrypted fields should at least make data unreadable to certain users (https://pimcore.com/docs/6.x/Development_Documentation/Objects/Object_Classes/Data_Types/Others.html). I am not 100% sure, it should be tested.
Workflows
You could use Workflows in order to restrict certain actions on objects depending on the current object state. Workflows have a possibility to fully implement permissions and dissallow certain actions for certain users.
https://pimcore.com/docs/6.x/Development_Documentation/Workflow_Management/Permissions.html
Use Relations
This is probably one of the simplest and best solutions. Create seperate classes for the sensitive data and connect the data objects via Many-To-One or Many-To-Many relationships and restrict access on them. This way you can ensure that certain users never can access or edit the sensitive data.
https://pimcore.com/docs/6.x/Development_Documentation/Objects/Object_Classes/Data_Types/Relation_Types.html

How to protect a specific record

We are trying to write an authorization program to our company.
We've decided to use claim based authorization .
The normal restrictions are pretty easy (Let particular users use particular services ETC) , but I have some kind of special requirement :
I need to filter records of the result set, based on the claim this user have.
For example , I have a service that return a list of people that invest in our company, with details about them and the amount of money they have. Now, an employee shouldn't be able to see other employee details, unless this employee is a direct manager of the employee presented.
This means -> I need the claim attribute to some how effect the result set, and I couldn't find any information online on how to do this.
What you're looking for is usually called fine-grain security, and HERE is one article on doing it with ASP.Net and claims. Also, a search for "asp.net fine grained permissions" will lead you to lots of resources.
This is a pretty involved topic, but it basically involves elegant and effective ways to add filters (e.g. WHERE clauses on SQL queries) to accomplish your row-level application security.

Repository pattern, POCO, ORM and intermediate entities

I am trying to figure out how to address this issue:
I have 3 tables with a many-to-many relationship.
Users *-* Roles *-* Permissions
I use a ORM to obtain data from them.
A method of my business layer must return users per permission, so I return objects with this class:
public class UsersPerPermission
{
public User[] {get;set;}
public Permission {get;set;}
}
But this class does not map to any table in the repository, it is something I generate from the existent tables. Where should this class live?
In other words:
Should I have a IRepository.GetUsersPerPermission()? And then that class should live in the repository.
Or should I have a IBusinessLayer.GetUsersPerPermission()? And then I have to invoke the CRUD methods in the repository?
It makes sense to put it in the business layer only, because the repository should just expose CRUD operations to tables... BUT, in order to execute this operation from the Business layer, I would have to execute several independent queries to get the data and create the 'UserPerPermission' class. In the other hand, if I place it in the repository, I can get that information in one shot using grouping.
Thanks!
PS: What is the name of this intermediate objects? 'transformations'?
In DDD, most entities and value objects should correspond to identified domain concepts that are part of your ubiquitous language. I usually try to limit many-to-many relationships and artificial association objects as much as possible. Eric Evans describes a few techniques allowing that in his book. When I have to create an association object, it must have a meaningful name with regard to the domain, basically I never name it Class1ToClass2.
In your scenario, it's even more artificial since your object :
Redundantly models an association that already exists (indirectly) in the original model.
Has a name that doesn't reflect any particular business concept.
Note that this kind of object wouldn't be useless if we were in the presentation or application layer as it could come in handy to have a structure containing exactly what is displayed on the screen (DTO). But I'm talking about the domain layer here, which should be devoid of such composite objects.
So I wouldn't create a UsersPerPermission class in the first place. If what you want is a list of users and User is an aggregate root, just create a GetUsersByPermission() method in UserRepository. It doesn't mean that you can't have a GetUsersByPermission() method in an application service as well, if it matches a use case of your application (a screen that displays the details of one permission and the list of users with that permission).
I agree with guillaume31 that there is no need to introduce a domain object "UsersPerPermission" to support a single use case.
There are two ways you can implement your use case using existing domain classes "User", "Role" and "Permission".
Solution one:
Assume you have: Permission --> Role --> User
Arrow denotes navigability. A Permission has association to a list of Roles and a Role has association to a list of Users.
I would add a method GetPermittedUsers() : List<User> to the Permission class, which is trivial to implement.
Th UI logic will invoke GetPermissions() of PermissionRepository then call GetPermittedUsers() on each Permission.
I assume that you use a ORM framework like hibernate(Nhibernate) and defines the many-to-many relationships correctly. If you defines eager loading for Role and User from Permission, the ORM will generate a query that joins Permission, Role and User tables together and load everything in one go. If you defines lazy loading for Role and User, you will load a list of Permissions in one query when you call PermissionRepository, and then load all associated Roles and Users in another query. Everything is load from database with up to three queries maximum. This is called a 1+n problem which most ORMs handle properly.
Solution two:
Assume you have: User --> Role --> Permission
Arrow denotes navigability. A User has a list of Roles. A role has a list of Permission.
I'd add getUsersByPermissions(List<long> permissionIds) : List<Users> to the UserRepository, and add getPermissions() : List<Permission> to the User class.
The implementation of the UserRepository need to join the User, Role and Permission tables together in a single query and load everything in one go. Again, most ORMs will handle it correctly.
Once you have a list of Users, you can create a method to build a Map<Permission, List<User>> quite easily.
To be honest, I muck like the solution one. I avoid to write a complicate method to convert a List of Users to to a map of Permission and Users, hence I don't need to worry about where to put this method. However solution one may create cyclic relationship between User, Role and Permission classes if you already have navigability in another direction. Some people don't like cyclic relationship. I think the cyclic relationship is acceptable even necessary sometime if you user cases demand it.
In a similar context I used a query method in a domain service that returns something like an
IEnumerable<KeyValuePair<PermissionName, IEnumerable<Username>>>
By using the KeyValuePair<> I avoided to pollute the domain model with an artificial concept (like UsersPerPermition). Moreover such a structure is immutable.
I didn't used a query method on the repository because, in my context, no entity was coupled with the other. So it wasn't matter for any of the repositories.
However this solution is useful for your GUI, if and only if you modelled correctly the identifiers of your entities (in your example both Permissions and Users are entities).
Indeed if they are shared identifiers that belong to the ubiquitous language that your users understand, they will be enough without further descriptions.
Otherwise you are just building a useful DTO for your GUI. It does not belong to the domain thus you should use the simplest possible thing that works (an ADO.NET query? something even simpler?).
Indeed, in my own scenario both the GUI and the domain used such a service (the GUI showing a preview of an elaboration).
In general, the domain model must mirror the domain expert's language, capturing the knowledge relevant to the bounded context. Everything else must be outside the domain (but most of time can be expressed in terms of the domain's value objects).

What exactly are "tasks" in Yii's RBAC?

I'm diving into RBAC while designing new and rather big/complex site.
I'm trying to figure out if to create a task or simply an operation with biz rule.
Now, I've read most if not all existing documentation. The current documentation says that "a task consists of operations". This wiki article says that the different terms are simply naming conventions and the only limitation that exists is structural one - roles must include tasks (or other roles); tasks should include operations (or other tasks) and operations is the atomic term that is not further composed by other entities.
I've also read the relevant sections in the "Agile web dev..." and "Yii cookbook" books - both do not shed further light on this issue (at least as seen through my glasses).
Lets go to my example where I'll present the question. Actually, lets use an example similar to that demonstrated in most of the documentation resources mentioned above: Lets say I have a blog post and I want/need to have its author be able to "update own post". Now, why should this be a task as commonly demonstrated in the documentation resources and not an operation with a biz rule?
I think that the question above reveals the inclear definition of a "task" (in the RBAC context of course).
Please help me distill a better definition for an RBAC task.
EDIT:
I was suggested the following definitions of the mentioned terms that help conceptualize them in a useful way. In short and in its simplest form: operations are the basic building blocks. They are the material developers work with and only them. Developers compose tasks of and on top of operations. Roles are composed of tasks, like a set of tasks. Roles and tasks are what the site administrators should play with - assign and revoke to users but not operations.
That's a nice way to look and grasp those entities (roles, tasks and operations).
Do you have another option to conceptualize differently? Any comments will be appreciated.
TIA!
Boaz.
I'd say the same as you did in your question edit. A task is simply a composition of operations a user can do that have something in common. So you have for example operations oList, oView, oCreate and oUpdate these are the operation developer assigns to controller actions for access control, where the first two are only read- and the second two have write access to data (that's what they have in common). So you now want to combine those to tasks tInspect and tManage which both hold 2 operations, the first one can list and view and the second one can create and update. Optionally you could make tInspect a sub-task of tManage so a user that has tManage can list, view, update and create but normally you just give his role both tasks.
Regarding the classification of role -> task -> operation, they are essentially the same thing, as you can see in the code they are of class CAuthItem. We name them differently mainly from user point of view.
Operations are only used by developers and they represent the finest level of permission.
Tasks are built on top of operations by developers. They represent the basic building units to be used by RBAC administrators.
Roles are built on top of tasks by administrators and may be assigned to users or user groups.
The above is a recommendation, not requirement. In general, administrators can only see tasks and roles, while developers only care about operations and tasks.
Check this out : http://www.yiiframework.com/forum/index.php/topic/2313-rbac-confusion/page_p_16035#entry16035
if there are two user
1)admin
2)user
so we set role updatePost for update page.
and admin is parent of updatePost so admin can update.
user have updateOwnPost permission.updateOwnPost is parent of updatePost with bizrule.so if bizrule satisfy he can update

designing a restful api: naming URIs, custom headers?

EDIT: I've solved my issues (for now at least).
I've recently been working with the Zendesk REST Api and their use of the custom "X-On-Behalf-Of" header for looking up tickets opened by a particular user got me thinking about Restful Api design choices (in no specific language, more of a how to name URIs question). I've also read this related question on Custom HTTP headers, but it left me with more questions than answers.
Say I have an example restful web service dealing with rental apartment applications where clients use Basic Auth (keep it simple) to authenticate. Define the basic data as such:
Users (can be of type landlord or renter)
Forms (which consist of one or more Document resources and some form meta data like form name and version info)
And then some type of resource corresponding to Rental Applications, which ties together Forms, Applicants (one or more renters), Landlord, and some metadata like status and dates.
I'm struggling to properly model the URIs for the Applications resource in general, and more specifically with respect to a clients role. (assume api root is https://api.example.com/)
How do I allow a Landlord to fetch a list of applications sent to them? My intuition says make a request to "GET /applications" and Basic Auth lets the server know which user to build the list for; likewise "GET /applications" requested by a Renter would return a list of applications they've sent...but I'm not confident this is a solid design in general to mix and match sender vs. recipient lists at the same URI. Should I be thinking about the "/applications" resource differently, and perhaps allowing a hierarchy like "/applications/[USER_IDENTIFIER]" for each user instead?
Also, regardless of my applications URI design, assume a Landlord is able to create an application on behalf of a renter. Is this better accomplished by sending a custom header like "X-Create-On-Behalf-Of: somerenter#example.com" with the PUT/POST creation request? Or should my schema define a field which allows for this alternative scenario.
I'm very much an amateur at this, so I'm open to any criticism of my assumptions/design, as well as any pointers for learning more about designing RESTful api's. Thanks for reading.
I think I've found a solution.
Landlords and Renters are really just subclasses of the same object, which I'll call Party (as in party to a transaction, not birthday party). So then each one has their own resource, named like /party/PARTY_ID.
It's easy to extend this to see that /party/SOME_LANDLORD/applications and /party/SOME_RENTER/applications solve my issues. It also removes my need to consider custom headers.