PeopleCode | Executing PeopleCode immediately upon user sign on
A. Purpose of Sign-on PeopleCode
The vast majority of PeopleCode is attached to App Designer objects. While this works in most cases, there are some situations where object-based PeopleCode is impractical.
For instance, you might be faced with a task that requires code to be executed as soon as the user logs into the system. This could be needed for any number of reasons: (1) connecting to an LDAP service for user authentication, (2) performing additional security validation not handled by existing functionality, (3) transferring the user to a ‘message of the day’ style of page, or (4) transferring the user directly to another page that needs urgent attention.
Fortunately, Sign-on PeopleCode is capable of assisting you in all these cases. It can however be a challenge to implement. Even though the configuration page looks simple enough at first glance, trying to get Sign-on PeopleCode to work correctly often requires a fair amount of analysis and trial-and-error, not to mention a lot of care and patience. You can easily lock all users out of the system (including yourself) if you happen to add the wrong code.
In particular, there’s the question of which Sign-on PeopleCode function you should change. In general, developers are told not to amend Oracle delivered objects and instead use custom objects when setting up new code. However, this can be difficult to enforce when dealing with Sign-on PeopleCode. Some of the delivered sign-on code performs essential tasks (such as verifying the user’s credentials), so this code shouldn’t be inactivated lightly.
In addition, because sign-on functions run sequentially, if one of the higher priority functions halts the code for whatever reason – for instance, by redirecting the user to a component – this has the effect of negating any future code. This means you cannot simply place a custom function at the bottom of the configuration page, hoping it will run after the various delivered functions have carried out their tasks. The App Server may never actually reach the bottom of the list after processing (and terminating) all the prior code.
Changes to Sign-on PeopleCode therefore require a delicate balancing act. How do you continue to use the existing functionality, while at the same time, allowing your own custom code to run? In many cases, it’s easier to amend the delivered code.
Before we proceed with a couple of simple examples, keep in mind that Sign-on PeopleCode can only be attached to Record PeopleCode. There is no support for Application Packages and other forms of PeopleCode.
B. Sign-on Configuration
Firstly, to determine which sign-on PeopleCode functions currently exist on your system, navigate to the following page:
PeopleTools -> Security -> Security Objects -> Signon Peoplecode
This will present you with a grid of all available sign-on functions, along with an ‘Enabled’ column that indicates whether the the function is currently active:
Also note the Sequence Number which specifies the order in which the functions should be executed. This is important to note when deciding where to place any custom code.
Next, we turn to two examples of functions created for sign-on purposes.
C. Example 1 – Display Message
For our first example, we will display a simple welcome message to the user. As we’ll see, this isn’t a terribly useful example, but it does help to display some of the core concepts surrounding Sign-on PeopleCode.
Firstly, create a new work record and insert a single field into the record:
Open up one of the PeopleCode events attached to the field. In the case of my example, I’m going to use FieldFormula. Then in this event, add your Sign-on PeopleCode as a function:
Function ShowMessage Local Record &Operator_Rec = CreateRecord(Record.PSOPRDEFN); &Operator_Rec.OPRID.Value = %SignonUserId; &Operator_Rec.SelectByKey(); SetAuthenticationResult(True, %SignonUserId, "Welcome " | &Operator_Rec.OPRDEFNDESC.Value, False, 0); End-Function;
This displays a welcome message to the user based on the system variable %SignonUserId. The usual message functions such as ‘MessageBox’ do not work in Sign-on PeopleCode. To get around this (in a quick-and-dirty kind of way), I am using the ‘SetAuthenticationResult’ function, passing in a piece of text as a third parameter.
Now open up the delivered record FUNCLIB_PWDCNTL. Open the FieldChange event on the PWDCNTL field. At the top of the code, add a reference to your new function:
And then in the function itself, make a call to the ‘ShowMessage’ function. When developing Sign-on PeopleCode, it’s important to wrap the code with your own user ID, at least as a starting point. That way, your change should not impact other users:
Now try logging into the system via the browser. You should receive a simple welcome message:
As I said, not a terribly helpful example as you can’t do anything further after receiving the message, except return to the sign-on page. But it does help to quickly demonstrate how Sign-on PeopleCode works, without getting into too many complexities.
D. Example 2 – Transfer to Component
Next we look at a slightly more useful example. This function transfers the user directly to a component via the use of ‘GeneralComponentContentURL’ and ‘SetAuthenticationResult’. Note that any form of ‘transfer’ function will produce an error if the user does not have security over the destination page.
Again, we start by creating our ‘Transfer’ code as a function. I will use the same record, field and event as before:
Function TransferUser Local string &url = GenerateComponentContentURL(Portal.EMPLOYEE, Node.HRMS, MenuName.MAINTAIN_SECURITY, %Market, Component.CHANGE_PASSWORD, Page.CHANGE_PASSWORD, %Action_UpdateDisplay); &message_text = "Your password needs to change. <a href='" | &url | "'>Click here to continue</a><p>"; SetAuthenticationResult(True, %SignonUserId, &message_text, False); End-Function;
Then, in the FUNCLIB_PWDCNTL record, we amend the code we previously added to call the new TransferUser function:
Upon logging you, the user now receives the message about changing their password: