/*  Copyright (c) 2000 by Oracle Corporation. All Rights Reserved. */

package oracle.portal.provider.v2.security;

import oracle.portal.provider.v2.PortletDefinition;
import oracle.portal.provider.v2.ProviderUser;
import oracle.portal.provider.v2.ProviderInstance;
import oracle.portal.provider.v2.PortletNotFoundException;
import oracle.portal.provider.v2.Validateable;
import oracle.portal.provider.v2.personalize.PortletReference;
import oracle.portal.provider.v2.utils.ValidationError;

/**
 * DefaultSecurityManager is a simple access controller for a portlet that uses
 * a user's authentication level to control access. A user will be granted
 * access to a portlet if his/her authentication level is greater than or
 * equal to the security level that has been specified for the security manager.
 * <p>If you do not specify a security level for the security manager, it will
 * default to the most secure level of operation
 */
public class AuthLevelSecurityManager extends PortletSecurityManager
    implements Validateable
{
    public static final String STRONG = "strong";
    public static final String WEAK = "weak";
    public static final String PUBLIC = "public";

    private int mSecurityLevel = ProviderUser.USER_STRONG_AUTH;

    /**
     *  Verifies that the specified user's authentication level is greater
     *  than or equal to the specified security threshhold.
     *
     *  @param pi the provider instance from which the portlet is being
     *  accessed.
     *  @param pd the definition of the portlet which we want to authorize
     *  access to.
     *  @param user the current user we are being asked to authorize.
     *  @return true is this user is authorized to access this portlet.
     */
    public boolean hasAccess(ProviderInstance pi, PortletDefinition pd, ProviderUser user)
    {
        if (user.getAuthenticationLevel() >= mSecurityLevel)
            return true;
        return false;
    }

    /**
     *  Verifies that the specified user's authentication level is greater
     *  than or equal to the specified security threshhold.
     *
     *  @param  inst the portlet instance
     *  @param  user the current user we are being asked to authorize.
     *  @return true is this user is authorized to access this portlet instance.
     */
    public boolean hasAccess(PortletReference ref, ProviderUser user)
        throws PortletNotFoundException
    {
        if (user.getAuthenticationLevel() >= mSecurityLevel)
            return true;
        return false;
    }

    /**
    * Sets the security threshhold for this security manager.
    * This version of the method is intended for use by Providers that
    * are initialized via the provider.xml file & it supports a reduced
    * subset of the authentication levels for simplicity
    *
    * @param level String representation of the security level
    */
    public void setSecurityLevel(String level) throws IllegalStateException
    {
        if (level == null)
            throw new IllegalStateException("Security level cannot be NULL");

        if (level.equalsIgnoreCase(STRONG))
            mSecurityLevel = ProviderUser.PUBLIC_STRONG_AUTH;
        else if (level.equalsIgnoreCase(WEAK))
            mSecurityLevel = ProviderUser.PUBLIC_WEAK_AUTH;
        else if (level.equalsIgnoreCase(PUBLIC))
            mSecurityLevel = ProviderUser.NOT_AUTHENTICATED;
        else
        {
            throw new IllegalStateException("Invalid security level: " + level);
        }
    }

    /**
    * Sets the security threshhold for this security manager.
    * This version of the setSecurityLevel method supports the full range
    * of security levels supported by the Portal.
    *
    * @param level integer representation of the security level
    */
    public void setSecurityLevel(int level) throws IllegalStateException
    {
        if (level == ProviderUser.USER_STRONG_AUTH ||
            level == ProviderUser.PUBLIC_STRONG_AUTH ||
            level == ProviderUser.USER_WEAK_AUTH ||
            level == ProviderUser.PUBLIC_WEAK_AUTH ||
            level == ProviderUser.NOT_AUTHENTICATED)
        {
            mSecurityLevel = level;
        }
        else
        {
            throw new IllegalStateException("Invalid security level: " + level);
        }
    }

    /**
     * Validates the internal state of this
     * <code>AuthLevelSecurityManager</code> instance. Errors found are
     * reported using the supplied {@link
     * oracle.portal.provider.v2.utils.ValidationError} instance.
     *
     * @param context The context of the calling instance.
     * @param errors The current list of errors.
     */
    public void validate(String context, ValidationError errors)
    {
        String ctx =
            ValidationError.newContext(context, "AuthLevelSecurityManager",
                                       null);

        // Check that the security level is a recognised one.
        if (mSecurityLevel != ProviderUser.USER_STRONG_AUTH &&
            mSecurityLevel != ProviderUser.PUBLIC_STRONG_AUTH &&
            mSecurityLevel != ProviderUser.USER_WEAK_AUTH &&
            mSecurityLevel != ProviderUser.PUBLIC_WEAK_AUTH &&
            mSecurityLevel != ProviderUser.NOT_AUTHENTICATED)
        {
            errors.addError(ctx, "Invalid security level",
                            String.valueOf(mSecurityLevel));
        }
    }

}
