723a1663991204062f470b03b3fb2edcddfc46fa
[Sone.git] / src / main / java / net / pterodactylus / sone / web / WebInterface.java
1 /*
2  * Sone - WebInterface.java - Copyright © 2010–2020 David Roden
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 package net.pterodactylus.sone.web;
19
20 import static java.util.logging.Logger.getLogger;
21
22 import java.util.Collection;
23 import java.util.TimeZone;
24 import java.util.logging.Logger;
25 import javax.annotation.Nonnull;
26 import javax.annotation.Nullable;
27
28 import net.pterodactylus.sone.core.Core;
29 import net.pterodactylus.sone.core.ElementLoader;
30 import net.pterodactylus.sone.core.event.*;
31 import net.pterodactylus.sone.data.Post;
32 import net.pterodactylus.sone.data.PostReply;
33 import net.pterodactylus.sone.data.Sone;
34 import net.pterodactylus.sone.freenet.L10nFilter;
35 import net.pterodactylus.sone.freenet.Translation;
36 import net.pterodactylus.sone.main.Loaders;
37 import net.pterodactylus.sone.main.PluginHomepage;
38 import net.pterodactylus.sone.main.PluginVersion;
39 import net.pterodactylus.sone.main.PluginYear;
40 import net.pterodactylus.sone.main.SonePlugin;
41 import net.pterodactylus.sone.notify.ListNotificationFilter;
42 import net.pterodactylus.sone.notify.PostVisibilityFilter;
43 import net.pterodactylus.sone.template.LinkedElementRenderFilter;
44 import net.pterodactylus.sone.template.ParserFilter;
45 import net.pterodactylus.sone.template.RenderFilter;
46 import net.pterodactylus.sone.template.ShortenFilter;
47 import net.pterodactylus.sone.text.TimeTextConverter;
48 import net.pterodactylus.sone.web.ajax.BookmarkAjaxPage;
49 import net.pterodactylus.sone.web.ajax.CreatePostAjaxPage;
50 import net.pterodactylus.sone.web.ajax.CreateReplyAjaxPage;
51 import net.pterodactylus.sone.web.ajax.DeletePostAjaxPage;
52 import net.pterodactylus.sone.web.ajax.DeleteProfileFieldAjaxPage;
53 import net.pterodactylus.sone.web.ajax.DeleteReplyAjaxPage;
54 import net.pterodactylus.sone.web.ajax.DismissNotificationAjaxPage;
55 import net.pterodactylus.sone.web.ajax.EditAlbumAjaxPage;
56 import net.pterodactylus.sone.web.ajax.EditImageAjaxPage;
57 import net.pterodactylus.sone.web.ajax.EditProfileFieldAjaxPage;
58 import net.pterodactylus.sone.web.ajax.FollowSoneAjaxPage;
59 import net.pterodactylus.sone.web.ajax.GetLikesAjaxPage;
60 import net.pterodactylus.sone.web.ajax.GetLinkedElementAjaxPage;
61 import net.pterodactylus.sone.web.ajax.GetNotificationsAjaxPage;
62 import net.pterodactylus.sone.web.ajax.GetPostAjaxPage;
63 import net.pterodactylus.sone.web.ajax.GetReplyAjaxPage;
64 import net.pterodactylus.sone.web.ajax.GetStatusAjaxPage;
65 import net.pterodactylus.sone.web.ajax.GetTimesAjaxPage;
66 import net.pterodactylus.sone.web.ajax.GetTranslationAjaxPage;
67 import net.pterodactylus.sone.web.ajax.LikeAjaxPage;
68 import net.pterodactylus.sone.web.ajax.LockSoneAjaxPage;
69 import net.pterodactylus.sone.web.ajax.MarkAsKnownAjaxPage;
70 import net.pterodactylus.sone.web.ajax.MoveProfileFieldAjaxPage;
71 import net.pterodactylus.sone.web.ajax.UnbookmarkAjaxPage;
72 import net.pterodactylus.sone.web.ajax.UnfollowSoneAjaxPage;
73 import net.pterodactylus.sone.web.ajax.UnlikeAjaxPage;
74 import net.pterodactylus.sone.web.ajax.UnlockSoneAjaxPage;
75 import net.pterodactylus.sone.web.page.FreenetRequest;
76 import net.pterodactylus.sone.web.page.TemplateRenderer;
77 import net.pterodactylus.sone.web.pages.*;
78 import net.pterodactylus.util.notify.Notification;
79 import net.pterodactylus.util.notify.NotificationManager;
80 import net.pterodactylus.util.template.Template;
81 import net.pterodactylus.util.template.TemplateContextFactory;
82 import net.pterodactylus.util.web.RedirectPage;
83 import net.pterodactylus.util.web.TemplatePage;
84
85 import com.codahale.metrics.*;
86 import com.google.common.base.Optional;
87 import com.google.common.eventbus.Subscribe;
88 import com.google.inject.Inject;
89 import freenet.clients.http.ToadletContext;
90
91 /**
92  * Bundles functionality that a web interface of a Freenet plugin needs, e.g.
93  * references to l10n helpers.
94  */
95 public class WebInterface implements SessionProvider {
96
97         /** The loaders for templates, pages, and classpath providers. */
98         private final Loaders loaders;
99
100         /** The notification manager. */
101         private final NotificationManager notificationManager;
102
103         /** The Sone plugin. */
104         private final SonePlugin sonePlugin;
105
106         /** The form password. */
107         private final String formPassword;
108
109         /** The template context factory. */
110         private final TemplateContextFactory templateContextFactory;
111         private final TemplateRenderer templateRenderer;
112
113         /** The parser filter. */
114         private final ParserFilter parserFilter;
115         private final ShortenFilter shortenFilter;
116         private final RenderFilter renderFilter;
117
118         private final ListNotificationFilter listNotificationFilter;
119         private final PostVisibilityFilter postVisibilityFilter;
120
121         private final ElementLoader elementLoader;
122         private final LinkedElementRenderFilter linkedElementRenderFilter;
123         private final TimeTextConverter timeTextConverter = new TimeTextConverter();
124         private final L10nFilter l10nFilter;
125
126         private final PageToadletRegistry pageToadletRegistry;
127         private final MetricRegistry metricRegistry;
128         private final Translation translation;
129         private final SessionProvider sessionProvider;
130
131         private final NewElements newElements;
132
133         @Inject
134         public WebInterface(SonePlugin sonePlugin, Loaders loaders, ListNotificationFilter listNotificationFilter,
135                                                 PostVisibilityFilter postVisibilityFilter,
136                                                 ElementLoader elementLoader, TemplateContextFactory templateContextFactory,
137                                                 TemplateRenderer templateRenderer,
138                                                 ParserFilter parserFilter, ShortenFilter shortenFilter,
139                                                 RenderFilter renderFilter,
140                                                 LinkedElementRenderFilter linkedElementRenderFilter,
141                                                 PageToadletRegistry pageToadletRegistry, MetricRegistry metricRegistry, Translation translation, L10nFilter l10nFilter,
142                                                 NotificationManager notificationManager, SessionProvider sessionProvider,
143                                                 NewElements newElements) {
144                 this.sonePlugin = sonePlugin;
145                 this.loaders = loaders;
146                 this.listNotificationFilter = listNotificationFilter;
147                 this.postVisibilityFilter = postVisibilityFilter;
148                 this.elementLoader = elementLoader;
149                 this.templateRenderer = templateRenderer;
150                 this.parserFilter = parserFilter;
151                 this.shortenFilter = shortenFilter;
152                 this.renderFilter = renderFilter;
153                 this.linkedElementRenderFilter = linkedElementRenderFilter;
154                 this.pageToadletRegistry = pageToadletRegistry;
155                 this.metricRegistry = metricRegistry;
156                 this.l10nFilter = l10nFilter;
157                 this.translation = translation;
158                 this.notificationManager = notificationManager;
159                 this.sessionProvider = sessionProvider;
160                 this.newElements = newElements;
161                 formPassword = sonePlugin.pluginRespirator().getToadletContainer().getFormPassword();
162
163                 this.templateContextFactory = templateContextFactory;
164                 templateContextFactory.addTemplateObject("webInterface", this);
165                 templateContextFactory.addTemplateObject("formPassword", formPassword);
166         }
167
168         //
169         // ACCESSORS
170         //
171
172         /**
173          * Returns the Sone core used by the Sone plugin.
174          *
175          * @return The Sone core
176          */
177         @Nonnull
178         public Core getCore() {
179                 return sonePlugin.core();
180         }
181
182         /**
183          * Returns the template context factory of the web interface.
184          *
185          * @return The template context factory
186          */
187         public TemplateContextFactory getTemplateContextFactory() {
188                 return templateContextFactory;
189         }
190
191         @Nullable
192         @Override
193         public Sone getCurrentSone(@Nonnull ToadletContext toadletContext) {
194                 return sessionProvider.getCurrentSone(toadletContext);
195         }
196
197         @Override
198         public void setCurrentSone(@Nonnull ToadletContext toadletContext, @Nullable Sone sone) {
199                 sessionProvider.setCurrentSone(toadletContext, sone);
200         }
201
202         /**
203          * Returns the notification manager.
204          *
205          * @return The notification manager
206          */
207         public NotificationManager getNotifications() {
208                 return notificationManager;
209         }
210
211         @Nonnull
212         public Optional<Notification> getNotification(@Nonnull String notificationId) {
213                 return Optional.fromNullable(notificationManager.getNotification(notificationId));
214         }
215
216         @Nonnull
217         public Collection<Notification> getNotifications(@Nullable Sone currentSone) {
218                 return listNotificationFilter.filterNotifications(notificationManager.getNotifications(), currentSone);
219         }
220
221         public Translation getTranslation() {
222                 return translation;
223         }
224
225         /**
226          * Returns the node’s form password.
227          *
228          * @return The form password
229          */
230         public String getFormPassword() {
231                 return formPassword;
232         }
233
234         @Nonnull
235         public Collection<Post> getNewPosts(@Nullable Sone currentSone) {
236                 return newElements.getNewPosts();
237         }
238
239         @Nonnull
240         public Collection<PostReply> getNewReplies(@Nullable Sone currentSone) {
241                 return newElements.getNewReplies();
242         }
243
244         //
245         // ACTIONS
246         //
247
248         /**
249          * Starts the web interface and registers all toadlets.
250          */
251         public void start() {
252                 registerToadlets();
253         }
254
255         /**
256          * Stops the web interface and unregisters all toadlets.
257          */
258         public void stop() {
259                 pageToadletRegistry.unregisterToadlets();
260         }
261
262         //
263         // PRIVATE METHODS
264         //
265
266         /**
267          * Register all toadlets.
268          */
269         private void registerToadlets() {
270                 Template postTemplate = loaders.loadTemplate("/templates/include/viewPost.html");
271                 Template replyTemplate = loaders.loadTemplate("/templates/include/viewReply.html");
272                 Template openSearchTemplate = loaders.loadTemplate("/templates/xml/OpenSearch.xml");
273
274                 pageToadletRegistry.addPage(new RedirectPage<FreenetRequest>("", "index.html"));
275                 pageToadletRegistry.addPage(new IndexPage(this, loaders, templateRenderer, postVisibilityFilter));
276                 pageToadletRegistry.addPage(new NewPage(this, loaders, templateRenderer, newElements));
277                 pageToadletRegistry.addPage(new CreateSonePage(this, loaders, templateRenderer));
278                 pageToadletRegistry.addPage(new KnownSonesPage(this, loaders, templateRenderer));
279                 pageToadletRegistry.addPage(new EditProfilePage(this, loaders, templateRenderer));
280                 pageToadletRegistry.addPage(new EditProfileFieldPage(this, loaders, templateRenderer));
281                 pageToadletRegistry.addPage(new DeleteProfileFieldPage(this, loaders, templateRenderer));
282                 pageToadletRegistry.addPage(new CreatePostPage(this, loaders, templateRenderer));
283                 pageToadletRegistry.addPage(new CreateReplyPage(this, loaders, templateRenderer));
284                 pageToadletRegistry.addPage(new ViewSonePage(this, loaders, templateRenderer));
285                 pageToadletRegistry.addPage(new ViewPostPage(this, loaders, templateRenderer));
286                 pageToadletRegistry.addPage(new LikePage(this, loaders, templateRenderer));
287                 pageToadletRegistry.addPage(new UnlikePage(this, loaders, templateRenderer));
288                 pageToadletRegistry.addPage(new DeletePostPage(this, loaders, templateRenderer));
289                 pageToadletRegistry.addPage(new DeleteReplyPage(this, loaders, templateRenderer));
290                 pageToadletRegistry.addPage(new LockSonePage(this, loaders, templateRenderer));
291                 pageToadletRegistry.addPage(new UnlockSonePage(this, loaders, templateRenderer));
292                 pageToadletRegistry.addPage(new FollowSonePage(this, loaders, templateRenderer));
293                 pageToadletRegistry.addPage(new UnfollowSonePage(this, loaders, templateRenderer));
294                 pageToadletRegistry.addPage(new ImageBrowserPage(this, loaders, templateRenderer));
295                 pageToadletRegistry.addPage(new CreateAlbumPage(this, loaders, templateRenderer));
296                 pageToadletRegistry.addPage(new EditAlbumPage(this, loaders, templateRenderer));
297                 pageToadletRegistry.addPage(new DeleteAlbumPage(this, loaders, templateRenderer));
298                 pageToadletRegistry.addPage(new UploadImagePage(this, loaders, templateRenderer));
299                 pageToadletRegistry.addPage(new EditImagePage(this, loaders, templateRenderer));
300                 pageToadletRegistry.addPage(new DeleteImagePage(this, loaders, templateRenderer));
301                 pageToadletRegistry.addPage(new MarkAsKnownPage(this, loaders, templateRenderer));
302                 pageToadletRegistry.addPage(new BookmarkPage(this, loaders, templateRenderer));
303                 pageToadletRegistry.addPage(new UnbookmarkPage(this, loaders, templateRenderer));
304                 pageToadletRegistry.addPage(new BookmarksPage(this, loaders, templateRenderer));
305                 pageToadletRegistry.addPage(new SearchPage(this, loaders, templateRenderer));
306                 pageToadletRegistry.addPage(new DeleteSonePage(this, loaders, templateRenderer));
307                 pageToadletRegistry.addPage(new LoginPage(this, loaders, templateRenderer));
308                 pageToadletRegistry.addPage(new LogoutPage(this, loaders, templateRenderer));
309                 pageToadletRegistry.addPage(new OptionsPage(this, loaders, templateRenderer));
310                 pageToadletRegistry.addPage(new RescuePage(this, loaders, templateRenderer));
311                 pageToadletRegistry.addPage(new AboutPage(this, loaders, templateRenderer, new PluginVersion(SonePlugin.getPluginVersion()), new PluginYear(sonePlugin.getYear()), new PluginHomepage(sonePlugin.getHomepage())));
312                 pageToadletRegistry.addPage(new InvalidPage(this, loaders, templateRenderer));
313                 pageToadletRegistry.addPage(new NoPermissionPage(this, loaders, templateRenderer));
314                 pageToadletRegistry.addPage(new EmptyImageTitlePage(this, loaders, templateRenderer));
315                 pageToadletRegistry.addPage(new EmptyAlbumTitlePage(this, loaders, templateRenderer));
316                 pageToadletRegistry.addPage(new DismissNotificationPage(this, loaders, templateRenderer));
317                 pageToadletRegistry.addPage(new DebugPage(this, loaders, templateRenderer));
318                 pageToadletRegistry.addDebugPage(new MetricsPage(this, loaders, templateRenderer, metricRegistry));
319                 pageToadletRegistry.addPage(loaders.<FreenetRequest>loadStaticPage("css/", "/static/css/", "text/css"));
320                 pageToadletRegistry.addPage(loaders.<FreenetRequest>loadStaticPage("javascript/", "/static/javascript/", "text/javascript"));
321                 pageToadletRegistry.addPage(loaders.<FreenetRequest>loadStaticPage("images/", "/static/images/", "image/png"));
322                 pageToadletRegistry.addPage(new TemplatePage<FreenetRequest>("OpenSearch.xml", "application/opensearchdescription+xml", templateContextFactory, openSearchTemplate));
323                 pageToadletRegistry.addPage(new GetImagePage(this));
324                 pageToadletRegistry.addPage(new GetTranslationAjaxPage(this));
325                 pageToadletRegistry.addPage(new GetStatusAjaxPage(this, elementLoader, newElements, timeTextConverter, l10nFilter, TimeZone.getDefault()));
326                 pageToadletRegistry.addPage(new GetNotificationsAjaxPage(this));
327                 pageToadletRegistry.addPage(new DismissNotificationAjaxPage(this));
328                 pageToadletRegistry.addPage(new CreatePostAjaxPage(this));
329                 pageToadletRegistry.addPage(new CreateReplyAjaxPage(this));
330                 pageToadletRegistry.addPage(new GetReplyAjaxPage(this, replyTemplate));
331                 pageToadletRegistry.addPage(new GetPostAjaxPage(this, postTemplate));
332                 pageToadletRegistry.addPage(new GetLinkedElementAjaxPage(this, elementLoader, linkedElementRenderFilter));
333                 pageToadletRegistry.addPage(new GetTimesAjaxPage(this, timeTextConverter, l10nFilter, TimeZone.getDefault()));
334                 pageToadletRegistry.addPage(new MarkAsKnownAjaxPage(this));
335                 pageToadletRegistry.addPage(new DeletePostAjaxPage(this));
336                 pageToadletRegistry.addPage(new DeleteReplyAjaxPage(this));
337                 pageToadletRegistry.addPage(new LockSoneAjaxPage(this));
338                 pageToadletRegistry.addPage(new UnlockSoneAjaxPage(this));
339                 pageToadletRegistry.addPage(new FollowSoneAjaxPage(this));
340                 pageToadletRegistry.addPage(new UnfollowSoneAjaxPage(this));
341                 pageToadletRegistry.addPage(new EditAlbumAjaxPage(this));
342                 pageToadletRegistry.addPage(new EditImageAjaxPage(this, parserFilter, shortenFilter, renderFilter));
343                 pageToadletRegistry.addPage(new LikeAjaxPage(this));
344                 pageToadletRegistry.addPage(new UnlikeAjaxPage(this));
345                 pageToadletRegistry.addPage(new GetLikesAjaxPage(this));
346                 pageToadletRegistry.addPage(new BookmarkAjaxPage(this));
347                 pageToadletRegistry.addPage(new UnbookmarkAjaxPage(this));
348                 pageToadletRegistry.addPage(new EditProfileFieldAjaxPage(this));
349                 pageToadletRegistry.addPage(new DeleteProfileFieldAjaxPage(this));
350                 pageToadletRegistry.addPage(new MoveProfileFieldAjaxPage(this));
351
352                 pageToadletRegistry.registerToadlets();
353         }
354
355         @Subscribe
356         public void debugActivated(@Nonnull DebugActivatedEvent debugActivatedEvent) {
357                 pageToadletRegistry.activateDebugMode();
358         }
359
360 }