Bridging the gap to Fusion through our PeopleSoft Solutions Extenders
Grey Sparling PeopleSoft Expert's Corner
Oracle Blogs
 Subscribe Now!

Wednesday, September 26, 2007

Security Zone Management in Internet Explorer

Internet Explorer manages a whole host of security settings through the concept of security zones. Security zones have names such as Internet, Intranet, Trusted Sites. There's also the concept of a Custom zone, which just means that you've gone in and set one of the lower level security settings specifically.

Each time you load a web page, you can see on the bottom right hand status bar in IE, which zone that it thinks that it is in. One thing that catches some people is that IE does not have any sort of automatic facility to detect what is your corporate domain. Even though you may have done Windows level authentication to "mycompany.com", you'll still notice that when you visit "psft.mycompany.com", IE will flag that as an Internet site.

You can manually change these settings for particular sites/domains through Internet Explorer (Tools -> Internet Options -> Security), but if you have lots of machines to update, it's probably better to use some automation.

Microsoft provides some tools for doing this, but in the case of just adding a single site or domain, you can also go through and just push out updates via .reg files. If you've never pushed out any registry changes via a .reg file, it's not hard, but you definitely want to be careful because if you screw up the registry in Windows you can cause a lot of damage. There are probably people within your organization that can handle this though.

So, with that caveat out of the way, what does a .reg file look like for adding your PeopleSoft servers to the Intranet zone? Assuming that the server names are psfthr, psftfin, psftcrm and are all in the mycompany.com domain and just running http, then this is what you'd have.
Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\Domains\mycompany.com]

[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\Domains\mycompany.com\psfthr]
"http"=dword:00000001

[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\Domains\mycompany.com\psftfin]
"http"=dword:00000001

[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\Domains\mycompany.com\psftcrm]
"http"=dword:00000001
Not too bad. How about if we just want to flag the entire mycompany.com domain as the Intranet?
Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\Domains\mycompany.com]
"*"=dword:00000001
Before making changes like this, you'll want to check that you don't already have any custom settings for your standard workstations. If so, then you'll need to merge these changes in with however those settings get deployed in your organization.

If not, then you can save your own versions of these files with a .reg extension, and they'll be ready for importing. You can use the /quiet flag for regedit to add this as part of your user's Windows login scripts.

Labels:

Tuesday, September 25, 2007

Insatiable Application Classes

While double-checking something in PeopleBooks about Application Classes, I came across this typo.
Generic base classes contain reusable logic for PeopleCode classes; you write them to be self-contained, fully implemented, and insatiable.
I believe that instantiable was the word they were looking for. Heh. Spell-checkers can't save you from those errors.

In case you care, what I was looking for was a way to make the constructor for a base class only available to subclasses. The base class provides a bunch of functionality without applying any specific security rules. The subclasses fill in the security details for their specific requirements.

App Designer will let you save the constructor as protected, but it actually makes the constructor public at runtime. Good thing I tested that :-)

PeopleBooks does say that what I want to do is not allowed (constructors have to be public), which is unfortunate. The workaround is to have a separate "validate" method that sets an internal flag once called. The base class version throws whatever error you want to give, and the subclass version(s) perform the proper checking. That adds extra complexity to the methods in the base class though since they need to check the internal flag at the beginning of each method before doing their "real" work.

The alternative would be to just put a few comments in the base class code saying "Please don't use this class directly as it can be a security problem". Everyone reads comments in the code before using it though, right? :-)

Labels:

Monday, September 24, 2007

Code to Drill to any Chartfield Combination on Journal Entry Page

So, you have a journal with several hundred lines in it, and you want to find the lines that hit a particular account, fund code, and program code. You have a query that tells you it's there, but you want to pull up the journal entry itself to review it there.

This is the culmination of the last two posts with a few extra tidbits, such as array handling, rowset handling, and using variables to pick the field you want to use.

This posting shows how to pass any chartfield combination on the URL for accessing the journal entry page, allowing the navigation to the journal line(s) that contain those chartfield values. The code is written against Financials 8.9, but should work for previous versions.

Using a variable as a field reference?

Yes. One of the key items in the solution is the ability to evaluate a variable to get a fieldname in a record.field reference (this is how I'm able to take the list of chartfields from the BU_LED_CF_VW and use them). For those who aren't familiar with this, you can use @("RECORDNAME." | &VariableName) to do this. We often wrap this syntax with GetRecord or GetField to make it more error-proof in some of our other products.

Solution to the problem

The code does the following:

  • It matches up the valid chartfields with parameter names passed on the command line
  • It determines whether the journal is editable.
  • If it is editable, then it uses the SetCursorPos function
  • If it isn't editable, then it sets the work fields that the adjust_line_scroll() function uses

Here's the code (it should be added in the page activate Peoplecode after the PeopleSoft-delivered page activate PeopleCode in the JOURNAL_ENTRY2_IE page).

/* Grey Sparling - Call function to return journal lines with chartfield values */
Declare Function adjust_line_scroll PeopleCode FUNCLIB_GL.JOURNAL_LINE FieldFormula;

/* Grey Sparling - Code to drill to row with chartfield values passed in as a parameter */
Local Rowset &RS_CFS = GetRowset(Scroll.BU_LED_CF_VW);
Local string &sChartField;
Local number &sNumParameters = 0;
Local boolean &PassedParameters = False;
Local array of string &CF_Params;
Local array of string &CF_ParamValues;
Local number &m;

&CF_Params = CreateArray(&sChartField);
&CF_ParamValues = CreateArray(&sChartField);

/* Grey Sparling - Build Array with all the parameters passed in the Request Object */
For &l = 1 To &RS_CFS.ActiveRowCount;
    &sChartField = &RS_CFS(&l).BU_LED_CF_VW.CHARTFIELD.Value;
    &CF_ParamValues [&sNumParameters + 1] = %Request.GetParameter(&sChartField);

    If All(&CF_ParamValues [&sNumParameters + 1]) Then
      &CF_Params [&sNumParameters + 1] = &sChartField;
      &PassedParameters = True;
      &sNumParameters = &sNumParameters + 1;
    End-If;
End-For;

/* Grey Sparling - Use the parameters in the array to find the appropriate set of Journal Lines */
If &PassedParameters Then
    If JRNL_HEADER.JRNL_HDR_STATUS = "D" Or
      JRNL_HEADER.JRNL_HDR_STATUS = "P" Or
      JRNL_HEADER.JRNL_HDR_STATUS = "U" Then
      /* Grey Sparling - Journal is read only */
      /* Grey Sparing - Loop through parameters array and set them in work record for searching */
      For &m = 1 To &sNumParameters;
        @("JRNL_PANELS_WRK." | &CF_Params [&m]) = &CF_ParamValues [&m];
      End-For;

      adjust_line_scroll();
    Else
      /* Grey Sparling - Journal is editable */
      Local Rowset &rsJrnlLines = GetLevel0().GetRow(1).GetRowset(Scroll.JRNL_LN);
      Local number &j;

      /* Grey Sparling - Loop through Journal Lines in Panel Buffer to find first one that matches combination of parameters */
      For &j = 1 To &rsJrnlLines.ActiveRowCount
        Local Row &rowTest = &rsJrnlLines.GetRow(&j);
        &sFoundCombination = True;

        /* Grey Sparling - Loop through fields in array to see if current row matches all passed parameters */
        For &m = 1 To &sNumParameters;
          If &rowTest.GetRecord(Record.JRNL_LN).GetField(@("Field." | &CF_Params [&m])).Value = &CF_ParamValues [&m] Then
            &rowTest.GetRecord(Record.JRNL_LN).GetField(@("Field." | &CF_Params [&m])).SetCursorPos(%Page);
          Else
            &sFoundCombination = False;
          End-If;
        End-For;

        If &sFoundCombination Then
          Break;
        End-If;
      End-For;
    End-If;
End-If;

Labels: ,