Search This Blog

Tuesday, February 3, 2015

Storing security settings (users, roles, permissions) and application-specific data in separate databases

I wanted to inform the community of a solution we have just finished testing for the next XAF version in response to the following customer's business scenario:

"We have 2 content databases and we will be running multiple applications on the same databases. Therefore i would like to have a separate database for each application to store the application specific data in...For security reasons we are not allowed to store security data in the same DB as our other data. It not our choice."






As you probably know, XAF supports connecting to several databases and even using both Entity Framework (EF) and eXpress Persistent Objects (XPO) at the same time (examples: onetwothree), although it is not the primary scenario, to be honest. The aforementioned scenario could currently be solved if your application uses DevExpress XPO for data access (by implementing an IDataStore proxy as per this example), but there were no good solutions for EF or EF + XPO cases. In our case, a customer was using EF so the solution would be complicated (see the details).

The good news is that starting with version 14.2.5, we made accomplishing this business scenario easier for both EF and XPO data access options. Now IObjectSpace (an XAF abstraction representing a context to a specific database) from the registered XafApplication.ObjectSpaceProviders collection is passed to the security system and there this information is reused to query permissions from the corresponding database.

I would greatly appreciate it if you let me know in comments if you experienced a similar scenario and how the new solution works for you.

15 comments:

  1. This comment has been removed by the author.

    ReplyDelete
  2. Also, Will the Business Objects to support the various Apps be capable of being created dynamically or even inherited from a Master business object?

    ReplyDelete
  3. @Ken:
    >>support the various Apps be capable of being created dynamically
    Would you please elaborate a bit more on this?
     
    >>even inherited from a Master business object?
    Using this particular approach (separate ObjectSpaceProviders) inheritance of persistent classes is only possible for classes mapped to the same database.
     
    I would be very interested to learn more on the actual business problem/scenario you want to address by this, because there may be different technical solutions.

    ReplyDelete
  4. The legacy system is exactly as your diagram above although the design of each Database / App is the same design.

    I have implement E1150 using separate namespaces for each business class and separate connection strings in the web.config that differ with namespace suffix.

    The above means creating the business class at compile time. Each additional app means adding classes and recompiling the XAF application in total. I would like to create a better way of managing adding and deleting Apps (databases) without having to create a new XAF app.

    ReplyDelete
  5. I have just noticed 14.2.5 has been released today. Can you point to documentation regarding this new approach?

    Thanks

    ReplyDelete
  6. @Ken: Thank you for clarifying your needs. It seems that your scenario is different from what I was describing above, as each app and database share the same design...Unless I am mistaken, you are currently duplicating the class code in a different namespace...I do not know the full requirements of our business that led to this, but it does not look right to me. Would you please elaborate on this?
     
    As for v14.2.5, there was no new documentation in this regard. The existing documentation is the following:
    1. https://documentation.devexpress.com/#Xaf/CustomDocument3476
    2. https://www.devexpress.com/Support/Center/Example/Details/E4896
    These approaches will only work with v14.2.5 when you want to have security related and application data in different DBs.

    ReplyDelete
  7. Hi, Dennis
    This is a really good news.
    Is there any example of how to accomplish this scenario or is it only provided as a feature yet to be implemented?

    Thanks

    ReplyDelete
  8. @UnKnOwN: Thanks for your feedback. I have already answered the same question in my previous comment, which contains links to docs and examples. This feature is already present in v14.2.5 and there is nothing special to be implemented on your side for this - it just works in the aforementioned configuration.

    ReplyDelete
  9. Hi Dennis,

    I have managed to follow the example E4896 but in my case using two XPO instances with underlying business objects.

    In the example notes uncer item 3 - "3. Business classes linked to different ObjectSpaceProviders are considered....... "

    It seems this contradicts exactly what this change is implementing. I don't see how to put all the Roles and Security objects in a separate Db and have the other Db's use them?

    Thanks

    ReplyDelete
  10. Thanks for your feedback, Ken. In the original scenario the main problem was with security permissions stored in a separate database. I cannot imagine many real-life scenarios where you would need to have links to this pure service info (permissions, roles, etc.). So, you can safely put this staff into a separate database and this is what we made possible with the new release. I hope this makes sense.

    ReplyDelete
  11. Hi Dennis,

    I think were talking about the same thing.

    In example E4896 it states you cannot have permissions & roles in a separate database - See item 3 in the notes. But this new facility is supposed to allow it. I can't see how this is achieved as the example clearly doesn't cover it?

    Thanks

    ReplyDelete
  12. @Ken: I have found that the 3rd point of notes was not updated after implementing this feature. I have updated it accordingly. Thanks!
    The E4896 itself does not cover storing permissions in a separate database, but rather demonstrates a general concept of separating different persistent types in different databases. You, as a developer, should not do anything special for this to happen except for registering separate ObjectSpaceProviders as it is demonstrated in the example. I hope it is clearer now.

    ReplyDelete
  13. Hi Dennis, how will this affect Model Differences stored in the database. If I have 2 different XAF Applications, how are the Model Difference tables be stored?

    ReplyDelete
    Replies
    1. You can choose yourself where to store ModelDifference and ModelDifferenceAspect data when configuring XPTypeInfoSource and XPObjectSpaceProvider.

      Delete
  14. does this work if XPO is not used for data access at all, and there are multiple EFObjectSpaceProviders?
    Actually this is my scenario:
    I've two databases, both accessed via EF by an xaf application. One of the two, contains the tables of security(PermissionPoliyUser, ...)
    I'm using the latest version, though, I get this error when I try to access the entities which are contained in the database which does not hold the security information:
    The entity set for the 'DevExpress.Persistent.BaseImpl.EF.PermissionPolicy.PermissionPolicyUser' type is not found.

    at DevExpress.ExpressApp.EF.EFTypeInfoSource.GetEntitySetName(Type type)
    at DevExpress.ExpressApp.EF.EFObjectSpace.GetObjectByKey(Type objectType, Object key)
    at DevExpress.ExpressApp.Security.EF.Adapters.EFCachedRequestSecurityAdapterProvider.GetUpdatedPermissionsProvider(IObjectSpace objectSpace, Type providerType, Object providerId)
    at DevExpress.ExpressApp.Security.AdapterFacade.GetPermissionsProvider(IObjectSpace objectSpace, Type providerType, Object providerId, ISecurityAdapterProvider securityAdapterProvider)
    at DevExpress.ExpressApp.Security.AdapterFacade.GetPermissionsProvider(IObjectSpace objectSpace, Type providerType, Object providerId)
    at DevExpress.ExpressApp.Security.SecurityStrategy.CreateSelectDataSecurityCore(IObjectSpace objectSpace)
    at DevExpress.ExpressApp.Security.SecurityStrategy.CreateSelectDataSecurity(IObjectSpace objectSpace)
    at DevExpress.ExpressApp.Security.SecurityStrategy.IsGranted(IPermissionRequest permissionRequest)
    at DevExpress.ExpressApp.SecuritySystem.IsGranted(IPermissionRequest permissionRequest)
    at DevExpress.ExpressApp.DataManipulationRight.HasPermissionTo(Type objectType, String memberName, Object targetObject, IObjectSpace objectSpace, String operation)
    at DevExpress.ExpressApp.DataManipulationRight.CanDelete(Type type, Object targetObject, CollectionSourceBase collectionSourceBase, IObjectSpace objectSpace)
    at DevExpress.ExpressApp.SystemModule.DeleteObjectsViewController.UpdateActionState()
    at DevExpress.ExpressApp.SystemModule.DeleteObjectsViewController.DoUpdateActionState()
    at DevExpress.ExpressApp.SystemModule.DeleteObjectsViewController.OnActivated()
    at DevExpress.ExpressApp.Controller.activeList_ResultValueChanged(Object sender, BoolValueChangedEventArgs e)
    at DevExpress.ExpressApp.Utils.BoolList.OnResultValueChanged(Boolean oldResultValue, Boolean resultValue)
    at DevExpress.ExpressApp.Utils.BoolList.EndUpdate()
    at DevExpress.ExpressApp.ViewController.SetView(View newView)
    at DevExpress.ExpressApp.Frame.ActivateViewControllers()
    at DevExpress.ExpressApp.Frame.SetView(View view, Boolean updateControllers, Frame sourceFrame, Boolean disposeOldView)

    ReplyDelete