==============================
This solution can be applied only to the old Security System.
Starting with v13.2, you can configure member permissions to grant access to the associated collections (see Security - Provide the capability to link/unlink objects in non-aggregated collections if they have the corresponding permissions while the master object is restricted ). You should not use this example in a new project.
==============================
Suppose, I have the Organization and Person classes. Each Person object can be associated with a number of Organization objects, and each Organization object can be associated with a number of Person objects (a many-to-many relationship, see the BusinessClasses.cs file):
[C#]publicclassPerson:XPObject{publicPerson(Sessionsession):base(session){}publicstringName{get{returnGetPropertyValue<string>("Name");}set{SetPropertyValue<string>("Name",value);}}[Association("Organizations-Persons2")]publicXPCollection<Organization>Organizations{get{returnGetCollection<Organization>("Organizations");}}}publicclassOrganization:XPObject{publicOrganization(Sessionsession):base(session){}publicstringFullName{get{returnGetPropertyValue<string>("FullName");}set{SetPropertyValue<string>("FullName",value);}}[Association("Organizations-Persons")]publicXPCollection<Person>Persons{get{returnGetCollection<Person>("Persons");}}}
And, an end-user needs to modify any Person object, including its "Organizations" collection ('Link' or 'Unlink' organization objects), but he or she should not modify any property of an Organization object.
To accomplish this, I grant all operations under the Person objects and grant only the Read operation over the Organization objects (see the Updater.cs file):
[C#]userRole.AddPermission(newObjectAccessPermission(typeof(object),ObjectAccess.AllAccess,ObjectAccessModifier.Allow));userRole.AddPermission(newObjectAccessPermission(typeof(Person),ObjectAccess.AllAccess,ObjectAccessModifier.Allow));userRole.AddPermission(newObjectAccessPermission(typeof(Organization),ObjectAccess.ChangeAccess,ObjectAccessModifier.Deny));
With these permissions, I have achieved the necessary behavior, except for that an end-user cannot modify the Organizations collection property. This is a restriction of the current implementation of the XAF Security system.
To avoid it, I introduce a new class and manually allow modifying the "Organizations" property in the code (see the AllowManyToMany_ObjectAccessComparer.cs file):
[C#]publicclassAllowManyToMany_ObjectAccessComparer:ObjectAccessComparer{publicoverrideboolIsSubsetOf(ObjectAccessPermissionsourcePermission,ObjectAccessPermissiontargetPermission){if(sourcePermission.AccessItemList.Count== 1){ParticularAccessItemsourceAccessItem=sourcePermission.AccessItemList[0];if(typeof(Organization).IsAssignableFrom(sourceAccessItem.ObjectType)&&sourceAccessItem.Access==ObjectAccess.Write&&sourceAccessItem.Modifier==ObjectAccessModifier.Allow){if(sourcePermission.Contexts!=null&&sourcePermission.Contexts.CollectionPropertyContext!=null&&sourcePermission.Contexts.CollectionPropertyContext.CollectionPropertyName=="Organizations"&&typeof(Person).IsAssignableFrom(sourcePermission.Contexts.CollectionPropertyContext.MasterObjectType)){returntrue;}}}returnbase.IsSubsetOf(sourcePermission,targetPermission);}}
and set this class as the current ObjectAccessComparer in the main.cs and global.aspx.cs files:
[C#]ObjectAccessComparerBase.SetCurrentComparer(newAllowManyToMany_ObjectAccessComparer());
Thanks,
Dan