0
|
1 package nabble.view.web.template;
|
|
2
|
|
3 import fschmidt.util.java.Base64;
|
|
4 import fschmidt.util.mail.MailAddress;
|
|
5 import nabble.model.ModelException;
|
|
6 import nabble.model.ModelHome;
|
|
7 import nabble.model.Node;
|
|
8 import nabble.model.Site;
|
|
9 import nabble.model.Subscription;
|
|
10 import nabble.model.User;
|
|
11 import nabble.naml.compiler.Command;
|
|
12 import nabble.naml.compiler.CommandSpec;
|
|
13 import nabble.naml.compiler.IPrintWriter;
|
|
14 import nabble.naml.compiler.Interpreter;
|
|
15 import nabble.naml.compiler.Namespace;
|
|
16 import nabble.naml.compiler.ScopedInterpreter;
|
|
17 import nabble.naml.namespaces.ListSequence;
|
|
18 import nabble.naml.namespaces.TemplateException;
|
|
19 import nabble.view.lib.Jtp;
|
|
20
|
|
21 import java.util.List;
|
|
22 import javax.servlet.http.HttpServletRequest;
|
|
23
|
|
24
|
|
25 @Namespace (
|
|
26 name = "subscription",
|
|
27 global = false
|
|
28 )
|
|
29 public final class SubscriptionNamespace {
|
|
30 private Node node;
|
|
31 private User user;
|
|
32 private Subscription subscription;
|
|
33 private final Site site;
|
|
34
|
|
35 public SubscriptionNamespace(Node node, User user) {
|
|
36 this.node = node;
|
|
37 this.user = user;
|
|
38 this.subscription = user.getSubscription(node);
|
|
39 this.site = node.getSite();
|
|
40 }
|
|
41
|
|
42 public SubscriptionNamespace(Subscription subscription) {
|
|
43 this.node = subscription.getNode();
|
|
44 this.user = subscription.getSubscriber();
|
|
45 this.subscription = subscription;
|
|
46 this.site = node.getSite();
|
|
47 }
|
|
48
|
|
49 public SubscriptionNamespace(String code, HttpServletRequest request)
|
|
50 throws TemplateException
|
|
51 {
|
|
52 this.site = Jtp.getSite(request);
|
|
53 Object[] emailAndNode = getValuesFromCode(code, site);
|
|
54 this.user = site.getUserFromEmail((String) emailAndNode[0]);
|
|
55 this.node = (Node) emailAndNode[1];
|
|
56 this.subscription = user.getSubscription(node);
|
|
57 }
|
|
58
|
|
59 public static final CommandSpec this_subscription = CommandSpec.DO;
|
|
60
|
|
61 @Command public void this_subscription(IPrintWriter out, ScopedInterpreter<SubscriptionNamespace> interp) {
|
|
62 out.print( interp.getArg(this,"do") );
|
|
63 }
|
|
64
|
|
65 @Command public void is_subscribed(IPrintWriter out, Interpreter interp) {
|
|
66 out.print( subscription != null );
|
|
67 }
|
|
68
|
|
69 public static final CommandSpec _node = CommandSpec.DO;
|
|
70
|
|
71 @Command("node") public void _node(IPrintWriter out,ScopedInterpreter<NodeNamespace> interp) {
|
|
72 NodeNamespace nodeNs = new NodeNamespace(node);
|
|
73 out.print( interp.getArg(nodeNs,"do") );
|
|
74 }
|
|
75
|
|
76 public static final CommandSpec _user = CommandSpec.DO;
|
|
77
|
|
78 @Command("user") public void _user(IPrintWriter out,ScopedInterpreter<UserNamespace> interp) {
|
|
79 UserNamespace visitorModel = new UserNamespace(user);
|
|
80 out.print( interp.getArg(visitorModel,"do") );
|
|
81 }
|
|
82
|
|
83 @Command public void to(IPrintWriter out, Interpreter interp) {
|
|
84 out.print( subscription.getTo() );
|
|
85 }
|
|
86
|
|
87 @Command public void type(IPrintWriter out, Interpreter interp) {
|
|
88 out.print( subscription.getType() );
|
|
89 }
|
|
90
|
|
91 public static final CommandSpec save = new CommandSpec.Builder()
|
|
92 .parameters("to","type")
|
|
93 .build()
|
|
94 ;
|
|
95
|
|
96 @Command public void save(IPrintWriter out, Interpreter interp) {
|
|
97 String toS = interp.getArgString("to");
|
|
98 Subscription.To to = toS==null ? Subscription.To.DESCENDANTS : Subscription.To.valueOf(toS);
|
|
99 Subscription.Type type =
|
|
100 node.getKind() == Node.Kind.APP?
|
|
101 Subscription.Type.valueOf(interp.getArgString("type")) :
|
|
102 Subscription.Type.INSTANT;
|
|
103
|
|
104 if (subscription == null) {
|
|
105 subscription = user.subscribe(node, to, type);
|
|
106 } else {
|
|
107 subscription.setTo(to);
|
|
108 subscription.setType(type);
|
|
109 }
|
|
110 }
|
|
111
|
|
112 @Command public void remove(IPrintWriter out, Interpreter interp) {
|
|
113 subscription.delete();
|
|
114 }
|
|
115
|
|
116 private static final String SALT = "zDf3s";
|
|
117
|
|
118 @Command public void subscription_code(IPrintWriter out, Interpreter interp) {
|
|
119 String email = user.getEmail();
|
|
120 out.print( getCode(email, node) );
|
|
121 }
|
|
122
|
|
123 public static String getCode(String email, Node node) {
|
|
124 int key = (email + SALT).hashCode();
|
|
125 String params = email + '|' + node.getId() + '|' + key;
|
|
126 return Base64.encode(params.getBytes());
|
|
127 }
|
|
128
|
|
129 private static Object[] getValuesFromCode(String code, Site site) throws TemplateException {
|
|
130 String[] values = decodeParams(code);
|
|
131 if (values == null)
|
|
132 values = decodeParams(code+"=="); // try with "==" at the end (most common problem with invalid codes)
|
|
133 if (values == null)
|
|
134 throw ModelException.newInstance("invalid_link");
|
|
135
|
|
136 long nodeId = Long.valueOf(values[1]);
|
|
137 Node node = site.getNode(nodeId);
|
|
138 if (node == null || !node.getSite().equals(site))
|
|
139 throw ModelException.newInstance("invalid_link");
|
|
140 return new Object[] { values[0], node };
|
|
141 }
|
|
142
|
|
143 private static String[] decodeParams(String code) {
|
|
144 String params;
|
|
145 try {
|
|
146 params = new String(Base64.decode(code));
|
|
147 } catch (Base64.InvalidCharEncodedStringException e) {
|
|
148 return null;
|
|
149 }
|
|
150 if (params.indexOf('|') == -1)
|
|
151 return null;
|
|
152 String[] values = params.split("\\|");
|
|
153 if (!new MailAddress(values[0]).isValid())
|
|
154 return null;
|
|
155 try {
|
|
156 Long.valueOf(values[1]);
|
|
157 } catch (NumberFormatException e) {
|
|
158 return null;
|
|
159 }
|
|
160 String key = (values[0] + SALT).hashCode() + "";
|
|
161 if (!key.equals(values[2]))
|
|
162 return null;
|
|
163
|
|
164 return values;
|
|
165 }
|
|
166
|
|
167
|
|
168
|
|
169 @Namespace (
|
|
170 name = "subscription_list",
|
|
171 global = true
|
|
172 )
|
|
173 public static final class SubscriptionList extends ListSequence<Subscription> {
|
|
174 private SubscriptionNamespace ns = null;
|
|
175
|
|
176 public SubscriptionList(List<Subscription> subscriptions) {
|
|
177 super(subscriptions);
|
|
178 }
|
|
179
|
|
180 public static final CommandSpec current_subscription = CommandSpec.DO;
|
|
181
|
|
182 @Command public void current_subscription(IPrintWriter out,ScopedInterpreter<SubscriptionNamespace> interp) {
|
|
183 Subscription subscription = get();
|
|
184 if( ns==null || ns.subscription != subscription )
|
|
185 ns = new SubscriptionNamespace(subscription);
|
|
186 out.print( interp.getArg(ns,"do") );
|
|
187 }
|
|
188
|
|
189 }
|
|
190
|
|
191 }
|