/*
 * Copyright (C) 2010-2011 The University of Manchester
 * 
 * See the file "LICENSE" for license terms.
 */
package org.taverna.server.master.worker;

import static org.taverna.server.master.identity.WorkflowInternalAuthProvider.PREFIX;

import java.net.URI;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.taverna.server.master.common.Roles;
import org.taverna.server.master.common.Workflow;
import org.taverna.server.master.exceptions.NoCreateException;
import org.taverna.server.master.exceptions.NoDestroyException;
import org.taverna.server.master.exceptions.NoUpdateException;
import org.taverna.server.master.interfaces.Policy;
import org.taverna.server.master.interfaces.TavernaRun;
import org.taverna.server.master.interfaces.TavernaSecurityContext;
import org.taverna.server.master.utils.UsernamePrincipal;

/**
 * Basic policy implementation that allows any workflow to be instantiated by
 * any user, but which does not permit users to access each others workflow
 * runs. It also imposes a global limit on the number of workflow runs at once.
 * 
 * @author Donal Fellows
 */
class PolicyImpl implements Policy {
	Log log = LogFactory.getLog("Taverna.Server.Worker.Policy");
	private PolicyLimits limits;
	private RunDBSupport runDB;

	@Required
	public void setLimits(PolicyLimits limits) {
		this.limits = limits;
	}

	@Required
	public void setRunDB(RunDBSupport runDB) {
		this.runDB = runDB;
	}

	@Override
	public int getMaxRuns() {
		return limits.getMaxRuns();
	}

	@Override
	public Integer getMaxRuns(UsernamePrincipal user) {
		return null;
	}

	@Override
	public int getOperatingLimit() {
		return limits.getOperatingLimit();
	}

	@Override
	public List<URI> listPermittedWorkflowURIs(UsernamePrincipal user) {
		return limits.getPermittedWorkflowURIs();
	}

	private boolean isSelfAccess(String runId) {
		Authentication auth = SecurityContextHolder.getContext()
				.getAuthentication();
		boolean self = false;
		String id = null;
		for (GrantedAuthority a : auth.getAuthorities()) {
			String aa = a.getAuthority();
			if (aa.equals(Roles.SELF)) {
				self = true;
				continue;
			}
			if (!aa.startsWith(PREFIX))
				continue;
			id = aa.substring(PREFIX.length());
		}
		return self && runId.equals(id);
	}

	@Override
	public boolean permitAccess(UsernamePrincipal user, TavernaRun run) {
		String username = user.getName();
		TavernaSecurityContext context = run.getSecurityContext();
		if (context.getOwner().getName().equals(username)) {
			if (log.isDebugEnabled())
				log.debug("granted access by " + user.getName() + " to "
						+ run.getId());
			return true;
		}
		if (isSelfAccess(run.getId())) {
			if (log.isDebugEnabled())
				log.debug("access by workflow to itself: " + run.getId());
			return true;
		}
		if (log.isDebugEnabled())
			log.debug("considering access by " + user.getName() + " to "
					+ run.getId());
		return context.getPermittedReaders().contains(username);
	}

	@Override
	public void permitCreate(UsernamePrincipal user, Workflow workflow)
			throws NoCreateException {
		if (user == null)
			throw new NoCreateException(
					"anonymous workflow creation not allowed");
		if (runDB.countRuns() >= getMaxRuns())
			throw new NoCreateException("server load exceeded; please wait");
	}

	@Override
	public synchronized void permitDestroy(UsernamePrincipal user, TavernaRun run)
			throws NoDestroyException {
		if (user == null)
			throw new NoDestroyException();
		String username = user.getName();
		TavernaSecurityContext context = run.getSecurityContext();
		if (context.getOwner() == null
				|| context.getOwner().getName().equals(username))
			return;
		if (!context.getPermittedDestroyers().contains(username))
			throw new NoDestroyException();
	}

	@Override
	public void permitUpdate(UsernamePrincipal user, TavernaRun run)
			throws NoUpdateException {
		if (user == null)
			throw new NoUpdateException(
					"workflow run not owned by you and you're not granted access");
		TavernaSecurityContext context = run.getSecurityContext();
		if (context.getOwner().getName().equals(user.getName()))
			return;
		if (isSelfAccess(run.getId())) {
			if (log.isDebugEnabled())
				log.debug("update access by workflow to itself: " + run.getId());
			return;
		}
		if (!context.getPermittedUpdaters().contains(user.getName()))
			throw new NoUpdateException(
					"workflow run not owned by you and you're not granted access");
	}

	@Override
	public void setPermittedWorkflowURIs(UsernamePrincipal user,
			List<URI> permitted) {
		limits.setPermittedWorkflowURIs(permitted);
	}
}
