PSQuery Record Security

GitHub

PT 8.60
Randall Groncki

*Note: SQL in this post and in the attached PeopleTools Zip file has been updated with more efficient code.

Introduction

Users have access to records in PSQuery through the Query Access Manager. Records are assigned to Query security trees. However, finding the bigger picture of what records a user has access to through many roles and permission lists is somewhat daunting. Just as difficult, questions about which roles and permission lists have access to a specific record can be a trip down the multiple rabbit holes.

I’ve created a few PSQiueries and SQL statements to help clarify the current relationships between the Records, Roles and Users. Hopefully these can help you adjust security in your implementation so your PSQuery users have correct record access.

PSQuery Record Security Refresher

Query administrators assign records to one or more Query Security trees to allow and control access to the record. This is not row level security for that record, but just whether a user has access to a record at all.

Using the Query Access Manager, administrators assign records to one or more Query Security Trees. The records can appear on multiple trees and also appear on the same tree multiple times on different branches.

Navigation: Menu > PeopleTools > Security > Query Security > Query Access Manager.

Administrators then use permission lists to grant access to these records by granting access to a node on one or more Query Security Trees. Access can be granted at the root node which allows access to every record on that tree or they can grant access to a branch of that tree. Granting access to a tree branch enables records on every record and child branch of that tree.

Navigation: Menu > PeopleTools > Security > Permissions and Roles > Permission Lists (Query Tab)

Click on the “Access Group Permissions” link

Unchecking the Accessible box denies access to the records in that tree branch to this permission list.

The permission list is assigned to a role and any user that has that role has access to these records in PSQuery.

Where it gets confusing…

A role can have many permission lists and users have multiple roles. On the other hand, records are assigned to trees and can appear on the same tree multiple times.

There is a many to many relationship between the user and the records with multiple roles, permission lists and trees granting access to a record, sometimes multiple times.

The same record can be granted to a user multiple times through different roles, permission lists and trees.

A better view of the situation.+

Functional Users

Download the PeopleTools project from GitHub or PeopleToolsTechTips.com and have your developers load it to a demo or development environment. This project contains a new view and five prompted queries to show the relationships between PSQuery Records and tress, users, permission lists and roles.

Query NameDescription
X_PT3_QUERY_SEC_RECORDS_PLWhat PList can see Query Rec
X_PT3_QUERY_SEC_PL_RECORDSWhat records can PL see
X_PT3_QUERY_SEC_USER_RECORDSWhat recs can a user see
X_PT3_QUERY_SEC_RECORDS_ROLESWhat roles can see Query Rec
X_PT3_QUERY_SEC_RECORD_USERSWhat users can see a Query Rec

Here is the records you will need access in order to use these Queries:
• X_PT3_QRYSEC_VW
• PSROLEUSER
• PSROLECLASS

Here is a sample result of X_PT3_QUERY_SEC_PL_RECORDS query looking at the custom X_PT3 permission list showing what trees, branches, records are granted to this permission list and the Tree Path of that record.

Technical users and Developers

These three tables show you the relationship between a permission list and a record

RecordDescription
PS_SCRTY_ACC_GRPThis is the child record in the permission list that connects a permission list to a specific tree and node
PSTREENODEThe detailed definition of the trees. This is the actual records and branches.
Each row of this table defines the record name or the branch name and it’s immediate parent node
PSTREEDEFNTop level tree definition. This record will provide the correct effective date and whether the tree is active.

The work is done on the PSTREENODE table by using a revers SYS_CONNECT_BY_PATH in the SQL to show the path from the target record on the tree up through the hierarchy to the root node.

The core is a view the connects the path of the record up through the parent tree nodes using the Oracle SYS_CONNECT_BY_PATH SQL function. This may not work in DB2 or other PeopleSoft supported databases – you may have to adjust your code if you are not using Oracle DB.

SELECT CONNECT_BY_ROOT P.TREE_NODE AS RECNAME,
			P.TREE_NAME,
			P.EFFDT,
			P.TREE_NODE_TYPE ,
			P.SETID ,
			REVERSE(LTRIM(SYS_CONNECT_BY_PATH (REVERSE(P.TREE_NODE),' >- '),' >- ')) AS TREE_PATH ,
			P.TREE_NODE    AS ACCESS_PATH
		  FROM      PSTREENODE P,
				PSTREEDEFN A 
 WHERE P.TREE_NODE_TYPE = 'G' 
				AND P.SETID   = ' '
				AND A.SETID         = P.SETID
				and A.SETCNTRLVALUE = P.SETCNTRLVALUE
				and A.EFFDT         = P.EFFDT
				AND A.TREE_NAME     = P.TREE_NAME
				AND A.TREE_STRCT_ID = 'ACCESS_GROUP'
				AND A.EFF_STATUS    = 'A'
				AND A.EFFDT         =   (SELECT MAX(D.EFFDT)  FROM PSTREEDEFN D
										WHERE D.SETID   = ' '
										AND D.TREE_NAME = A.TREE_NAME
										AND D.EFFDT    <= SYSDATE   )
			START WITH P.TREE_NODE        = 'JOB_MIL'    /* RECNAME */
			CONNECT BY PRIOR P.PARENT_NODE_NUM = P.TREE_NODE_NUM
				  AND PRIOR P.TREE_NAME                = P.TREE_NAME
				  AND PRIOR P.EFFDT                    = P.EFFDT
				  AND PRIOR P.SETID                    = P.SETID
				  AND PRIOR P.SETCNTRLVALUE            = P.SETCNTRLVALUE     

Tying this view in with the other records along with PSROLECLASS (Permission lists in a role) AND PSROLEUSER (Users granted the role) provides a view of all the paths a user has access to a record

What Query Records can a User see

WITH TREE_NODE AS
		  (SELECT CONNECT_BY_ROOT P.TREE_NODE AS RECNAME,
		    P.TREE_NAME,
		    P.EFFDT,
		    P.TREE_NODE_TYPE ,
		    P.SETID ,
		    REVERSE(LTRIM(SYS_CONNECT_BY_PATH (REVERSE(P.TREE_NODE),' >- '),' >- ')) AS TREE_PATH ,
		    P.TREE_NODE    AS ACCESS_PATH
		  FROM      PSTREENODE P,
                PSTREEDEFN A 
      WHERE P.TREE_NODE_TYPE = 'G' 
                AND P.SETID   = ' '
                AND A.SETID         = P.SETID
                and A.SETCNTRLVALUE = P.SETCNTRLVALUE
                and A.EFFDT         = P.EFFDT
                AND A.TREE_NAME     = P.TREE_NAME
                AND A.TREE_STRCT_ID = 'ACCESS_GROUP'
                AND A.EFF_STATUS    = 'A'
                AND A.EFFDT         =   (SELECT MAX(D.EFFDT)  FROM PSTREEDEFN D
                                        WHERE D.SETID   = ' '
                                        AND D.TREE_NAME = A.TREE_NAME
                                        AND D.EFFDT    <= SYSDATE   )
		    CONNECT BY PRIOR P.PARENT_NODE_NUM = P.TREE_NODE_NUM
                  AND PRIOR P.TREE_NAME                = P.TREE_NAME
                  AND PRIOR P.EFFDT                    = P.EFFDT
                  AND PRIOR P.SETID                    = P.SETID
                  AND PRIOR P.SETCNTRLVALUE            = P.SETCNTRLVALUE     )   
SELECT DISTINCT 
  RU.ROLEUSER,
--  RC.ROLENAME,  
--  C.CLASSID,
  B.RECNAME ,
  RD.RECDESCR,
  B.TREE_NAME,
  B.EFFDT,
  C.ACCESS_GROUP,
  C.ACCESSIBLE,
  B.TREE_PATH
FROM 
PS_SCRTY_ACC_GRP C ,
  TREE_NODE B ,
  PSRECDEFN RD
  , PSROLECLASS RC ,
   PSROLEUSER RU
WHERE C.TREE_NAME   = B.TREE_NAME
AND C.ACCESS_GROUP  = B.ACCESS_PATH
 AND RD.RECNAME = B.RECNAME
 AND RC.CLASSID = C.CLASSID 
 AND RU.ROLENAME = RC.ROLENAME
  AND RU.ROLEUSER = 'PT3';  /* User ID Here */

What Query Records can a Permission List See?

WITH TREE_NODE AS
		  (SELECT CONNECT_BY_ROOT P.TREE_NODE AS RECNAME,
		    P.TREE_NAME,
		    P.EFFDT,
		    P.TREE_NODE_TYPE ,
		    P.SETID ,
		    REVERSE(LTRIM(SYS_CONNECT_BY_PATH (REVERSE(P.TREE_NODE),' >- '),' >- ')) AS TREE_PATH ,
		    P.TREE_NODE    AS ACCESS_PATH
		  FROM      PSTREENODE P,
                PSTREEDEFN A 
      WHERE P.TREE_NODE_TYPE = 'G' 
                AND P.SETID   = ' '
                AND A.SETID         = P.SETID
                and A.SETCNTRLVALUE = P.SETCNTRLVALUE
                and A.EFFDT         = P.EFFDT
                AND A.TREE_NAME     = P.TREE_NAME
                AND A.TREE_STRCT_ID = 'ACCESS_GROUP'
                AND A.EFF_STATUS    = 'A'
                AND A.EFFDT         =   (SELECT MAX(D.EFFDT)  FROM PSTREEDEFN D
                                        WHERE D.SETID   = ' '
                                        AND D.TREE_NAME = A.TREE_NAME
                                        AND D.EFFDT    <= SYSDATE   )
		    CONNECT BY PRIOR P.PARENT_NODE_NUM = P.TREE_NODE_NUM
                  AND PRIOR P.TREE_NAME                = P.TREE_NAME
                  AND PRIOR P.EFFDT                    = P.EFFDT
                  AND PRIOR P.SETID                    = P.SETID
                  AND PRIOR P.SETCNTRLVALUE            = P.SETCNTRLVALUE     )   
SELECT DISTINCT 
  C.CLASSID,
  B.RECNAME ,
  RD.RECDESCR,
  B.TREE_NAME,
  B.EFFDT,
  C.ACCESS_GROUP,
  C.ACCESSIBLE,
  B.TREE_PATH
FROM 
PS_SCRTY_ACC_GRP C ,
  TREE_NODE B ,
  PSRECDEFN RD
WHERE C.TREE_NAME   = B.TREE_NAME
AND C.ACCESS_GROUP  = B.ACCESS_PATH
 AND RD.RECNAME = B.RECNAME
AND C.CLASSID       = 'X_PT3';  /* Permission List Here */

What users can see a Query Record?

 WITH TREE_NODE AS
		  (SELECT CONNECT_BY_ROOT P.TREE_NODE AS RECNAME,
		    P.TREE_NAME,
		    P.EFFDT,
		    P.TREE_NODE_TYPE ,
		    P.SETID ,
		    REVERSE(LTRIM(SYS_CONNECT_BY_PATH (REVERSE(P.TREE_NODE),' >- '),' >- ')) AS TREE_PATH ,
		    P.TREE_NODE    AS ACCESS_PATH
		  FROM      PSTREENODE P,
                PSTREEDEFN A 
      WHERE P.TREE_NODE_TYPE = 'G' 
                AND P.SETID   = ' '
                AND A.SETID         = P.SETID
                and A.SETCNTRLVALUE = P.SETCNTRLVALUE
                and A.EFFDT         = P.EFFDT
                AND A.TREE_NAME     = P.TREE_NAME
                AND A.TREE_STRCT_ID = 'ACCESS_GROUP'
                AND A.EFF_STATUS    = 'A'
                AND A.EFFDT         =   (SELECT MAX(D.EFFDT)  FROM PSTREEDEFN D
                                        WHERE D.SETID   = ' '
                                        AND D.TREE_NAME = A.TREE_NAME
                                        AND D.EFFDT    <= SYSDATE   )
            START WITH P.TREE_NODE        = 'JOB_MIL'    /* RECNAME */
		    CONNECT BY PRIOR P.PARENT_NODE_NUM = P.TREE_NODE_NUM
                  AND PRIOR P.TREE_NAME                = P.TREE_NAME
                  AND PRIOR P.EFFDT                    = P.EFFDT
                  AND PRIOR P.SETID                    = P.SETID
                  AND PRIOR P.SETCNTRLVALUE            = P.SETCNTRLVALUE     ) 
SELECT DISTINCT 
  RU.ROLEUSER,
--  RC.ROLENAME,  
  B.RECNAME ,
  RD.RECDESCR,
 -- C.CLASSID,
  B.TREE_NAME,
  B.EFFDT,
  C.ACCESS_GROUP,
  C.ACCESSIBLE,
  B.TREE_PATH
FROM 
PS_SCRTY_ACC_GRP C ,
  TREE_NODE B ,
  PSRECDEFN RD,
  PSROLECLASS RC ,
   PSROLEUSER RU
WHERE C.TREE_NAME   = B.TREE_NAME
AND C.ACCESS_GROUP  = B.ACCESS_PATH
 AND RD.RECNAME = B.RECNAME
AND RC.CLASSID = C.CLASSID 
AND RU.ROLENAME = RC.ROLENAME;

What Roles can a see a Query Record?

WITH TREE_NODE AS
		  (SELECT CONNECT_BY_ROOT P.TREE_NODE AS RECNAME,
			P.TREE_NAME,
			P.EFFDT,
			P.TREE_NODE_TYPE ,
			P.SETID ,
			REVERSE(LTRIM(SYS_CONNECT_BY_PATH (REVERSE(P.TREE_NODE),' >- '),' >- ')) AS TREE_PATH ,
			P.TREE_NODE    AS ACCESS_PATH
		  FROM      PSTREENODE P,
				PSTREEDEFN A 
	  WHERE P.TREE_NODE_TYPE = 'G' 
				AND P.SETID   = ' '
				AND A.SETID         = P.SETID
				and A.SETCNTRLVALUE = P.SETCNTRLVALUE
				and A.EFFDT         = P.EFFDT
				AND A.TREE_NAME     = P.TREE_NAME
				AND A.TREE_STRCT_ID = 'ACCESS_GROUP'
				AND A.EFF_STATUS    = 'A'
				AND A.EFFDT         =   (SELECT MAX(D.EFFDT)  FROM PSTREEDEFN D
										WHERE D.SETID   = ' '
										AND D.TREE_NAME = A.TREE_NAME
										AND D.EFFDT    <= SYSDATE   )
			START WITH P.TREE_NODE        = 'JOB_MIL'    /* RECNAME */
			CONNECT BY PRIOR P.PARENT_NODE_NUM = P.TREE_NODE_NUM
				  AND PRIOR P.TREE_NAME                = P.TREE_NAME
				  AND PRIOR P.EFFDT                    = P.EFFDT
				  AND PRIOR P.SETID                    = P.SETID
				  AND PRIOR P.SETCNTRLVALUE            = P.SETCNTRLVALUE     )
		  
SELECT DISTINCT 
 -- RU.ROLEUSER,
  RC.ROLENAME,  
  B.RECNAME ,
  RD.RECDESCR,
 -- C.CLASSID,
  B.TREE_NAME,
  B.EFFDT,
  C.ACCESS_GROUP,
  C.ACCESSIBLE,
  B.TREE_PATH
FROM 
PS_SCRTY_ACC_GRP C ,
  TREE_NODE B ,
  PSRECDEFN RD,
  PSROLECLASS RC
WHERE C.TREE_NAME   = B.TREE_NAME
AND C.ACCESS_GROUP  = B.ACCESS_PATH
 AND RD.RECNAME = B.RECNAME
AND RC.CLASSID = C.CLASSID ; 

What Permission Lists can see a Query Record

WITH TREE_NODE AS
		  (SELECT CONNECT_BY_ROOT P.TREE_NODE AS RECNAME,
		    P.TREE_NAME,
		    P.EFFDT,
		    P.TREE_NODE_TYPE ,
		    P.SETID ,
		    REVERSE(LTRIM(SYS_CONNECT_BY_PATH (REVERSE(P.TREE_NODE),' >- '),' >- ')) AS TREE_PATH ,
		    P.TREE_NODE    AS ACCESS_PATH
		  FROM      PSTREENODE P,
                PSTREEDEFN A 
      WHERE P.TREE_NODE_TYPE = 'G' 
                AND P.SETID   = ' '
                AND A.SETID         = P.SETID
                and A.SETCNTRLVALUE = P.SETCNTRLVALUE
                and A.EFFDT         = P.EFFDT
                AND A.TREE_NAME     = P.TREE_NAME
                AND A.TREE_STRCT_ID = 'ACCESS_GROUP'
                AND A.EFF_STATUS    = 'A'
                AND A.EFFDT         =   (SELECT MAX(D.EFFDT)  FROM PSTREEDEFN D
                                        WHERE D.SETID   = ' '
                                        AND D.TREE_NAME = A.TREE_NAME
                                        AND D.EFFDT    <= SYSDATE   )
            START WITH P.TREE_NODE        = 'JOB_MIL'    /* RECNAME */
		    CONNECT BY PRIOR P.PARENT_NODE_NUM = P.TREE_NODE_NUM
                  AND PRIOR P.TREE_NAME                = P.TREE_NAME
                  AND PRIOR P.EFFDT                    = P.EFFDT
                  AND PRIOR P.SETID                    = P.SETID
                  AND PRIOR P.SETCNTRLVALUE            = P.SETCNTRLVALUE     )
		  
SELECT DISTINCT 
  C.CLASSID,
  B.RECNAME ,
  RD.RECDESCR,
  B.TREE_NAME,
  B.EFFDT,
  C.ACCESS_GROUP,
  C.ACCESSIBLE,
  B.TREE_PATH
FROM 
PS_SCRTY_ACC_GRP C ,
  TREE_NODE B ,
  PSRECDEFN RD
WHERE C.TREE_NAME   = B.TREE_NAME
AND C.ACCESS_GROUP  = B.ACCESS_PATH
 AND RD.RECNAME = B.RECNAME;

Randall Groncki

Oracle ACE ♠ PeopleTools Developer since 1996 Lives in Northern Virginia, USA

View all posts by Randall Groncki →