package org.neo4j.tutor.security;

import org.neo4j.api.core.Node;
import org.neo4j.api.core.Relationship;
import org.neo4j.api.core.RelationshipType;
import org.neo4j.api.core.ReturnableEvaluator;
import org.neo4j.api.core.TraversalPosition;
import org.neo4j.impl.event.Event;
import org.neo4j.impl.event.EventData;

public class SecurityMgr4 extends AbstractSecurityMgr
{
	private static final RelationshipType ACCESS = MyRelationshipTypes.ACCESS;
	private static final RelationshipType MEMBER_OF = 
		MyRelationshipTypes.MEMBER_OF;
	private static final RelationshipType FILE = MyRelationshipTypes.FILE;
	
	public boolean proActiveEventReceived( Event event, EventData data )
	{
		if ( event == SecurityEvent.ACCESS )
		{
			Node file = (Node) data.getData();
			Node user = AuthorizationService.getCurrentUser();
			// --- TODO
			// --- Make security hierarchical
			// --- Access granted by ACCESS relationship to a user or a group
			// --- that user is member of via the MEMBER_OF relationship
			// --- If no ACCESS relationship exist on the file or any of the 
			// --- files parents (traverse FILE relationship) access is granted
			// --- else If no user registered (null user), access is denied
			// --- else traverser must find ACCESS relationship connected 
			// --- to user or any group the user is member of
			// --- make use of the MyReturnableEvaluator implementation bellow
		}
		// we shouldn't get any other events but returning true by default 
		return true;
	}
	
	private static class MyReturnableEvaluator implements ReturnableEvaluator
	{
		private boolean accessRelFound = false;
		private Node userToFind;
		
		public MyReturnableEvaluator( Node userToFind )
		{
			this.userToFind = userToFind;
		}
		
		public boolean foundAccessRelationship()
		{
			return accessRelFound;
		}
		
		public boolean isReturnableNode( TraversalPosition currentPosition )
		{
			Relationship lastRel = currentPosition.lastRelationshipTraversed();
			if ( lastRel != null && lastRel.getType().equals(  
				MyRelationshipTypes.ACCESS ) )
			{
				accessRelFound = true;
			}
			return currentPosition.currentNode().equals( userToFind );
		}
	}
}
