The extended security model is used to create a customer rule for limiting the access to records. The different components of the XDS security are :
1. Query: Whenever we are designing a record level security, there is one primary table where the logic to record restriction is built and then this is extended to all the related tables where this table is a foreign key. The query contains the condition to restrict the primary table.
2. Security policy: Once the primary table to be restricted has been identified and the query designed, the next step is to plan when to apply the policy and to which all table. A policy is used to link the condition query (created in step 1) with a list of tables which need to be restricted for security (constraint tables). It also has a policy context which is used to determine when the policy is applied, this is generally set to a security role (i.e. anyone which the configured role would be applied with the record level security).
The security policy also has a primary table mentioned which is the root of the query that is created. The primary table should have an explicit relationship with all the tables where the constraint is being applied.
Every security policy would also have a property called Constrained Table which can be set to Yes or No to decide if the policy would be applied on the primary table itself or not.
When the policy is applied on the primary table it be already applied before the xds method is called in MyTables. If the xds method needs access to the records in the primary table, this might be a concern as the policy would already be applied and not all the rows in the primary table would be available for the xds method. In cases like this a view based on the primary table can be created and that should be used instead of the actual table.
3. MyTables : These are special tables created to be used in the security query, where custom logic can be written to populate data. These table names are prefixed with "My" keyword and the logic is written in xds function.
public RefreshFrequency xds() { MyAFZCategory myCategory; SPYHCMWorker hcmWorker; //view is used as the primary table is contrained DirPersonUser dirPersonUser; AFZEmployeeCategory afzEmployeeCategory; AFZWorkerCategoryUserAccess workerCategoryUserAccess; insert_recordset myCategory(HcmWorkerRecId) select RecID from hcmWorker join afzEmployeeCategory where afzEmployeeCategory.Code == hcmWorker.AFZCategoryCode join workerCategoryUserAccess where workerCategoryUserAccess.UserId == curUserId() && afzEmployeeCategory.CodeGroup == workerCategoryUserAccess.CodeGroup ; /* select generateOnly forceLiterals RecID from hcmWorker join afzEmployeeCategory where afzEmployeeCategory.Code == hcmWorker.AFZCategoryCode join workerCategoryUserAccess where workerCategoryUserAccess.UserId == curUserId() && afzEmployeeCategory.CodeGroup == workerCategoryUserAccess.CodeGroup ; info( hcmWorker.getSQLStatement() ); */ //Calculate current worker value select firstonly PersonParty, ValidFrom, ValidTo from dirPersonUser where dirPersonUser.User == curUserId(); select firstonly RecId from hcmWorker where hcmWorker.Person == dirPersonUser.PersonParty; myCategory.initValue(); myCategory.HcmWorkerRecId = hcmWorker.RecId; myCategory.insert(); // This is static data, so only refresh when session is restarted return RefreshFrequency::PerSession; } }