/*
 * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved.
 *
 * The contents of this file are subject to the CCM Public
 * License (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the
 * License at http://www.redhat.com/licenses/ccmpl.html.
 *
 * Software distributed under the License is distributed on an
 * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
 * or implied. See the License for the specific language
 * governing rights and limitations under the License.
 *
 */
package com.arsdigita.kernel.permissions;

import com.arsdigita.domain.DomainObject;
import com.arsdigita.domain.GlobalObserver;
import com.arsdigita.kernel.ACSObject;
import com.arsdigita.kernel.Kernel;
import com.arsdigita.kernel.KernelHelper;
import com.arsdigita.kernel.Party;
import com.arsdigita.persistence.DataObject;
import com.arsdigita.persistence.metadata.ObjectType;
import org.apache.log4j.Logger;

/**
 * Global observer to enforce permissions on ACS Objects. This
 * observer verifies that the user has write access to the object
 * before the object is saved.
 *
 * @author richardl@redhat.com
 *
 */
public class PermissionsObserver implements GlobalObserver {

    private static final Logger s_log =
        Logger.getLogger(PermissionsObserver.class);

    public void set(DomainObject dobj,
                    String name,
                    Object old_value,
                    Object new_value) { }

    public void add(DomainObject dobj,
                    String name, DataObject dataObject) { }

    public void remove(DomainObject dobj,
                       String name, DataObject dataObject) { }

    public void clear(DomainObject dobj, String name) { }

    public void beforeSave(DomainObject dobj) {
        if (isKernelMode()) { 
            if (s_log.isDebugEnabled()) {
                s_log.debug("In kernel mode so skipping " + 
                            (dobj.isNew() ? "CREATE" : "EDIT") +
                            " privilege check on object " + dobj.getOID());
            }
            return; 
        }

        if ( dobj.isNew() ) {
            ((ACSObject) dobj).doCreateCheck();
        } else {
            ((ACSObject) dobj).doWriteCheck();
        }
    }

    public void afterSave(DomainObject dobj) { }

    public void beforeDelete(DomainObject dobj) {
        if (isKernelMode()) { 
            if (s_log.isDebugEnabled()) {
                s_log.debug("In kernel mode so skipping ADMIN privilege " +
                            "check on object " + dobj.getOID());
            }
            return; 
        }

        ((ACSObject) dobj).assertPrivilege(PrivilegeDescriptor.ADMIN);
    }

    public void afterDelete(DomainObject dobj) { }

    public boolean shouldObserve(DomainObject dobj) {
        ObjectType type = dobj.getObjectType();
        return type.isSubtypeOf(ACSObject.BASE_DATA_OBJECT_TYPE);
    }

    private boolean isKernelMode() {
        Party currentParty = KernelHelper.getCurrentEffectiveParty();

        return (currentParty != null &&
                currentParty.getID().equals(Kernel.getSystemParty().getID()));
    }

}
