Hi,
I have 2 applications that require to be set-up with multi-tennant data. One is a new app from the ground up, the other will be based on the XCRM demo app - both supporting Domain Components. Both apps will only have a web UI.
Scenarios I need to accommodate are…
When a user logs in:
they will not select a company but will be logged into 'their' company
they will only see information from their company.
some classes *may* be shared across all companies
some records may only be edited by the 'CreatedBy' user
a user may not be logged in multiple times concurrently
The 'username' would preferably be an email address which is unique within the system
The way I see it, I will need 'Owner' (Company) and 'CreatedBy' (User) added to each class. These values would be filled in as each record is created based on the logged in user.
Filtering of views would occur by default based on the users company.
I notice in the 2011 RoadMap that a "a security system on the data layer level" is targeted for release in 2011 Vol 1 which I'm guessing will impact on what I would like to achieve. Is the Vol 1 release imminent and is it still likely to include the changes to the security system?
Can you please provide assistance with implementing the above scenario, either into XCRM or a clean project.
Best Regards,
Gavin Horne
Hi Gavin,
Unfortunately, we were unable to implement planned improvements to the XAF Security system in 11.1. We will try to implement them in future versions, possibly in 11.2.
Your scenario seems to require an object-level security system. It is not supported out-of-the-box. We already have a suggestion about it: Security.ObjectLevel - Introduce an "Object Owner" feature into the XAF Security system. You can track it to be notified when its status is changed.
Currently, you can filter list views not to include inaccessible objects as demonstrated in example E2039 (OBSOLETE - How to filter ListView to show only objects owned by the currently logged User).
Should you need any further assistance, please let us know.
Thanks,
Michael.
Hi,
I need some help with Domain Components. I would like to implement the example E2039 within the XCRM demo application. Would it be possible to provide sample code to implement CreatedBy/CreatedOn, preferably in a way that can be applied to multiple DC's?
Regards,
Gavin Horne
Hi Gavin,
I have created an example for you, based on example E2039 and domain components. It is attached. Please let me know if you need additional assistance.
Thanks,
Michael.
Hi Michael,
Thanks for the sample code. I have a problem though, I get an InvalidCastException :Unable to cast object of type 'System.Int32' to type 'DomainComponents.Common.IDCUser'. on the line
instance.CreatedBy = (IDCUser)SecuritySystem.CurrentUserId;
What's that about?
Cheers,
Gavin
Actually, the error with the original code "instance.CreatedBy = (Guid)SecuritySystem.CurrentUserId;" is "Specified cast is not valid."
Cheers,
Gavin
Also, I cannot open the designer for FilterDocumentsByOwnerListViewController.cs in the sample project or my own, not sure if that's a problem or not. The sample project does compile, run and work as expected.
Cheers,
Gavin
Hi Gavin,
The example I provided is designed to use Guid type user key. If your user class has a different key field type, modify the IOwnedObject.CreatedBy property type and the type used in the cast operator.
>>>instance.CreatedBy = (IDCUser)SecuritySystem.CurrentUserId;
The SecuritySystem.CurrentUserId property returns the key value of the currently logged user, not a user instance. So, you should cast this value to the key property type.
The visual designer for the FilterDocumentsByOwnerListViewController controller cannot be open, because it is inherited from a generic ViewController<ListView> type. This is by design. If you want to edit a controller visually, you should create it from the corresponding Visual Studio template.
Thanks,
Michael.
Hi Michael,
As mentioned in my question I want to "I would like to implement the example E2039 within the XCRM demo application." Turns out the user class has an integer ID. I didn't expect that as everything DX does with XAF usually declares GUID ID's.
Cheers,
Gavin
Hi Gavin,
I my project I use a built-in DevExpress.Persistent.BaseImpl.User class that is inherited from the BaseObject class and has a Guid type key field. The XCRM demo uses the IMyAppUser domain component that is registered using the ITypesInfo.AddEntityToGenerate method (without the third argument) that use the XPObject class, which has an Int32 type key.
If any part of my response is unclear, please let me know.
Thanks,
Michael.
Thanks Michael,
Got my head around it finally, bit slow I know ;^)
Now I need to start working on filtering the data based on what Company a user belongs to rather than who created the object in the first place.
Thanks for your help.
Cheers,
Gavin
Hi,
My aim now is to filter the data presented to the end user based on the Organization they belong to i.e. Where a Domain Component inherits the IOwnedObject Domain Component the end user should only see Objects where the CreatedBy user belongs to the same Organization.
Not sure if I'm going about this the best way. I was able to setup another project using Domain Objects by adding the OwnedBy Organization (Company) to each object I needed to filter. Can you please assist in getting this functionality happening for Domain Components.
Also, Is Domain Components the way to go if I have no intention on using anything other than XPO? It's more complicated than Domain Objects but there seems to be a number of new features or attributes. Will performance be better, are there any other advantages?
Cheers,
Gavin Horne
Hi Gavin,
To accomplish this task, I recommend that you modify the IObjectOwner domain component to store a user instance (e.g. IPerson) in the CreatedBy property, instead of its key. Then, simply modify the list view filter criteria to compare user's organizations:
CriteriaOperator.Parse("CreatedBy.Organization=?", View.ObjectSpace.GetObject(((IPerson)SecuritySystem.CurrentUser).Organization))
>>>Is Domain Components the way to go if I have no intention on using anything other than XPO?
The Domain Components technology is a different approach to design the business class model, with its exclusive features and limitations. It provides the functionality that cannot be implemented using persistent objects (the capability to create independent domain libraries and multiple inheritance), but hides some implementation details. So, you should decide whether you need these capabilities or a more detailed control over internal operation of your business objects.
>>>Will performance be better, are there any other advantages?
I am afraid DC won't show a higher performance than persistent object.
Thanks,
Michael.
Michael,
Thanks for all your help so far. I'm getting very close now to achieving my goals. Next, I would like to setup a "Company Admin" role. A user assigned to this role can add new users to their own Company and set the role(s) that user belongs to. I'm setting up a demo company admin as per the code below in Updater.cs but can't get the right object access levels. My Company Admin can add a new user but cannot link o roles. Can you please assit with the right "addpermission" code.
Regards,
Gavin
IPersistentRole companyadminRole = ObjectSpace.FindObject<IPersistentRole>(new BinaryOperator("Name", "Company Administrators"));
if (companyadminRole == null)
{
companyadminRole = ObjectSpace.CreateObject<IPersistentRole>();
companyadminRole.Name = "Company Administrators";
}
if (companyadminRole.ObjectAccessPermissions.Count == 0)
{
companyadminRole.AddPermission(typeof(IOrganization), ObjectAccess.Navigate);
companyadminRole.AddPermission(typeof(IOrganization), ObjectAccess.Read);
companyadminRole.AddPermission(typeof(IOrganization), ObjectAccess.Write);
companyadminRole.AddPermission(typeof(IMyAppUser), ObjectAccess.AllAccess);
companyadminRole.AddPermission(typeof(IPersistentRole), ObjectAccess.AllAccess);
companyadminRole.AddPermission(typeof(IObjectAccessPermission), ObjectAccess.Navigate);
companyadminRole.AddPermission(typeof(IObjectAccessPermission), ObjectAccess.Read);
companyadminRole.CanEditModel = false;
}
Hi Gavin,
This issue has been recently reported to us: XCRM Demo: The IMyAppUser.UserName property editor is read-only. It is not related to the XCRM demo code, but to a bug in our framework. I am afraid there is no workaround in the current version. Please track issue B200191 to be notified when its status is changed.
Thanks,
Michael.