Thursday, October 01, 2015

XDS MyConstruct

My construct is a pattern used to implement record level security when the business logic to implement the restriction is not straight forward.

Eg. We had a requirement at a customer where the HR wanted the records to be restricted as per the position hierarchy. So if a manager logs in he should be able to see managers reporting to him and any subordinates below these managers.

The answer to the above problem is to implement the My construct pattern for security. My Construct uses temporary tables of type TempDB which are populated using a table method called XDS().  This method is available for developers to write X++ logic to populate the temporary table. After the temporary table is populated, subsequent policy queries can use this temporary table.

In MyConstructs, we have the ability to refresh the data either PerSession or PerInvocation.

Below is the code for an overridden XDS method of a table

public RefreshFrequency xds()
{
    SPYMYSubordinate                mySubordinate;
    List                            workerList = new List(Types::Int64);
    ListEnumerator                  workerListEnumerator;
    HcmEmployment                   hcmEmployment;

    List subordinate(HcmWorkerRecId _worker,List _workerList)
    {
        HcmPositionHierarchy            positionHierarchy;
        HcmPositionWorkerAssignment     positionWorkerAssignment;

        _workerList.addEnd(_worker);
        while select positionWorkerAssignment join positionHierarchy
            where positionWorkerAssignment.Position == positionHierarchy.Position &&
                  positionHierarchy.ParentPosition == HcmWorker::getPrimaryPosition(_worker) &&
                  positionHierarchy.PositionHierarchyType == HcmPositionHierarchyType::lineHierarchyType()
            join hcmEmployment
            where hcmEmployment.Worker == positionWorkerAssignment.Worker
        {
            _workerlist = subordinate(positionWorkerAssignment.Worker,_workerlist);
        }
        return _workerlist;
    }

    workerList = subordinate(currentWorker(),workerList);
    workerListEnumerator = workerList.getEnumerator();
    while(workerListEnumerator.moveNext())
    {
        mySubordinate.Worker = workerListEnumerator.current();
        mySubordinate.insert();
    }

    return RefreshFrequency::PerSession;
}

No comments: