Lets say i have objects A, B, C, D, E, F, collaborator groups C1, C2, users C1U1 (admin), C1U2 (user), C2U1 (admin), C2U2 (user).
A, C, E belongs to group C1.
B, D, F belongs to group C2.
Thus only members of correpsonding group can view their respective objects. Also any object created ends up in group to which its creator (user) belongs.
Admin can create and edit every entity, user can only create entities and only edit his entities.
And ofcourse each user (admin or regular user) as said before can view only entities that belong to his group.
In my particular task there are number of type of entities (static) and number of types of users (static). There will be multiple collaboration groups (dynamic) where users will create some entities. Some of the users will have ability only to view entities (to which they are entitiled to view due to being member of correspodning collaboration group), create and edit. Some of them will have ability to edit entities of other users (but only ceratin types of entities). Essentialy its a little bit like JIRA.
That said, my question is quite simple: what pattern helps organising this stuff? I believe this is a common problem, thus it must have common name.
I know there is a blunt way to create this. Im using symfony 2 and it have both RBAC and ACL, but not RBACL afaik. RBAC will help me with user types (i use UserGroups and i create roles like ROLE_EDIT_ENTITYTYPE1), checks for ownership are performed with ACL.
But how do i implement those collaboration groups?
Im sorry if my explanation sounds vague or just stupid or anything else, i would like to hear anything about subject. I got a feeling that i'm missing something here.
PS: Not sure about "security" tag, if its related to this question.
For your case the just Role Hierachy is not suffiecient enough. What you need is complete ACL:
http://symfony.com/doc/current/cookbook/security/acl.html
You can create the ACL right in a Listener when Entities are saved and then grant the access for all the group members.
You can also work with different ACL Masks, in order to control which user can EDIT entities and which users can only view them:
http://symfony.com/doc/current/cookbook/security/acl_advanced.html
Sorry for mainly linking to the default documentation, but I think this basically covers everything you need.
Related
In my system, I have some entities that conceptually inherit from User. For instance, I can have suppliers and regular consumers. I wish to extend the User entity, so that I can inherit all of user benefits like register, login, lost password and so forth.
I though about a few options:
1. Extending the User entity using one of the Hibernate inheritance strategies (https://docs.jboss.org/hibernate/orm/3.5/reference/en/html/inheritance.html), but it looks like a lot of changes in the code is needed. I'd also have to make sure the tables generation would be also correct and working fine with liquibase;
2. Adding all necessary attributes to the User entity and then adding suppliers and consumers as roles. I just don't feel comfortable by doing this since the User table wouldn't be normalized;
3. Creating a relationship from each of these entities to the User entity, but in this case, I don't clearly see how to inherit the user management benefits.
Has anyone ever done something similar so that could shed some light on this?
Thanks in advance.
I would rather use composition over inheritance. So basically, you would have Supplier holding a one-to-one relationship with User. This way, you let JHipster User related code unchanged.
User management feature has not yet been released so let's focus on user registration then how would a user qualify as a supplier or customer? Are they supposed to choose by themselves? Can a user be both a consumer and a supplier?
For me the simple JHipster CRUD screens will not be enough, you must be prepared for building your own screens for better UX. So, I would rather focus on having a strong data model and REST API.
I found a way following the second approach.
I added all the attributes for each subclass (in my example, Suppliers and Customers) to the table User (JHI_USER) and a type attribute as well so that I can know which type of user I'm handling. I added also their respective attributes to the User class and updating the related classes, like UserService, UserRepository, test classes and so forth. I used the concept of roles too, but just to provide permissions to each section of the site.
After that, I created an AngularJS state for each user type, passing its type (kinda like a discriminator). For instance, I created a state called /registerSupply passing its type = 'S'. I then edited the original register page to add all the additional suppliers and customer attributes, filtering them out based on the user type and that is it.
As I stated, I don't feel comfortable by using this approach, but in the end, it's basically one of the strategies suggested by Hibernate (https://docs.jboss.org/ejb3/app-server/tutorial/singleinheritance/single.html), which makes me feel a bit better.
The preferred way explained in this issue is to use Git. Just add your code manually, and use git merge when you regenerate your code from JDL.
Using composition would create a JOIN that has performance impact on a massively used entity. Entity inheritance works but is hard with JPA and would even harder with generated code.
If I had to choose between composition and inheritance, I would prefer here composition with caching when the application grows.
I am sure this has been done by many of you and was looking for some guidance into designing a robust, scalable, application that can handle data (row level) security for multiple users.
We are looking at a system whereby users, some acting as individuals, and some as part of larger groups will need access to both their own data as well as to data shared with them by other individuals and organizations. In some cases the data is shared just to view and in other cases full edit permissions will be available.
And even within the same organization there will need to be restrictions on what users can see in terms of data created by other users in the organization.
So a very rough example may be...
User A with Role X, (individual user)
User B with Role Y (individual user)
User C with Role Z (individual user)
Users D and E with Roles X, in Organization AA
Users F and G with Roles Y in Organization AA
Each individual User might create for eg a contract on our system. That contract shoudl not be viewable by anyone else until they choose to share that contract with other individual users eg A will share his contract with User B or F.
But User A may also want to share his contract with all users of Role Y in Organization AA.
Likewise sharing the contract may even mean permission to edit the contract.
We initially had wanted to have a separate schema for each individual user to ensure security at a data level but this makes sharing more complicated and also may result in 1000's of schemas (which just doent seem like a good idea).
So it seems like our only resort is to leave all the data in one schema in one db and simply design a user and role driven application level security model which can accommodate all the required CRUD permissions on each contract. It just sounds like this is going to get very complicated and "not so pretty". For every contract we would have to define a list of users and roles by organization which with the individual permissions for each one of these users/roles.
Has anyone done anything like this? Any suggestions with regards to a good and secure application design?
Thanks
Here are some rough thoughts for this requirement
Since you are talking about data security control rather than system function/feature access control, so I will focus on data access control here.
Structure of Access Control Classes
You might want to treat all level of security atom as the same thing, e. g, it's generally defined in a way that individual / permission / role / group are inherited from the same basic principle class, and then conceptually, all access control definition will be on this basic principle, hence you don't need to know whether the control is over a role, a group or a user, this will give you more flexibility and simples the question.
You might also want to define the principles as kind of combination / hierarchy structure, for example
User A is assigned RoleA, RoleB, RoleC and PERMISSION2
Role A is a combination of RoleC and RoleD
RoleC is a combination of permission PERMISSION1, PERMISSION2 etc.
BTW: Since the design here is very flexible so you will need a system level conflict check mechanism to check
The conflict between all the principles upon any assignment to make sure there's no system level conflict(for example, roleA defines that the user can not update document of Type A, while PERMISSION2 defines it can), another possible method is to define a priority for different type of principle, for example, defined level USER > ROLE > PERMISSION.
And also a function level(SOX law etc) conflict check to make sure there's no function level conflict, for example, someone capable to do payment can not have access to operate on cash etc)
Access for Documents
Then a schema such as document / principle / restrict type / restrict operation / restrict start and thru date could be defined to store data access control for each document,
Document could be a contract, a purchase order, purchase request etc, it's actual type doesn't matter at all here.
Principle could be a user / permission / role / group etc, also you don't want to focus on the actual principle type here, by this design, only one row of data is needed for those normal documents(since we could define it on role level), and also if the user choose to share this document with a particular organization or individual, it will also be able to handle.
Restrict type might be "ALLOW" / "NOT_ALLOW" etc,
Restrict operation could be "VIEW" / "UPDATE" / "ADMIN" etc,
Restrict start and thru date will be the date range this access control take effectives, by combine this thru date, operation and restrict type we defined, you can combine exceptional access control with normal access control, hence to implement requirements like share / delegation will be easier, and it also didn't bring too much complicate for normal access control.
Organizations
If your organization has a hierarchy structure, you can also define how the access control to be inherited for parent and to child organizations, a sample schema might be,
Organization Id / Acccess inherent Type / Start and thru date.
Organization id: primary key of this organization
Access inherent type: Could be something like: ALLOW_ALL_CHILD / ALLOW_ALL_PARENT / ALLOW_ALL_SAME_LEVEL /DENY_ALL etc.
Start and thru date could be the date this role takes effective and ends.
Something you might be able to implement could be:
For organization A, all it's subsidiaries is not allowed to view / update any documents under it.
For organization B, all it's subsidiaries is allowed to have view / update permissions to all documents under it, but not to the documents on the same hierarchy level.
Then you can combine this organization level access control and the document level access control, when evaluating the rules, the document level access control always have a higher priority than organization level ones.
Except the question whether the following scenario is a good case for DDD at all, I'd like to discuss it and ask for advice:
Given we have users and groups. A user has a name, and a group has a name as well. Users may join of leave groups, and they may also change groups. The rules they have to obey are: A user may only be in maximally 2 groups, and a group may consist of maximally 10 users.
How do you model this? So far I can think of three options, where each option has its individual advantages and disadvantages:
Users and groups are entities, and both are aggregates as well. Join, Switch and Leave are commands on the group aggregate. While this works great for Join and Leave (as they only refer to a single group), it does not work for Switch, as this refers to two groups at the same time, and hence needs to modify two aggregates in a single transaction, which is not nice.
Users and groups are entities, and both are aggregates as well. Join, Switch and Leave are commands on the user aggregate. This works great for all three, and it is easy to check that a user is not in more than two groups at the same time, but how would you check that the rule of maximally 10 users per groups is not violated?
Users and groups are entities, both are aggregates. But there is also a third aggregate: Relationship. Join, Switch and Leave are now commands on the relationship aggregate. While this seems to be the best approach (since it gives the relation between users and groups a name and makes it explicit), I am now completely lost on how to model the constraints.
Can anybody give me a hint?
If there was only one of the two constraints it would be dead-easy: Then you could put the commands to the aggregate which also has the constraints. But if you have a constraint on both sides, I'm lost. Any help?
You may hand an instance of group to the user to have it check aggregate-encompassing invariants. Then let the user know it joined the group and let the group know that a user has joined.
class Application
handle(UserWantsToJoinGroup command)
user = users.withId(command.userId)
group = groups.withId(command.groupId)
user.join(group)
class User
join(Group g)
if g.isFull throw
if this.isMemberOf(g) throw
if this.numberOfGroupsImIn >= 2 throw
publish new JoinedGroup(this.userId, g.groupId)
handle(JoinedGroup evt)
// modify state
class Group
handle(JoinedGroup evt)
// modifiy state
We are currently designing a new member administration for our study association in LDAP, using OpenLDAP 2.3.31 distributed with Debian. One of the requirements is that we need to record which members are in committees. To this end, we have created a subclass of organizationalUnit, called x-FMFCommittee and a subclass of organizationalRole caled x-FMFCommitteeRole. Now, all roles (such as president, treasurer, etc.) that are associated with a committee are located in the subtree of the committee entry. The DN of the members that take on this role are then set as a roleOccupant attribute on the x-FMFCommitteeRole. This works perfectly fine.
However, we also give our users access to a Linux shell and Windows desktops (using Samba) and for this we would also like to administer POSIX group membership. To this end, every committee we want to do this for, also has the objectclass posixGroup (as per RFC2307). In order to get the group members and the groups associated to a user, we need to set the memberUid attribute on the committee entry whenever a member occupies a role in the committee.
We have tried doing this using the dynlist overlay, but this fails when doing reverse group lookups. The only option we see now is to do this all manually, but we really would like to automate this, to provide easier maintenance in the future as administrators tend to change often at our association.
Has anybody come across a similar scenario before, or does anyone know a solution to this problem?
I would suggest that you simply get rid of the first implementation and just use posixGroup. Database denormalization is always a bad idea, whatever form it takes.
And you don't need to extend schemas for this problem. If you want to distinguish these committees just put them them in their own subtree.
But I'd like more detail on why using a dynamic list doesn't work. You could use the memberOf overlay instead of having to do reverse lookups.
I've got a system that allows classroom instructors and graders to log in and manage classes and grade papers. A user can be both an instructor and a grader, and can be so for particular semesters. Other users, like students, are also bound to this semester scheme. Still others, like administrators, have accounts that don't run by semester.
When someone is no longer a grader or instructor, she still needs to be able to access past grading or classroom records, albeit with fewer privileges (view only).
I've thought about implementing a roles table with a semester as a part of the key, but that doesn't apply to all users. I've also thought about keeping the semester data separate from the roles, but making roles like "PastGrader" and "PastInstructor" to cover those people who need to have access to past information but should not be allowed to participate in this semester.
What is the optimal data model/roles model for this application?
I think you're on the right track. I would keep the semester out of the roles table, but use them together where needed.
Here is what I did recently that will also work in your scenario:
Create a FunctionalRole table that has the following columns:
FunctionalRoleId, FunctionalRoleName
These roles will be like jobs. Teacher, Grader, etc.
Add another table called FeatureRole, with the following columns:
FeatureRoleId, FeatureRoleName
These roles will be for specific features in the application. GradePapers, ViewPapers, etc.
Then create a third table... call it RoleMember, that has these columns:
FunctionalRoleId, FeatureRoleId
That way, the admin can assign roles more simply by the job and all of the feature roles will automatically be assigned.
And like I said, keep the semester information separate.
Gabriel
I think that you need an additional entity to help you out. You clearly have the domain object of a CLASS to represent a specific class (ie: Composition II is a class). You also clearly have a domain object for PARTICIPANT to represent the people that attend the class. I think you have already identified those two.
Next, you need a domain object to represent a specific semester/timeslot/classroom where a CLASS will be held. Let’s call that domain object a CLASSSCHEDULE. You will need a relationship from CLASS to CLASSSCHEDULE to show what topic will be taught in that room during that semester.
Now you need a domain object to represent how a PRATICIPANT interacts with a CLASSSCHEDULE. We can call this domain object an ENROLLMENT. The ENROLLMENT object is where you put your privileges for the PARTICIPANT. The PARTICIPANT is ENROLLed in the CLASSSCHEDULE as a learner or a grader. Your role is attached to the ENROLLMENT object. In this way, each PARTICIPANT will have a different privilege level for each CLASSSCHEDULE that they are involved with.