StrataFrame Forum

Security Enhancement - row level security

http://forum.strataframe.net/Topic4222.aspx

By Greg McGuffey - 11/7/2006

I've been evaluating SF for about 3 weeks. In general, I'm very pleased. There is one area that is causing me no end of headaches though: the need to set a users permission based on some data in the application. (I've started a couple of topics regarding this: http://forum.strataframe.net/Topic3970-21-1.aspx and http://forum.strataframe.net/Topic4164-21-1.aspx).



Now, the security that you do provide is very good, but it starts getting messy in these two cases, both requiring that the permission be determined based on application data.



1. The final permission depends on the state of data in the database, which could be coming from multiple tables. E.g. The database has a widgets table, describing each widget, including the factory were they are made. Widgets have a status that describes whether the widget is currently in production or is still being tooled. In the factory table, there is a 'lockdown' field, which locks down any changes to widgets in production at that factory. Thus if the user has Grant permission to add/edit/delete a widget, they can only do so if the widget is being tooled for factories that are 'lockeddown' (but could add/edit/delete widgets of any status - based permissions of user - for factories that are not 'lockeddown'). Thus, the final permission could be overruled by a data rule (restriction?). (I also have this type of issue within the app I'm considering converting to .NET using SF.)



2. The user has different permissions based on what data they are attempting to use. This is the subject of the afore mentioned forum topics. In this case, the permission.action would change based on some data in the database. To extend the example above, image that some users have access only to widgets from a specific factory. This might be the case for a machinist who needs to update how she is tooling a widget for production. In fact, this user probably only has edit access to certain fields (the ones concerning tooling, but not the fields concerned with description of the widget itself). This could of course be handled by a Fill method on the Widget BO. But what if the machinist also is consulting another machinist at another factory. At this factory, the machinist can only view the widget, with no editing possible, in order to provide feedback, etc. Thus the machinist has one set of permissions at one factory (can edit widgets) and another permission at the second factory (can only read widgets). This is were it gets sticky. The appropriate permission needs to be applied based on the data (in this case the factory).



With regards to #2 above, there is also an issue of concurrency. Because the permissions are now set within db tables, it is impossible to have both edit widgets and read widgets permissions set and have them work correctly. I.e. if both are set, then the user has edit permissions at both factories. This means that the user can't view two widgets at the same time, unless it can be ensured that they are from the same factory (and thus the same permission applies).



It would be nice if the framework supported this level of complexity. I'm wondering if perhaps the restriction set paradigm might work. Except instead of time of day and workstations, be able to define data rules. For case #1, the rule would be fairly straight forward, something like:



factoryBO.LockDown = true And widgetBO.Status = 'production' -> PermissionAction.Deny



In this case, I image that factoryBO.LockDown is indicating that the LockDown property of a factoryBO is compared to True and widgetBO.Status is indicating the Status property of the WidgetBO. This restriction is then associated with a role or user for the WidgetEdit permission. Then when an instance of the widget BO is used (which is were we need the restriction), its secuirty key is set to WidgetEdit. It would also have to configure what object to use as the factoryBO and what object to use as the widgetBO (it would use itself most likely). When a user who is a member of a role with this permission and restriction set will have the restriction set on this object then.



For case #2, we would likely need to add the ability to reference other types, e.g. the SecurityBasics.CurrentUser and be able to call methods and have multiple rules:



rule 1: UserXFactory.UserHasAccess(SecurityBasics.CurrentUser.UserPrimaryKey) = false -> PermissionAction.Deny

rule 2: UserXFactoryRole.GetRoleActionForFactory(SecurityBasics.CurrentUser.UserPrimaryKey,factory.fc_pk) = "Read" -> PermissionAction.Readonly

rule 3: UserXFactoryRole.GetRoleActionForFactory(SecurityBasics.CurrentUser.UserPrimaryKey,factory.fc_pk) = "WidgetEdit" -> PermissionAction.Grant



In this case, there are multiple rules to process. If the rule evaluates to true, then successive rules are not evaluated. I.e. if rule 1 is true (the user doesn't have access to the factory), there is no need to evaluate rules 2 and 3. Again, the restriction is applied to a role for the WidgetEdit permission and factored in when the permission is determined. Here there is a BO to interface with a table that stores the role action for a user-factory combination.



Of course, the intent here is to help you understand what I'm having to deal with (cases #1 and #2) and then provide a bit of brainstorming on how it might work.



OK, this is long, but since I actually need to implement this NOW, I figured I could hit two birds with one stone: provide a detailed enhancement request and figure out more carefully what I will need to do! w00t



Now, even if you can't/won't fully implement this much functionality, there might be an easy improvement you could do in the mean time:



* Add an event to SecurityBasics for CurrentUserChanging (you have CurrentUserChanged), which would be fired before the current user is set. This would allow for custom rearranging of roles (as I now have to do), without much fuss.



I know this was a long post, but I've spent many hours dealing with this (and not done yet). Thanks for listening!

Greg