/*
 * Copyright (C) 2013 The University of Manchester
 * 
 * See the file "LICENSE.txt" for license terms.
 */
package org.taverna.server.master.identity;

import static org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes;
import static org.taverna.server.master.common.Roles.SELF;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.taverna.server.master.exceptions.UnknownRunException;
import org.taverna.server.master.interfaces.LocalIdentityMapper;
import org.taverna.server.master.interfaces.RunStore;
import org.taverna.server.master.utils.UsernamePrincipal;
import org.taverna.server.master.worker.RunDatabaseDAO;

import edu.umd.cs.findbugs.annotations.NonNull;

/**
 * A special authentication provider that allows a workflow to authenticate to
 * itself. This is used to allow the workflow to publish to its own interaction
 * feed.
 * 
 * @author Donal Fellows
 */
public class WorkflowInternalAuthProvider extends
		AbstractUserDetailsAuthenticationProvider {
	private static Log log = LogFactory.getLog("Taverna.Server.UserDB");
	private static final boolean logDecisions = true;
	public static final String PREFIX = "wfrun_";
	private RunDatabaseDAO dao;

	@Required
	public void setDao(RunDatabaseDAO dao) {
		this.dao = dao;
	}

	public void setAuthorizedAddresses(String[] addresses) {
		authorizedAddresses = new HashSet<String>(localAddresses);
		for (String s : addresses)
			authorizedAddresses.add(s);
	}

	@PostConstruct
	public void logConfig() {
		log.info("authorized addresses for automatic access: "
				+ authorizedAddresses);
	}

	@PreDestroy
	void closeLog() {
		log = null;
	}

	private final Set<String> localAddresses = new HashSet<String>();
	private Set<String> authorizedAddresses;
	{
		localAddresses.add("127.0.0.1"); // IPv4
		localAddresses.add("::1"); // IPv6
		try {
			InetAddress addr = InetAddress.getLocalHost();
			if (!addr.isLoopbackAddress())
				localAddresses.add(addr.getHostAddress());
		} catch (UnknownHostException e) {
			// Ignore the exception
		}
		authorizedAddresses = new HashSet<String>(localAddresses);
	}

    /**
	 * Check that the authentication request is actually valid for the given
	 * user record.
	 * 
	 * @param userRecord
	 *            as retrieved from the
	 *            {@link #retrieveUser(String, UsernamePasswordAuthenticationToken)}
	 *            or <code>UserCache</code>
	 * @param principal
	 *            the principal that is trying to authenticate (and that we're
	 *            trying to bind)
	 * @param credentials
	 *            the credentials (e.g., password) presented by the principal
	 * 
	 * @throws AuthenticationException
	 *             AuthenticationException if the credentials could not be
	 *             validated (generally a <code>BadCredentialsException</code>,
	 *             an <code>AuthenticationServiceException</code>)
	 * @throws Exception
	 *             If something goes wrong. Will be logged and converted to a
	 *             generic AuthenticationException.
	 */
	protected void additionalAuthenticationChecks(UserDetails userRecord,
			@NonNull Object principal, @NonNull Object credentials)
			throws Exception {
		@NonNull
		HttpServletRequest req = ((ServletRequestAttributes) currentRequestAttributes())
				.getRequest();

		// Are we coming from a "local" address?
		if (!req.getLocalAddr().equals(req.getRemoteAddr())
				&& !authorizedAddresses.contains(req.getRemoteAddr())) {
			if (logDecisions)
				log.info("attempt to use workflow magic token from untrusted address:"
						+ " token=" + userRecord.getUsername()
						+ ", address=" + req.getRemoteAddr());
			throw new BadCredentialsException("bad login token");
		}

		// Does the password match?
		if (!credentials.equals(userRecord.getPassword())) {
			if (logDecisions)
				log.info("workflow magic token is untrusted due to password mismatch:"
						+ " wanted=" + userRecord.getPassword()
						+ ", got=" + credentials);
			throw new BadCredentialsException("bad login token");
		}

		if (logDecisions)
			log.info("granted role " + SELF + " to user "
					+ userRecord.getUsername());
	}

    /**
	 * Retrieve the <code>UserDetails</code> from the relevant store, with the
	 * option of throwing an <code>AuthenticationException</code> immediately if
	 * the presented credentials are incorrect (this is especially useful if it
	 * is necessary to bind to a resource as the user in order to obtain or
	 * generate a <code>UserDetails</code>).
	 * 
	 * @param username
	 *            The username to retrieve
	 * @param details
	 *            The details from the authentication request.
	 * @see #retrieveUser(String,UsernamePasswordAuthenticationToken)
	 * @return the user information (never <code>null</code> - instead an
	 *         exception should the thrown)
	 * @throws AuthenticationException
	 *             if the credentials could not be validated (generally a
	 *             <code>BadCredentialsException</code>, an
	 *             <code>AuthenticationServiceException</code> or
	 *             <code>UsernameNotFoundException</code>)
	 * @throws Exception
	 *             If something goes wrong. It will be logged and converted into
	 *             a general AuthenticationException.
	 */
	@NonNull
	protected UserDetails retrieveUser(String username, Object details) throws Exception {
		if (details == null || !(details instanceof WebAuthenticationDetails))
			throw new UsernameNotFoundException("context unsupported");
		if (!username.startsWith(PREFIX))
			throw new UsernameNotFoundException(
					"unsupported username for this provider");
		if (logDecisions)
			log.info("request for auth for user " + username);
		String wfid = username.substring(PREFIX.length());
		final String securityToken;
		try {
			securityToken = dao.getSecurityToken(wfid);
			if (securityToken == null)
				throw new UsernameNotFoundException("no such user");
		} catch (NullPointerException npe) {
			throw new UsernameNotFoundException("no such user");
		}
		return new User(username, securityToken, true, true, true, true,
				Arrays.asList(new LiteralGrantedAuthority(SELF),
						new WorkflowSelfAuthority(wfid)));
	}

	@Override
	protected final void additionalAuthenticationChecks(UserDetails userRecord,
			UsernamePasswordAuthenticationToken token) {
		try {
			additionalAuthenticationChecks(userRecord, token.getPrincipal(),
					token.getCredentials());
		} catch (AuthenticationException e) {
			throw e;
		} catch (Exception e) {
			log.warn("unexpected failure in authentication", e);
			throw new AuthenticationServiceException(
					"unexpected failure in authentication", e);
		}
	}

	@Override
	@NonNull
	protected final UserDetails retrieveUser(String username,
			UsernamePasswordAuthenticationToken token) {
		try {
			return retrieveUser(username, token.getDetails());
		} catch (AuthenticationException e) {
			throw e;
		} catch (Exception e) {
			log.warn("unexpected failure in authentication", e);
			throw new AuthenticationServiceException("unexpected failure in authentication", e);
		}
	}

	@SuppressWarnings("serial")
	public static class WorkflowSelfAuthority extends LiteralGrantedAuthority {
		public WorkflowSelfAuthority(String wfid) {
			super(wfid);
		}

		public String getWorkflowID() {
			return getAuthority();
		}

		@Override
		public String toString() {
			return "WORKFLOW(" + getAuthority() + ")";
		}
	}

	public static class WorkflowSelfIDMapper implements LocalIdentityMapper {
		private static Log log = LogFactory.getLog("Taverna.Server.UserDB");
		private RunStore runStore;

		@PreDestroy
		void closeLog() {
			log = null;
		}

		@Required
		public void setRunStore(RunStore runStore) {
			this.runStore = runStore;
		}

		private String getUsernameForSelfAccess(WorkflowSelfAuthority authority)
				throws UnknownRunException {
			return runStore.getRun(authority.getWorkflowID()).getSecurityContext()
					.getOwner().getName();
		}

		@Override
		public String getUsernameForPrincipal(UsernamePrincipal user) {
			Authentication auth = SecurityContextHolder.getContext()
					.getAuthentication();
			if (auth == null || !auth.isAuthenticated())
				return null;
			try {
				for (GrantedAuthority authority : auth.getAuthorities())
					if (authority instanceof WorkflowSelfAuthority)
						return getUsernameForSelfAccess((WorkflowSelfAuthority) authority);
			} catch (UnknownRunException e) {
				log.warn("workflow run disappeared during computation of workflow map identity");
			}
			return null;
		}
	}
}
