In the previous post about row level security, I mentioned that the two PeopleCode events SearchInit and SearchSave were not intended for providing row level security.
There’s a few different reasons. One key reason is that, by design, online security that is implemented via SQL is security that can be re-used for reporting. Query, Crystal, and nVision will all use the same search record/view when it is attached to tables being reported on. Crystal and nVision do this because they use Query as a data source (note that nVision is not limited to just Query as a data source though).
All you need to do is open the record properties in Application Designer. On the Use tab, you’ll see a prompt for Query Security field. Unfortunately, this prompt is not smart enough to limit your choices only to records that will make sense as security records (same keys, plus OPRID or OPRCLASS), but that won’t stop you from using the same search record/view that you used for the online component.
The next time that you run a Query, Crystal or nVision report that uses that data table, you’ll see that the data is limited appropriately. Even with SQR, where this doesn’t happen automatically, you can perform the join manually to implement this security.
If the data level security is written in PeopleCode, then you’ll have to do extra work for reporting security.
An even more important reason to avoid using SearchInit and SearchSave is to avoid potential security breaches.
Historically the behaviour of the component processor had been that if all of the key values for the search record were provided and the search record/view allowed access, then the SearchInit and SearchSave events did not fire. And why would they, given that there is no need to display a dialog to help someone browse for data that they have already supplied?
Of course, there were a number of people that did make this assumption, so the default behaviour of the component processor was changed awhile back to always force SearchInit and SearchSave to fire.
One consequence of this change in behaviour was that sending someone a URL directly into a page with the data loaded stopped working. Instead the person would see the search dialog with the key values loaded, and they would need to press the “Search” button. Since all of the keys needed to load the page were already present, the user wouldn’t need to select from multiple rows, but it was still a pretty jarring experience for the user.
So, another change was added. This time a new PeopleCode function called SetSearchDialogBehaviour() was added. The function could only be used in the SearchInit event and would allow the application developer control over whether the component processor used the historic behaviour and go straight into the page when all key values were supplied, or to keep the new default behaviour.
In case you’re wondering, there wasn’t an easy way to make the events fire, but still let the page load if all key values were provided (long explanation, but it was considered the most desirable outcome – just couldn’t happen in the releases that needed to be changed).
The problem comes because the reason for this behaviour is still not widely known in the Application Developer community. So you’ll see questions like this along with answers like this. Right answer, but not getting the overall story.
I once had to fly 3000 miles for a meeting with a large PeopleSoft customer that made this mistake in some custom development that they had a consulting company do for them. Only they didn’t figure this out themselves, a major newspaper wrote an article about the holes in the system that allowed anyone to look at anyone else’s data. Not good.
That’s not to say that it’s impossible to do row level security in PeopleCode, but in general you’re better off using the mechanisms that were intended for security.
Labels: PeopleCode, Security