Showing posts with label Plugins. Show all posts
Showing posts with label Plugins. Show all posts

Sunday, November 19, 2017

PeopleTools 8.56 Hidden Gem | HTMLAREA 'Respond Only Once' Property

While working on some quirks with reCAPTCHA implementation in a PeopleSoft PIA page, I stumbled on this scarcely documented, hidden gem in PeopleTools 8.56. For many years, we struggled with HTMLAREAs and how they behave with AJAX requests in PeopleSoft. Basically, HTMLAREAs get reloaded every time there is an AJAX request on the page which puts the responsibility on the developer to make sure any javascript code in the HTMLAREA continues to work as expected. Jim's post dating back to 2006 illustrates how long this has been a problem!

I ran into a similar problem with the reCAPTCHA implementation and I wrote additional javascript code to workaround the issue. In the process, I found this HTMLAREA page field property called 'Respond Only Once' which is new in PeopleTools 8.56. This property is not documented in PeopleBooks except for this one location as a related topic:
PeopleBooks - PeopleTools 8.56 - Field Class Properties

Based on what I found, this property when selected will exclude the HTMLAREA from AJAX requests. A total life saver! :)

Of course, the HTMLAREA will be included in the Save event (postback).

Demonstration of Problem

In this demo we can see how the reCAPTCHA plugin (as an example) which is generated by a HTMLAREA gets reloaded/refreshed on every AJAX requests. On the second server trip, the reCAPTCHA div will disappear because the reCAPTCHA API javascript is no longer loaded as expected.

HTMLAREA


Demo

We can see how the HTMLAREA is reloaded every server trip resulting the disappearance of the  reCAPTCHA plugin.


Respond Only Once Property

Let us set the 'Respond Only Once' property in the HTMLAREA.


Demo

In the following demo, we can see how the 'Respond Only Once' property helps to exclude the HTMLAREA from the AJAX requests and to avoid reloading its contents.


Saturday, November 18, 2017

reCAPTCHA in PeopleSoft PIA Pages

In one of my previous blog posts, I showed how to implement reCAPTCHA 2.0 in PeopleSoft. My blog post only covered setting up the reCAPTCHA plugin on the PeopleSoft login page as a workaround for DOS, bot attacks, etc. I also mentioned that the effort to implement reCAPTCHA in a PeopleSoft PIA page (Classic/Fluid) should be very similar. But I found that there is one challenge with implementing the same client side code in the PIA (as noted by some comments in the post). The issue is a common problem we routinely run into when we combine a HTMLAREA (with JavaScript) and a PIA page! Every time there is an event that posts back to the server, the entire page is refreshed. Obviously and unfortunately for us, this will cause the HTMLAREA to reload as well. If there is javascript in the HTMLAREA and if we are referencing external scripts (as we do in reCAPTCHA), there is a risk that the script will be reloaded and any variables may be reset. In order to workaround this problem, we need to be extra careful with writing javascript in HTMLAREA making sure we properly 'manage' how our code is executed during such events. This is true for all cases not specific to this reCAPTCHA implementation.

To demonstrate the problem, I added the reCAPTCHA plugin (client side) code to a Classic PIA Page using a HTMLAREA.

Classic Page


HTMLAREA and Page Activate PeopleCode

The HTMLAREA is populated dynamically using Page Activate PeopleCode.


JavaScript and HTML for reCAPTCHA

The javascript and HTML needed to display the reCAPTCHA plugin is stored in a HTML object (CSK_RECAPTCHA).


Result

We can see that the reCAPTCHA plugin is displayed successfully on the page.


Demonstration of Problem

Basically, on the second postback the reCAPTCHA API javascript will no longer load and therefore result in the reCAPTCHA div to disappear. In the demo, we can see the problem occurs during the FieldChange (Server Trip) and the Save events.


Solution

To solve this problem, instead of directly using the script element in the HTMLAREA to reference the reCAPTCHA API javascript, I wrote a javascript function to load the script in the DOM.

Result


reCAPTCHA Callback Function

You may notice that there is another function called svRecaptchaCallback and it is used as the data-callback attribute value in the reCAPTCHA div element. This callback function is a great feature that is available with reCAPTCHA which allows us to execute our custom code upon a successful reCAPTCHA event. You can see in the following demo that the message is printed on the console once we complete a successful reCAPTCHA verification. As an example, this could be used to conditionally activate/display certain page field elements only after a successful reCAPTCHA verification. Please note that this is purely on the client side. That is, the callback function is available and executed on the browser as part of our HTMLAREA. This is not the same as the server-side validation!


Notes

- Environment Details: HCM 9.2 PUM Image 23, PeopleTools 8.56.01.
- The main focus of this post is the client-side implementation. The server side validation logic can be implemented based on the code provided in my previous post. Only difference here is that we will be executing the PeopleCode in a event such as SavePreChange or similar instead of the SignOn PeopleCode event.
- The implementation in this post is done as a proof of concept only. When implementing reCAPTCHA in a PIA page, we may also want to consider only prompting the user with the reCAPTCHA validation once. Prompting the users to confirm that they are not robots on every Save event might not result in a great user experience.

Sample Project on GitHub

https://github.com/SasankVemana/reCAPTCHA-in-PIA

Wednesday, November 25, 2015

Implementing no CAPTCHA reCAPTCHA in PeopleSoft

This post is based on a great discussion concerning security on the OTN forums.

The requirement was to solve the problem of bots/hacker websites hijacking users to their malicious locations (masquerading the legitimate PeopleSoft site), scraping the credentials from the users and then posting the data into the PeopleSoft signin page in a typical phishing attack scenario.

If you read through the discussion, you will notice some very valid questions, concerns and suggestions provided by Greg Kelly from Oracle and others around how to ensure that such phishing emails and attacks can be prevented.

Outside of that discussion, traditionally CAPTCHA has been used in several websites to prevent bot attacks. Now Google's reCAPTCHA project is being used more commonly since its inception in 2009. The latest version (no CAPTCHA reCAPTCHA) has significant user experience improvements. Additionally, the reCAPTCHA API version 2.0 is now a RESTful API which makes server side validation a lot easier. Another great incentive to use Google's no CAPTCHA reCAPTCHA is the fact that it is FREE!

Before going down the path of implementing reCAPTCHA, please consider accessibility and user experience implications and test accordingly. Click here for an article that talks about accessibility features of reCAPTCHA.

Here are the steps to implement Google reCAPTCHA API version 2.0 in PeopleSoft.

Note: I am currently using a HCM 9.2 PUM Image 12 - PeopleTools 8.54.08.
Reference Document: Developer's Guide

Step 1: Sign up for an API key pair

Please click here to sign up on the Goolge reCAPTCHA website. Once you sign up for an API key pair to your site, you will be provided with two keys - secret key and site key.

Step 2: Client side integration

In this case, let us assume that we want to add reCAPTCHA to the PeopleSoft signin page. So the signin page will be our client side content where we would add the reCAPTCHA code.

Here are the instructions from the Google reCAPTCHA documentation:


Let us add the above code snippet to the PeopleSoft signin page (signin.html).

Note: We can locate the signin.html file in the following directory on the web server.
<PIA_HOME>/webserv/<DOMAIN>/applications/peoplesoft/PORTAL.war/WEB-INF/psftdocs/<site_name>/

Add the following script inclusion code just before </HEAD> as shown:
<!-- CSK reCAPTCHA - Start -->
<script src='https://www.google.com/recaptcha/api.js'></script>
<!-- CSK reCAPTCHA - End -->


 Add the following div (reCAPTCHA) in an appropriate location on the content page. I chose to add it right before the submit button which could be referenced by <input name="Submit" type="submit" title="<%=137%>" class="ps-button" value="<%=137%>">.

<!-- CSK reCAPTCHA - Start -->
    <div class="g-recaptcha" data-sitekey="<ENTER_YOUR_SITE_KEY_HERE>" align="center"></div>
    <br/>
<!-- CSK reCAPTCHA - End -->


Note: If you are on PeopleTools 8.54 then you might also want to perform the same customizations to signin_fmode.html file as well. This is due to a known issue that will be fixed in PeopleTools 8.55. Refer: E-FLUID - Fluid HomePage Sign Off Link Calls fmode=1 in URL, Skips Custom signout.html Page (Doc ID 2001761.1).

Please bounce and clear the cache on your web server domains. Let us now see the reCAPTCHA plugin in action on the client side.






We are not done yet! Once verified, the reCAPTCHA integration would additionally add a string with the name "g-recaptcha-response" to the payload when the user submits (form post). This string would be a key that is generated specifically for our site. The string needs to be validated on the server side which we will explore in the next section.

Step 3: Server side integration/validation

This is the step where we verify the string provided by reCAPTCHA for validity by making a REST API call. Instructions from Google reCAPTCHA documentation.


For more details: Refer API documentation.

In this case, since we are trying to validate the reCAPTCHA response string provided by the PeopleSoft signin page, the best place to add the validation logic would be in the SignOn PeopleCode.

Let us now add a new row/entry in the sequence of Signon PeopleCode events as shown in the following screenshot. I am referencing a custom function name which I will explain shortly.


Record: CSK_RECAPTCHA
Field Name: FUNCLIB
Event Name: FieldFormula
Function Name: CSK_RECAPTCHA_CHECK

Note: After making any changes to Signon PeopleCode we must bounce the app servers for them to take effect.

Now let us see how to write some custom code to validate the reCAPTCHA response string. For reference, I pasted the entire peoplecode at the very end of this post.

Click on image to zoom in!


Note: In this case, I am using Apache Commons HttpClient Java Libraries to make the REST API call. Please refer to my previous blog posts that have more details on this topic (Part I and Part II).

Details on custom function validate_reCAPTCHA_JSON is provided below. For the purposes of JSON parsing, I am using a server side scripting technique described by Jim Marion in his blog post

Click on image to zoom in!


Message Catalog Entry that contains the JSON Parsing Script:


Script for reference:

var result = (function() {

     var json = JSON.parse(json_string);

     if (json.success) {
          return "true";
     } else {
          return "false";
     }

}());


This completes our server side integration/validation. Now we are relatively free of bot attacks! :)

Note: The same feature can be applied to any content page within the PeopleSoft application as well. If not easier, the effort should be the same as what we just went through in this post.

PeopleCode Functions for reference:

Function validate_reCAPTCHA_JSON(&json As string) Returns boolean;
  
   Local string &success;
  
   /* Instantiate ScriptEngine Manager and Engine objects */
   Local JavaObject &manager = CreateJavaObject("javax.script.ScriptEngineManager");
   Local JavaObject &engine = &manager.getEngineByName("JavaScript");
  
   /* Pass JSON string */
   &engine.put("json_string", &json);
   /* Get JSON Parse JavaScript from Message Catalog */
   Local string &jsFunction = MsgGetExplainText(26000, 1, "NONE");
  
   If &jsFunction <> "NONE" Then
      &engine.eval(&jsFunction);
      &success = &engine.get("result").toString();
   End-If;
  
   If Upper(&success) = "TRUE" Then
      Return True;
   Else
      Return False;
   End-If;
  
End-Function;

Function CSK_RECAPTCHA_CHECK()
  
   /* Get reCaptcha parameter from the Request */
   Local string &reCAPTCHA = %Request.GetParameter("g-recaptcha-response");
  
   If &reCAPTCHA = "" Then
      /* Fail Authentication */
      SetAuthenticationResult( False, %SignonUserId, "", False);
   Else
      /* Do further validation if required. Refer: https://developers.google.com/recaptcha/docs/verify */
      /* Post user's reCAPTCHA response and server's private key to API: https://www.google.com/recaptcha/api/siteverify */
      try
        
         /* Using Apache HttpClient for REST - Post Method */
         Local JavaObject &jHttp, &jMethod, &filePart, &partArray, &mPartReqEntity;
        
         /* Initialize HttpClient and set parameters */
         &jHttp = CreateJavaObject("org.apache.commons.httpclient.HttpClient");
         &jHttp.getHttpConnectionManager().getParams().setConnectionTimeout(20000);
        
         /* Initialize PostMethod */
         /* !!!!!! Avoid hardcoding !!!!!!!! Replace below URL with a URL definition that is configurable. */
         Local string &sURL = "https://www.google.com/recaptcha/api/siteverify";
         &jMethod = CreateJavaObject("org.apache.commons.httpclient.methods.PostMethod", &sURL);
         &jMethod.setFollowRedirects( False);
        
         /* Add Multi-Part Message - Start */
         /* Create String Part - secret */
         &secretPart = CreateJavaObject("org.apache.commons.httpclient.methods.multipart.StringPart", "secret", "<ENTER_YOUR_SECRET_KEY_HERE>");
         /* Create String Part - response */
         &responsePart = CreateJavaObject("org.apache.commons.httpclient.methods.multipart.StringPart", "response", &reCAPTCHA);
         /* Add Parts to Part Array */
         &partArray = CreateJavaObject("org.apache.commons.httpclient.methods.multipart.Part[]", &secretPart, &responsePart);
         /* Create Multi-Part Request Entity */
         &mPartReqEntity = CreateJavaObject("org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity", &partArray, &jMethod.getParams());
         /* Add Multi-Part Request Entity to the Post Method */
         &jMethod.setRequestEntity(&mPartReqEntity);
         /* Add Multi-Part Message - End */
        
         /* Invoke PostMethod */
         Local integer &return = &jHttp.executeMethod(&jMethod);
         Local string &responseBody = &jMethod.getResponseBodyAsString();
        
         If (validate_reCAPTCHA_JSON(&responseBody)) Then
            /* reCaptcha success: allow user */
            SetAuthenticationResult( True, %SignonUserId, "", False);
         Else
            /* reCaptcha failure: deny */
            SetAuthenticationResult( False, %SignonUserId, "", False);
         End-If;
        
      catch Exception &ex
         /* Unknown Exception */
         SetAuthenticationResult( False, %SignonUserId, "", False);
      end-try;
   End-If;
End-Function;

 

Sunday, October 4, 2015

Fluid - WYSIHTML5 Editor Prototype!

I recently answered a question on the OTN forums related to rich text editor in PeopleSoft. Since PeopleTools 8.50, PeopleSoft has leveraged using CKEditor for rich text editor (aka RTE) configurations options in App Designer. As a follow up to the OTN, I wrote a small post on how to create and use custom RTE configurations, toolbars and plugins.

CKEditor in PeopleTools provides a way to create and work with a WYSIWYG (What You See Is What You Get) rich text editor.

This has found its way to several use cases ranging from but not limited to:
-    Rich text configuration fields which are then used for rich text display in HTMLAREAs
-    Content source for rich text enabled emails
-    Content source for rich text enabled BI Publisher reports
-    Content source for Enterprise Components Forms Builder – Instructions
-    Content source for rich text enabled Student Activity Guide (Configurable) Pages such as Agreement Pages, Start and Complete Pages

While this is a great utility, it is a WYSIWYG editor which means that it might only be appropriate for Classic pages and might not be suitable for Fluid. I was curious to see how a rich text enabled field appears on a Fluid page and based on my tests it appears that Fluid does not support rich text enabled fields.

RTE Field on a Fluid Page:



Results: RTE toolbar does not appear in Fluid.


We can also confirm that rich text is not supported for Fluid in PeopleBooks.

Home > PeopleSoft > PeopleTools 8.54 > Fluid User Interface Developer’s Guide > Considerations for PeopleSoft Fluid Application Implementation


We can imagine how RTE powered by CKEditor (WYSIWYG) would introduce several challenges when it comes to incorporating the editor in Fluid. But why not WYSIHTML5 - What You See Is HTML5? :)

So that is how I got started on this little pet project!

I wanted to take the same concept and create a rich text editor that is also responsive (WYSIHTML5). I used an open source project (http://wysihtml.com/) to develop a prototype for a WYSIHTML5 Editor in PeopleSoft (Fluid) that enables Responsive Rich Text.

It is still a prototype so it has a few quirks to be worked around and it is also not a fully functional RTE yet. But I think it is a great start!

Step 1: Load Open Source Project to the Web Server

Based on instructions in the http://wysihtml.com/ I downloaded the open source project (zip file), extracted/unzipped the contents and placed it on the web server.

Path:

<PIA_HOME>/webserv/<DOMAIN>/applications/peoplesoft/PORTAL.war/<site_name>


Contents:


This completes the first step to make the necessary javascripts and stylesheets (amongst other things) available on the web server.

Now moving on to incorporating this in PeopleTools.

Step 2: Create Fluid Page with WYSIHTML5 Editor (Configuration)


Legend:

1. Static HTMLAREA (1) is used to store a javascript function and a button which when invoked transfers the WYSIHTML5 contents in HTMLAREA (4) to an invisible - modifiable by javascript - long edit field (2).


The "csk_div" ID used in var x = document.getElementByID("csk_div"); is referencing an input field (WYSIHTML5 editor) in HTMLAREA (4).

2. Invisible (Modifiable by Javascript) field to temporarily store/move (PreSave) the WYSIHTML5 contents from HTMLAREA (4) to the component buffer. This helps with sending the HTML5 contents to the server during the save (3). This is kind of a hack/temporary workaround and there should be a cleaner way to get this to work. It is a "to-do" item to make this more efficient.


 
3. Save button to push data (component buffer) in the page to the server.



4. HTMLAREA that holds the WYSIHTML5 contents with an input/editable field (and other associated wysihtml toolbar items, styling and scripts). HTMLAREA is populated using PageActivate PeopleCode using a HTML object (CSK_WYSIHTML5).



CSK_WYSIHTML5 HTML object was built primarily based on the HTML in this example page:
http://voog.github.io/wysihtml/examples/advanced.html

Few things to note about CSK_WYSIHTML5 HTML:

- An ID attribute ("csk_div") was added to a DIV that represents the input/editable element for the HTML5 editor. This is needed because it is used in the javascript function that is part of the Static HTMLAREA (1).
- The contents in the HTML5 editor field (csk_div) are passed in using a bind variable (via Page PeopleCode).
- The script sources were appropriately adjusted to refer to the directory on the web server (where the wysihtml project is located).


Step 3: Create Fluid Page for WYSIHTML5 Display (Viewer)



This is a very simple Fluid page with a single HTMLAREA that is loaded on PageActivate as shown above. During the load,  the HTML5 contents that was created and stored using the previous page (CSK_WYSIHTML5_CFG) is retrieved and used as a parameter to HTML object (CSK_WYSIHTML5_DISP). The HTML retrieved from CSK_WYSIHTML5_DISP is them assigned to the HTMLAREA field.

CSK_WYSIHTML5_DISP was also primarily built using the following page:
http://voog.github.io/wysihtml/examples/advanced.html

Only differences are:
- Toolbar was removed (as it is a display only page).
- Made the editor display only (non-editable).
- Added a bind value to place the HTML5 contents using PageActivate code.


Let us see this in action!! 

I created a custom Fluid Hompage (Sasank's WYSIHTML5) and added the two Fluid Pages as tiles.



Fluid Page with WYSIHTML5 Editor Prototype:

- Enter "Rich Text"/Responsive contents in the editor.
- Click on "PreSave (Load to Buffer)" button.
- Click on "Final Save" button.


Legend:
1. Push buttons to save responsive rich text data.
2. Responsive rich text toolbar.
3. Responsive rich text editor.

Quirks:
- Right now, the page just refreshes if we press ENTER/carriage return on the editor. ENTER/carriage return only works when the cursor is on text that does not contain any styling. This is also a "to-do" task.
- We must click the "PreSave (Load to Buffer)" button first before clicking the "Final Save" button, otherwise the changes made in the editor will not get transferred to the server as part of the component buffer.

Fluid Page with WYSIHTML5 Display Prototype:



We can see how the rich text displayed on this page in a HTMLAREA is responsive!

Demo Videos!!

WYSIHTML5 Responsive Rich Text Editor (click here to view video in a new tab):

WYSIHTML5 Responsive Rich Text Display (click here to view video in a new tab):

I just wanted to share this project with the PeopleSoft community! A lot of javascript hacking and app designer cheats (workarounds if you will) were required to get this prototype to function. I would love to work with anyone who would like to collaborate on improving this project and see where the results take us! Perhaps a truly integrated Responsive Rich Text Editor… Perhaps a futuristic Web Based Responsive Page Development Utility… Perhaps a case for productization and potential incorporation into the PeopleSoft solution!?!?!?

Project Details:

Disclaimer: I am sharing the project primarily to seek collaborators and others who might be interested in playing with or extending this prototype. If you choose to perform any of below steps then it is at your own risk! :)

Project Environment: HCM 9.2 PUM Image 9 - PeopleTools 8.54.08

1. Download the project by clicking here.
2. Unzip/extract the project and copy it to a testing/play environment (using 'Copy From File' option in App Designer).
3. Build project.
4. Explore! Test! Explore! Test!

Notes:

1. This project which contains the WYSIHTML5 editor prototype for PeopleSoft should be considered a proof of concept only. Please do not load this into your production environment. This was purely intended for experimentation and evaluation purposes.
2. I, the author, will not assume any liability for any problems resulting from the implementation of this project.
3. All objects in the project are custom and start with the prefix "CSK_".
4. A role (CSK_WYSIHTML5_TEST) in the project should give access to both the pages above.

Please feel free to comment on this post if you have any questions/concerns/suggestions.

Thursday, September 24, 2015

Working with Rich Text Editor - Custom Configuration, Toolbars and Plugins

Rich Text Editors (RTE) are being used more commonly with the latest PeopleTools versions. There are several pages that contain Rich Text Editor fields (generally for configuration) which are then used for display on other transactional pages using HTMLAREAs, used as the content for Rich Text enabled emails or used as the content for Rich Text enabled BI Publisher reports (to name a few use cases).

Note: The Rich Text Editor provided by PeopleTools is powered by CKEditor.

Page With Rich Text Editor Enabled Field:

Here is an example of a simple page that contains a Rich Text Editor field. 



The page contains a Long EditBox (CSK_RTE_DATA.DESCRLONG) with the following properties.


We are currently using the default Rich Text Options (Note: Configuration Settings Id is blank). The page appears as follows with the Rich Text Editor for the DESCRLONG Long EditBox. The Rich Text Toolbar is generated based on the default configuration.



Page Displaying Rich Text Data:

Here is an example of a simple page that displays data stored in a Rich Text enabled field using a HTMLAREA.


Page Activate PeopleCode to display the Rich Text data field in the HTMLAREA:


The page display the Rich Text data in the HTMLAREA as follows:



Adding Custom Rich Text Options - Templates, Plugins:

I recently came across an interesting question on the OTN forums. The question was "how to use Rich Text to display an iframe with a link to a youtube video?". If you look at the above Rich Text Editor field that uses the default Toolbar, it does not have the ability to add any HTML tags or specifically IFRAME content.

To enable additional/custom Toolbar items on the Rich Text Editor, we must first create our own custom Rich Text Editor Configuration.

Creating a Custom RTE Configuration:

We need to create a new HTML definition with a name that starts with 'PT_RTE_CFG'. Let us create a custom HTML definition called PT_RTE_CFG_CSK cloned from PT_RTE_CFG_PTPPB (delivered RTE Configuration).


Now to enable a custom Toolbar item for embedding an IFRAME, we must make use of additional plugins. To find the list of all available plugins as delivered, we can look in the following directory on the web server:

<PIA_HOME>/webserv/<domainname>/applications/peoplesoft/PORTAL.war/<sitename>/ckeditor/plugins

Fortunately, in this case the IFRAME plugin for CKEditor is already available as delivered (if not we must download and place the required plugins in the above folder path).


Let us now add the custom IFRAME Toolbar to our Custom RTE Configuration (PT_RTE_CFG_CSK). Let us include the following additional line in the configuration (note the comma in the screenshot).

  { name: 'insert', items : [ 'Image','Flash','Table','HorizontalRule','Smiley','SpecialChar','PageBreak','Iframe' ] }



Moving ahead, let us reference this Custom RTE Configuration in the Page Field Properties of the Rich Text enabled field.



Now let us take a look at the page with the Rich Text enabled field.


We can see the additional/custom Toolbar that we added to our Custom RTE Configuration. This would help us with embedding an IFRAME element that links to a youtube video.




This results in an embedded IFRAME as follows:


Testing IFRAME on the Display Page:


Similarly, we can add additional custom Toolbars to our Custom RTE Configuration. Hope you find this useful!

Environment details at the time of writing this post:
HCM 9.2 PUM Image 12 (PeopleTools 8.54.08)

Reference:
PeopleBooks - Modifying the Rich Text User Interface