User acess rights using MemberOfGroups in hybris - sap-commerce-cloud

I have custome item type "Appeasement" , which contains attribute "appeasementStatus" of enum type "AppeasementStatusType" .
For customersupportagentgroup we dont have write access to item type "Appeasement" but I want to provide write access to attribute "appeasementStatus". I create below impex but this is not working as excepted.
Is any think missing?
enter code here
$START_USERRIGHTS;;;;;;;;;
Type;UID;MemberOfGroups;Password;Target;read;change;create;remove;change_perm
UserGroup;customersupportagentgroup;;;;;;;;
;;;;Appeasement;+;-;-;-;-
;;;;AppeasementStatusType;+;+;+;+;-
;;;;Appeasement.appeasementStatus;+;+;-;-;-
$END_USERRIGHTS;;;;;;;;;

What you are trying to do is not possible this way. Check the following section from https://help.sap.com/viewer/d0224eca81e249cb821f2cdf45a82ace/1905/en-US/8b4aa00e866910148df2920f69d68b27.html
Attribute Permissions
Using attribute permissions allows you to
explicitly assign permission to selected attributes of a certain type.
Attribute-related permissions don't override type-related permissions.
For example, if the type permission for a type is set to deny:
<Change>, you cannot grant permission: <Change> to any of the
attributes of that type. You can, however, set the type permission for
that type to permission: <Change>, and then decide which of the
attribute-related permissions you want to set to permission: <Change>,
and which to deny: <Change>.
As a summary, the type-level permissions can not be overridden to make less strict at attribute-level.
The workaround is the other way round i.e.
Grant <write> access to customersupportagentgroup for the itemtype, Appeasement.
Deny <write> access to customersupportagentgroup for all the attributes, except appeasementStatus.

Related

Find all resources (users) that has a schema extension property set to null

We have a scenario were we need to extend the existing schema in AAD for users to support our use case. As soon as a new user has been created (we do not control this process) we want to attach some additional information to the object. We also want to attach information to all the already existing user objects. We though the schema extension in the Graph API would solve this issue for us.
I've added a schema definition based on the tutorial here. Our extension got the name ext7sumrsqd_policies and have the following properties:
IsHandled (boolean)
SuggestedOwner (string)
After the extension was created I wanted to find all users that does not have the new "property" set (imagine a sync that is running on an intervall and want to check for new users that has not yet been handled).
Tried the following query first: https://graph.microsoft.com/v1.0/users?$filter=ext7sumrsqd_policies eq null
However the Graph API does not support filter with null.
Therefore tried to filter on any of the properties on the new extension:
https://graph.microsoft.com/v1.0/users?$filter=ext7sumrsqd_policies/IsHandled eq false
https://graph.microsoft.com/v1.0/users?$filter=ext7sumrsqd_policies/IsHandled eq true
However this filter never returns any user that has ext7sumrsqd_policies=null.
Are there any way you can filter the Graph API for resources that is currently missing a schema extension property or where the property is null?
As stated filtering by null is not supported. You might try creating a second schema extension such as ext7sumrsqd_hasPolicies that specifies if ext7sumrsqd_policies is null or not.

How and when to hydrate domain objects in the CQRS command stack

Suppose I have a command that saves an application Role along with some application Permissions. My roles and permissions have (or will have) business rules, so I'll use domain objects:
class Role {
...
IEnumerable<Permission> Permissions { ... }
AddPermission(...)
...
}
class Permission {
...
int ID { ... }
string Foo { ... }
string Bar { ... }
string Baz { ... }
}
When I'm saving a Role, I need a full Role object and will probably receive everything I need from the presentation layer. I do not need full Permission objects, though, because I only need to associate their ID with the Role. I don't need the Foo, Bar, and Baz properties.
When I'm saving a Permission, I obviously need the full Permission object.
My Question: What is the right way to handle that Permission object? If I only have one Permission class, then, when I'm saving a Role, I will either:
Have to query/hydrate full Permission objects from the database so the Role has legitimate Permission objects in its collection, or
Attach incomplete Permission objects (IDs only) to avoid the trip to the database.
Option #1 sounds like the kind of command/query complexity CQRS aims to avoid, and #2 sounds like an invalid object floating around--I don't even want to be able to create invalid objects, much less use them.
I could also create a PermissionSummary class and the full Permission class derives from it. I've done this before, and it inevitably leads to a creep of properties from the "full" class up to the "summary" class.
Batavia's response to CQRS is great and as I have no experience with that pattern Ill try and answer the 'what do I save' question.
The answer to this one depends strongly on your Model design and the proposed behavior of the Permission entities. DDD does not work without a strong knowledge of the business domain.
Having said that I can think of 3 scenarios:
1) Permissions are immutable and Roles get changed. In this scenario Role becomes the aggregate root and the collection of Permissions in re-hydrated on each fetch. The properties and methods of each Permissions entity is available to Role entity enabling operations like
partial class role() {
public enumAccessType AccessToAction(enumAction action) {
foreach(var p in Permissions)
if p.HasFullAccess(action) return enumAccesssType.Full;
foreach(var p in Permissions)
if p.HasLimitedAccess(action) return enumAccesssType.Restricted;
return enumAccesssType.None;
}
}
There is a Permission repository for saving new Permissions and a Role Repository for maintaining the roles and the role_Permission tables
NOTE: Just because the domain object has the full PERMISSION objects doesn't mean that the persistence layer needs to update the PERMISSION table for each of the permissions added. The RoleRepository should only update ROLE (roleId, roleName) and ROLE_PERMISSION (roleId, permissonId) tables.
2) Permissions are mutable But roles are static. In this situation is may make more sense for your model to have Permission as the Aggregate root and a collection of Roles as role is just a bucket for grouping Permissions:
class Permission {
Ienumerable<RoleId> Roles {get;private set;}
PermissionId ID { ... }
string Foo { ... }
string Bar { ... }
}
Again there is Permission repository for saving new Permissions and maintaining the Permission-Role relations. The Role Repository just handles roles.
3) Roles and Permissions change all the time - your security requirement is complex and will difficult for most end users to comprehend. Bring in the Domain Expert to explain how Role and Permissions relate and affect the rest of the system and WHY the have to be so flexible. Look at the why and try and identify processes or behavior that may be incorrectly being forced into a roles-permissions pattern. This will probably require its own bounded context and services to work.
It helps to remembers 'Database Tables' != 'DDD Entities' != 'User Interface'. At first blush it looks like your coming at this from a database design point of view rather than the domain behaviour point of view.
A big 'Am I Doing This Right' is this check: If I save changes to one entity , do I need to reload any other entities that reference that original entity in order for those other entities to work? If the answer is yes then you need to revisit your model.
so when using CQRS i think the answer is neither.
I think it's important to differentiate between DDD and CQRS.
When saving a role (In the CQRS pattern) you would be sending a "RoleChangeRequest" command to your backend. This would then raise a RoleChangeRequested event. (this could be done by a domain service, possibly even by the domain layer itself). This event would be handled by your database layer but this event would look more closely to this
class RoleChangeRequested {
IEnumerable<int> PermissionIds {....}
string name {....}
}
The key here is that in raising the event that would save your data you only need to know about the Id's of the permissions. There is no need to either query permissions (ok, maybe you want some check that they actually exist. but a foreign key relation could handle this). or to attach incomplete objects.
NOTE: In just this example CQRS is going to make your application a lot more complex. CQRS is weapons-grade architecture and should be handled with extreme caution. Now why would you want to use CQRS, that's because your next requirement is to make a full and guaranteed audit trail of all your role and or permission changes. This is just another event handler to the same events. And you could even have an event handler to the generic ievent interface and then you are guaranteed that you audit every event being raised in the application. That you get (almost) for free and is why CQRS can be a benifit.

How I get or set isMemberOf(memberOf), createdTimestamp, and modifiedTimestamp

I'm using spring ldap with OpenDJ and was not able to set the attribute isMemberOf or memberOf for the person. Also, I'm having problem to get createdTimestamp and modifiedTimestamp attributes for the person. Please help
The createTimeStamp and modifyTimeStamp LDAP attributes are by specification Operational and read-only: they are set automatically by the server when the entry is created (LDAP ADD operation) or modified.
The isMemberOf is also an operational and read-only attribute in OpenDJ. It is a backlink between a Group and a user. It's computed on the fly, based on Static or Dynamic group. Add the user DN to a group, and you will be able to read the isMemberOf attribute in the user entry.
In my implementation, which currently uses Spring LDAP repositories (spring-boot-starter-data-ldap version 3.0.0-M3) and Oracle Unified Directory (OUD), I was able to fetch the operational attribute isMemberOf by simply including the #Attribute annotation on the appropriate user property.
For example:
#Entry(...)
public class AppUser implements UserDetails {
// ... other fields ...
#Attribute(name = "isMemberOf")
private List<String> groups;
// ... getters/setters ...
}
#Repository
public interface AppUserRepository extends LdapRepository<AppUser> {
}
By fetching a user with the repository's findOne() method, and without any additional configuration, it correctly populated the groups property. However, as mentioned in the other answer, it's read-only; to set the isMemberOf, you would need to add the user DN to any relevant groups.

ldap objectclass with "contact type" attribute

Trying to do something with OpenLDAP that should be very simple, just can't seem to find a clear answer. I need to be able to organize any person's contact attributes according to their "type". For example, email would be type 6. So, if I wanted to send an email to all members of my OU, I would choose those that have a type 6 address.
since LDAP attributes are a name, value pair, I don't see how to assign an additional property to a contact address, yet it seems like a common enough problem. Any suggestions?
Attributes in the directory server model are indeed name [optional option] value constructs. To accomplish the task you describe, you could assign another attribute to the entry. RFC2798 defines the employeeType (link) attribute type with a syntax of DirectoryString and an equality matching rule of caseIgnoreMatch. Perhaps this attribute could be used for your purposes. If you assigned the attribute like:
employeeType: type 6
the LDAP client would then find all those employees with a filter like
(&(employeeType=type 6)(objectClass=inetOrgPerson)).
If you had concerns about the matching being caseIgnoreMatch you could specify that the server use caseExactMatch by using an extensible match filter like:
(&(employeeType:caseExactMatch:=type 6)(objectClass=inetOrgPerson))
employeeType is multi-valued, therefore, employees could have more than one employeeType. Any value that is a valid DirectoryString could be assigned to employeeType.

Spring MVC: Securing handler method

I'm wondering what is good approach to secure handler method in Spring MVC controller. Now i use #Secured annotation, that ensure that some method may be accessed by logged user only. But how to ensure that one logged user doesn't do something bad for other users ? For example i have method that delete item with given id. To ensure that someone can't remove other than his items i check item owner. Is better way to do something like that ?
#Secured("ROLE_USER")
#RequestMapping("/deleteitem.html")
public String delete(#RequestParam(value="id") Long id) {
Item b = itemDAO.get(id);
if(b.getOwner().getId().equals(((UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUser().getId())) {
itemDAO.delete(id);
}
return "redirect:/user/items.html";
}
Perhaps you can look at #Preauthorize annotation. You can do something like
#PreAuthorize("#item.id == authentication.id")
public void doSomething(Item item);
You would need to rewrite your current code suitably.
Look into Spring Security ACL (Access control list) you can create a list of permissions that users have for this object. Permissions include read, write, delete...
You need to implement role base system, base on privileges user can perform delete operation.
If specific user having delete access then he/she do the delete stub.

Resources