/*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE file.
 */
package org.apache.james.nntpserver;

import org.apache.avalon.framework.component.ComponentException;
import org.apache.avalon.framework.component.ComponentManager;
import org.apache.avalon.framework.component.Composable;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.james.services.UsersRepository;
import org.apache.james.services.UsersStore;

import java.util.Locale;

/**
 * Provides Authentication State. 
 * Authenticates users.
 * Access Control for User Commands.
 *
 * Implementation is NNTP Specific. 
 * Would it be better to have a James Authentication Service ?
 *
 * Application could define and plugin their own authentication service.
 *
 * @author  Harmeet <harmeet@kodemuse.com> 
 */
public class AuthServiceImpl extends AbstractLogEnabled
    implements AuthService, Composable, Configurable
{
    protected boolean authRequired;
    protected UsersRepository repo;

    /**
     * @see org.apache.avalon.framework.component.Composable#compose(ComponentManager)
     */
    public void compose( final ComponentManager componentManager )
        throws ComponentException
    {
        UsersStore usersStore = (UsersStore)componentManager.lookup(UsersStore.ROLE);
        repo = usersStore.getRepository("LocalUsers");
    }

    /**
     * @see org.apache.avalon.framework.configuration.Configurable#configure(Configuration)
     */
    public void configure( Configuration configuration ) throws ConfigurationException {
        authRequired =
            configuration.getChild("authRequired").getValueAsBoolean(false);
        if (getLogger().isDebugEnabled()) {
            getLogger().debug("Auth required state is :" + authRequired);
        }
    }

    public boolean isAuthenticated(AuthState authState) {
        // no authentication required.
        if ( !authRequired )
            return true;

        // already authenticated, no need to repeat.
        if ( authState.isAuthenticated() )
            return true;

        String userid = authState.getUserID();
        String password = authState.getPassword();
        if ( userid == null || password == null )
            return false;
        
        return repo.test(userid,password);
    }

    public boolean isAuthorized(AuthState authState,String command) {
        command = command.toUpperCase(Locale.US);

        boolean allowed = isAuthenticated(authState);
        // some commands are authorized, even if the user is not authenticated
        allowed = allowed || command.equals("AUTHINFO");
        allowed = allowed || command.equals("MODE");
        allowed = allowed || command.equals("QUIT");
        return allowed;
    }
}
