001package com.identityworksllc.iiq.common.access;
002
003import com.identityworksllc.iiq.common.ThingAccessUtils;
004import org.apache.commons.logging.Log;
005import org.apache.commons.logging.LogFactory;
006import sailpoint.api.SailPointContext;
007import sailpoint.object.Identity;
008import sailpoint.rest.plugin.BasePluginResource;
009import sailpoint.tools.GeneralException;
010
011/**
012 * Implements some common access checks that are more complex than a straightforward
013 * implementation.
014 */
015public class CommonAccessChecks {
016    private static final Log log = LogFactory.getLog(CommonAccessChecks.class);
017
018    /**
019     * Plugin resource, containing IIQ context and user context
020     */
021    private final BasePluginResource pluginResource;
022
023    /**
024     * Constructs a new CommonAccessChecks utility with the given context and identity
025     * @param context The IIQ context
026     * @param source The requesting / subject Identity
027     */
028    public CommonAccessChecks(SailPointContext context, Identity source) {
029        this.pluginResource = ThingAccessUtils.createFakePluginContext(context, source, null);
030    }
031
032    /**
033     * Constructs a new CommonAccessChecks utility with the given existing {@link BasePluginResource}.
034     * @param pluginResource The plugin resource
035     */
036    public CommonAccessChecks(BasePluginResource pluginResource) {
037        this.pluginResource = pluginResource;
038    }
039
040    /**
041     * Returns true if the logged in user is allowed to view the specific field on the
042     * specified account, owned by the specified person.
043     *
044     * This will check three different criteria:
045     *
046     * - view:account:(application):field:(field)
047     * - view:account:field:(field)
048     * - view:account:(application)
049     *
050     * If the first criteria exists explicitly (i.e., not via a substring), it is
051     * authoritative and the other two are skipped.
052     *
053     * Otherwise, both the second and third criteria must allow access.
054     *
055     * @param target The owner of the account
056     * @param applicationName The name of the application
057     * @param fieldName The field name on the application
058     * @return True if the subject Identity can see the given field on the given account type
059     * @throws GeneralException if anything fails during the check
060     */
061    public boolean canSeeLinkField(Identity target, String applicationName, String fieldName) throws GeneralException {
062        SailPointContext context = pluginResource.getContext();
063
064        DelegatedAccessController da = new DelegatedAccessController(pluginResource);
065
066        String daTokenField = "view:account:field:" + fieldName;
067        String daTokenAppField = "view:account:" + applicationName + ":field:" + fieldName;
068        String daTokenApp = "view:account:" + applicationName;
069
070        // Is the field visible on THIS account?
071        if (DelegatedAccessController.explicitControlExists(context, daTokenAppField)) {
072            boolean explicitCheck = da.canSeeIdentity(target, daTokenAppField);
073            if (log.isDebugEnabled()) {
074                log.debug("For token " + daTokenAppField + " the answer is " + explicitCheck);
075            }
076            return explicitCheck;
077        }
078
079        // Is the field visible on any account?
080        boolean fieldVisible = da.canSeeIdentity(target, daTokenField);
081
082        // Is an account of this type visible? (skip if field is not visible)
083        boolean accountVisible = da.canSeeIdentity(target, daTokenApp);
084
085        boolean visible = fieldVisible && accountVisible;
086
087        if (log.isDebugEnabled()) {
088            log.debug("For token " + daTokenField + " the answer is " + fieldVisible);
089            log.debug("For token " + daTokenApp + " the answer is " + accountVisible);
090        }
091
092        return visible;
093    }
094}