view src/nabble/view/web/template/SubscriptionNamespace.java @ 0:7ecd1a4ef557

add content
author Franklin Schmidt <fschmidt@gmail.com>
date Thu, 21 Mar 2019 19:15:52 -0600
parents
children
line wrap: on
line source

package nabble.view.web.template;

import fschmidt.util.java.Base64;
import fschmidt.util.mail.MailAddress;
import nabble.model.ModelException;
import nabble.model.ModelHome;
import nabble.model.Node;
import nabble.model.Site;
import nabble.model.Subscription;
import nabble.model.User;
import nabble.naml.compiler.Command;
import nabble.naml.compiler.CommandSpec;
import nabble.naml.compiler.IPrintWriter;
import nabble.naml.compiler.Interpreter;
import nabble.naml.compiler.Namespace;
import nabble.naml.compiler.ScopedInterpreter;
import nabble.naml.namespaces.ListSequence;
import nabble.naml.namespaces.TemplateException;
import nabble.view.lib.Jtp;

import java.util.List;
import javax.servlet.http.HttpServletRequest;


@Namespace (
	name = "subscription",
	global = false
)
public final class SubscriptionNamespace {
	private Node node;
	private User user;
	private Subscription subscription;
	private final Site site;

	public SubscriptionNamespace(Node node, User user) {
		this.node = node;
		this.user = user;
		this.subscription = user.getSubscription(node);
		this.site = node.getSite();
	}

	public SubscriptionNamespace(Subscription subscription) {
		this.node = subscription.getNode();
		this.user = subscription.getSubscriber();
		this.subscription = subscription;
		this.site = node.getSite();
	}

	public SubscriptionNamespace(String code, HttpServletRequest request)
		throws TemplateException
	{
		this.site = Jtp.getSite(request);
		Object[] emailAndNode = getValuesFromCode(code, site);
		this.user = site.getUserFromEmail((String) emailAndNode[0]);
		this.node = (Node) emailAndNode[1];
		this.subscription = user.getSubscription(node);
	}

	public static final CommandSpec this_subscription = CommandSpec.DO;

	@Command public void this_subscription(IPrintWriter out, ScopedInterpreter<SubscriptionNamespace> interp) {
		out.print( interp.getArg(this,"do") );
	}

    @Command public void is_subscribed(IPrintWriter out, Interpreter interp) {
		out.print( subscription != null );
	}

	public static final CommandSpec _node = CommandSpec.DO;

	@Command("node") public void _node(IPrintWriter out,ScopedInterpreter<NodeNamespace> interp) {
		NodeNamespace nodeNs = new NodeNamespace(node);
		out.print( interp.getArg(nodeNs,"do") );
	}

	public static final CommandSpec _user = CommandSpec.DO;

	@Command("user") public void _user(IPrintWriter out,ScopedInterpreter<UserNamespace> interp) {
		UserNamespace visitorModel = new UserNamespace(user);
		out.print( interp.getArg(visitorModel,"do") );
	}

	@Command public void to(IPrintWriter out, Interpreter interp) {
		out.print( subscription.getTo() );
	}

    @Command public void type(IPrintWriter out, Interpreter interp) {
		out.print( subscription.getType() );
	}

	public static final CommandSpec save = new CommandSpec.Builder()
		.parameters("to","type")
		.build()
	;

    @Command public void save(IPrintWriter out, Interpreter interp) {
		String toS = interp.getArgString("to");
		Subscription.To to = toS==null ? Subscription.To.DESCENDANTS : Subscription.To.valueOf(toS);
		Subscription.Type type =
			node.getKind() == Node.Kind.APP?
			Subscription.Type.valueOf(interp.getArgString("type")) :
			Subscription.Type.INSTANT;

		if (subscription == null) {
			subscription = user.subscribe(node, to, type);
		} else {
			subscription.setTo(to);
			subscription.setType(type);
		}
	}

    @Command public void remove(IPrintWriter out, Interpreter interp) {
		subscription.delete();
	}

	private static final String SALT = "zDf3s";

	@Command public void subscription_code(IPrintWriter out, Interpreter interp) {
		String email = user.getEmail();	
		out.print( getCode(email, node) );
	}

	public static String getCode(String email, Node node) {
		int key = (email + SALT).hashCode();
		String params = email + '|' + node.getId() + '|' + key;
		return Base64.encode(params.getBytes());
	}

	private static Object[] getValuesFromCode(String code, Site site) throws TemplateException {
		String[] values = decodeParams(code);
		if (values == null)
			values = decodeParams(code+"=="); // try with "==" at the end (most common problem with invalid codes)
		if (values == null)
			throw ModelException.newInstance("invalid_link");

		long nodeId = Long.valueOf(values[1]);
		Node node = site.getNode(nodeId);
		if (node == null || !node.getSite().equals(site))
			throw ModelException.newInstance("invalid_link");
		return new Object[] { values[0], node };
	}

	private static String[] decodeParams(String code) {
		String params;
		try {
			params = new String(Base64.decode(code));
		} catch (Base64.InvalidCharEncodedStringException e) {
			return null;
		}
		if (params.indexOf('|') == -1)
			return null;
		String[] values = params.split("\\|");
		if (!new MailAddress(values[0]).isValid())
			return null;
		try {
			Long.valueOf(values[1]);
		} catch (NumberFormatException e) {
			return null;
		}
		String key = (values[0] + SALT).hashCode() + "";
		if (!key.equals(values[2]))
			return null;

		return values;
	}



	@Namespace (
		name = "subscription_list",
		global = true
	)
	public static final class SubscriptionList extends ListSequence<Subscription> {
		private SubscriptionNamespace ns = null;

		public SubscriptionList(List<Subscription> subscriptions) {
			super(subscriptions);
		}

		public static final CommandSpec current_subscription = CommandSpec.DO;

		@Command public void current_subscription(IPrintWriter out,ScopedInterpreter<SubscriptionNamespace> interp) {
			Subscription subscription = get();
			if( ns==null || ns.subscription != subscription )
				ns = new SubscriptionNamespace(subscription);
			out.print( interp.getArg(ns,"do") );
		}

	}

}