aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/com/juick/server/configuration
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/juick/server/configuration')
-rw-r--r--src/main/java/com/juick/server/configuration/ActivityPubClientConfig.java22
-rw-r--r--src/main/java/com/juick/server/configuration/ActivityPubClientErrorHandler.java35
-rw-r--r--src/main/java/com/juick/server/configuration/ApiAppConfiguration.java76
-rw-r--r--src/main/java/com/juick/server/configuration/BaseWebConfiguration.java63
-rw-r--r--src/main/java/com/juick/server/configuration/SapeConfiguration.java39
-rw-r--r--src/main/java/com/juick/server/configuration/SecurityConfig.java215
-rw-r--r--src/main/java/com/juick/server/configuration/StorageConfiguration.java20
-rw-r--r--src/main/java/com/juick/server/configuration/TelegramConfig.java15
-rw-r--r--src/main/java/com/juick/server/configuration/WwwAppConfiguration.java120
-rw-r--r--src/main/java/com/juick/server/configuration/XMPPConfig.java55
10 files changed, 660 insertions, 0 deletions
diff --git a/src/main/java/com/juick/server/configuration/ActivityPubClientConfig.java b/src/main/java/com/juick/server/configuration/ActivityPubClientConfig.java
new file mode 100644
index 00000000..9bc1b656
--- /dev/null
+++ b/src/main/java/com/juick/server/configuration/ActivityPubClientConfig.java
@@ -0,0 +1,22 @@
+package com.juick.server.configuration;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.client.SimpleClientHttpRequestFactory;
+import org.springframework.web.client.RestTemplate;
+
+import javax.inject.Inject;
+
+@Configuration
+public class ActivityPubClientConfig {
+ @Inject
+ ActivityPubClientErrorHandler activityPubClientErrorHandler;
+ @Bean
+ public RestTemplate apClient() {
+ SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
+ requestFactory.setOutputStreaming(false);
+ RestTemplate restTemplate = new RestTemplate(requestFactory);
+ restTemplate.setErrorHandler(activityPubClientErrorHandler);
+ return restTemplate;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/com/juick/server/configuration/ActivityPubClientErrorHandler.java b/src/main/java/com/juick/server/configuration/ActivityPubClientErrorHandler.java
new file mode 100644
index 00000000..e535b3e5
--- /dev/null
+++ b/src/main/java/com/juick/server/configuration/ActivityPubClientErrorHandler.java
@@ -0,0 +1,35 @@
+package com.juick.server.configuration;
+
+import com.juick.service.activities.DeleteUserEvent;
+import org.apache.commons.io.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.ApplicationEventPublisher;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.client.ClientHttpResponse;
+import org.springframework.stereotype.Component;
+import org.springframework.web.client.DefaultResponseErrorHandler;
+
+import javax.annotation.Nonnull;
+import javax.inject.Inject;
+import java.io.IOException;
+import java.net.URI;
+import java.nio.charset.StandardCharsets;
+
+@Component
+public class ActivityPubClientErrorHandler extends DefaultResponseErrorHandler {
+ private static final Logger logger = LoggerFactory.getLogger(ActivityPubClientErrorHandler.class);
+
+ @Inject
+ private ApplicationEventPublisher applicationEventPublisher;
+ @Override
+ public void handleError(URI contextUri, HttpMethod method, @Nonnull ClientHttpResponse response) throws IOException {
+ logger.warn("HTTP ERROR {} {} : {}", response.getStatusCode().value(),
+ response.getStatusText(), IOUtils.toString(response.getBody(), StandardCharsets.UTF_8));
+ if (response.getStatusCode().equals(HttpStatus.GONE)) {
+ logger.warn("Server report {} is gone, deleting", contextUri.toASCIIString());
+ applicationEventPublisher.publishEvent(new DeleteUserEvent(this, contextUri.toASCIIString()));
+ }
+ }
+}
diff --git a/src/main/java/com/juick/server/configuration/ApiAppConfiguration.java b/src/main/java/com/juick/server/configuration/ApiAppConfiguration.java
new file mode 100644
index 00000000..5a5d2c7b
--- /dev/null
+++ b/src/main/java/com/juick/server/configuration/ApiAppConfiguration.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2008-2017, Juick
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.juick.server.configuration;
+
+import com.juick.server.WebsocketManager;
+import com.juick.server.api.rss.MessagesView;
+import com.juick.server.api.rss.RepliesView;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.Ordered;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+import org.springframework.web.servlet.view.BeanNameViewResolver;
+import org.springframework.web.servlet.view.feed.AbstractRssFeedView;
+import org.springframework.web.socket.config.annotation.EnableWebSocket;
+import org.springframework.web.socket.config.annotation.ServletWebSocketHandlerRegistry;
+import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
+import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
+import org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean;
+
+import javax.annotation.Nonnull;
+import javax.inject.Inject;
+
+/**
+ * Created by aalexeev on 11/12/16.
+ */
+@Configuration
+@EnableAsync(proxyTargetClass = true)
+@EnableScheduling
+@EnableWebSocket
+public class ApiAppConfiguration implements WebMvcConfigurer, WebSocketConfigurer {
+ @Inject
+ private WebsocketManager websocketManager;
+
+ @Override
+ public void registerWebSocketHandlers(@Nonnull WebSocketHandlerRegistry registry) {
+ ((ServletWebSocketHandlerRegistry) registry).setOrder(Ordered.HIGHEST_PRECEDENCE);
+ registry.addHandler(websocketManager, "/ws/**").setAllowedOrigins("*");
+ }
+
+ @Bean
+ public ServletServerContainerFactoryBean createWebSocketContainer() {
+ ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
+ container.setMaxTextMessageBufferSize(8192);
+ container.setMaxBinaryMessageBufferSize(8192);
+ return container;
+ }
+ @Bean
+ public BeanNameViewResolver beanNameViewResolver() {
+ return new BeanNameViewResolver();
+ }
+ @Bean
+ AbstractRssFeedView messagesView() {
+ return new MessagesView();
+ }
+ @Bean
+ AbstractRssFeedView repliesView() {
+ return new RepliesView();
+ }
+}
diff --git a/src/main/java/com/juick/server/configuration/BaseWebConfiguration.java b/src/main/java/com/juick/server/configuration/BaseWebConfiguration.java
new file mode 100644
index 00000000..23a35384
--- /dev/null
+++ b/src/main/java/com/juick/server/configuration/BaseWebConfiguration.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2008-2017, Juick
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.juick.server.configuration;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.SchedulingConfigurer;
+import org.springframework.scheduling.config.ScheduledTaskRegistrar;
+import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+import org.springframework.web.servlet.resource.ResourceUrlEncodingFilter;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * Created by vitalyster on 28.06.2016.
+ */
+@Configuration
+public class BaseWebConfiguration implements WebMvcConfigurer, SchedulingConfigurer {
+
+
+ @Override
+ public void configurePathMatch(PathMatchConfigurer configurer) {
+ configurer.setUseSuffixPatternMatch(false);
+ }
+
+ @Bean
+ public ResourceUrlEncodingFilter resourceUrlEncodingFilter() {
+ return new ResourceUrlEncodingFilter();
+ }
+
+ @Override
+ public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
+ taskRegistrar.setScheduler(taskExecutor());
+ }
+
+ @Bean(destroyMethod="shutdown")
+ public Executor taskExecutor() {
+ return Executors.newScheduledThreadPool(100);
+ }
+
+ @Bean
+ public ExecutorService executorService() {
+ return Executors.newCachedThreadPool();
+ }
+}
diff --git a/src/main/java/com/juick/server/configuration/SapeConfiguration.java b/src/main/java/com/juick/server/configuration/SapeConfiguration.java
new file mode 100644
index 00000000..9727fbb1
--- /dev/null
+++ b/src/main/java/com/juick/server/configuration/SapeConfiguration.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2008-2017, Juick
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.juick.server.configuration;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import ru.sape.Sape;
+
+/**
+ * Created by vitalyster on 29.03.2017.
+ */
+@Configuration
+@ConditionalOnProperty("sape_user")
+public class SapeConfiguration {
+ @Value("${sape_user:}")
+ private String token;
+
+ @Bean
+ public Sape sape() {
+ return new Sape(token, "juick.com", 2000, 3600);
+ }
+}
diff --git a/src/main/java/com/juick/server/configuration/SecurityConfig.java b/src/main/java/com/juick/server/configuration/SecurityConfig.java
new file mode 100644
index 00000000..f02083d5
--- /dev/null
+++ b/src/main/java/com/juick/server/configuration/SecurityConfig.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2008-2017, Juick
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.juick.server.configuration;
+
+import com.juick.service.UserService;
+import com.juick.service.security.HashParamAuthenticationFilter;
+import com.juick.service.security.JuickUserDetailsService;
+import com.juick.service.security.deprecated.RequestParamHashRememberMeServices;
+import com.juick.service.security.entities.JuickUser;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.annotation.Order;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.builders.WebSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.web.AuthenticationEntryPoint;
+import org.springframework.security.web.authentication.HttpStatusEntryPoint;
+import org.springframework.security.web.authentication.RememberMeServices;
+import org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices;
+import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.CorsConfigurationSource;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Created by aalexeev on 11/21/16.
+ */
+@EnableWebSecurity
+public class SecurityConfig {
+ @Resource
+ private UserService userService;
+ @Value("${auth_remember_me_key:secret}")
+ private String rememberMeKey;
+ @Value("${web_domain:localhost}")
+ private String webDomain;
+
+ private static final String COOKIE_NAME = "juick-remember-me";
+
+ @Bean
+ public UserDetailsService userDetailsService() {
+ return new JuickUserDetailsService(userService);
+ }
+
+ @Configuration
+ @Order(1)
+ public static class ApiConfig extends WebSecurityConfigurerAdapter {
+ @Value("${auth_remember_me_key:secret}")
+ private String rememberMeKey;
+ @Value("${web_domain:localhost}")
+ private String webDomain;
+ @Resource
+ private UserService userService;
+ ApiConfig() {
+ super(true);
+ }
+ @Bean
+ RememberMeServices apiTokenServices(){
+ return new RequestParamHashRememberMeServices(rememberMeKey, userService);
+ }
+ @Bean
+ public HashParamAuthenticationFilter apiAuthenticationFilter() {
+ return new HashParamAuthenticationFilter(userService, apiTokenServices());
+ }
+
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ http.antMatcher("/api/**")
+ .addFilterBefore(apiAuthenticationFilter(), BasicAuthenticationFilter.class)
+ .authorizeRequests()
+ .antMatchers(HttpMethod.OPTIONS).permitAll()
+ .antMatchers("/api/", "/api/messages", "/api/messages/discussions", "/api/users", "/api/thread", "/api/tags", "/api/tlgmbtwbhk", "/api/fbwbhk",
+ "/api/skypebotendpoint", "/api/_fblogin", "/api/_vklogin", "/api/_tglogin", "/api/inbox", "/api/u/**", "/.well-known/webfinger", "/.well-known/x-nodeinfo2", "/rss/**", "/api/events").permitAll()
+ .anyRequest().hasRole("USER")
+ .and()
+ .anonymous().principal(JuickUser.ANONYMOUS_USER).authorities(JuickUser.ANONYMOUS_AUTHORITY)
+ .and()
+ .httpBasic().authenticationEntryPoint(juickAuthenticationEntryPoint())
+ .and().cors().configurationSource(corsConfigurationSource())
+ .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
+ .and().exceptionHandling().authenticationEntryPoint(juickAuthenticationEntryPoint())
+ .and()
+ .rememberMe()
+ .alwaysRemember(true)
+ .tokenValiditySeconds((int) TimeUnit.DAYS.toSeconds(6 * 30))
+ .rememberMeServices(apiTokenServices())
+ .key(rememberMeKey)
+ .and()
+ .headers().defaultsDisabled().cacheControl();
+ }
+
+ @Bean
+ public AuthenticationEntryPoint juickAuthenticationEntryPoint() {
+ return new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED);
+ }
+
+ @Bean
+ public CorsConfigurationSource corsConfigurationSource() {
+ CorsConfiguration configuration = new CorsConfiguration();
+
+ configuration.setAllowedOrigins(Collections.singletonList("*"));
+ configuration.setAllowedMethods(Arrays.asList("POST", "GET", "PUT", "OPTIONS", "DELETE"));
+ configuration.setAllowedHeaders(Collections.singletonList("*"));
+
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ source.registerCorsConfiguration("/api/**", configuration);
+
+ return source;
+ }
+ @Override
+ public void configure(WebSecurity web) {
+ web.debug(false);
+ web.ignoring().antMatchers("/api/v2/api-docs", "/api/configuration/ui", "/api/swagger-resources/**",
+ "/api/configuration/**", "/swagger-ui.html", "/webjars/**", "/h2-console/**");
+ }
+ }
+
+ @Configuration
+ public static class WebConfig extends WebSecurityConfigurerAdapter {
+ @Value("${auth_remember_me_key:secret}")
+ private String rememberMeKey;
+ @Value("${web_domain:localhost}")
+ private String webDomain;
+ @Resource
+ private UserService userService;
+ @Inject
+ private UserDetailsService userDetailsService;
+ @Bean
+ @Qualifier("www")
+ public HashParamAuthenticationFilter wwwAuthenticationFilter() {
+ return new HashParamAuthenticationFilter(userService, hashCookieServices());
+ }
+ @Bean
+ @Qualifier("www")
+ public RememberMeServices hashCookieServices() {
+ TokenBasedRememberMeServices services = new TokenBasedRememberMeServices(
+ rememberMeKey, userDetailsService);
+
+ services.setCookieName(COOKIE_NAME);
+ services.setCookieDomain(webDomain);
+ services.setAlwaysRemember(true);
+ services.setTokenValiditySeconds(6 * 30 * 24 * 3600);
+ services.setUseSecureCookie(false); // TODO set true if https is supports
+
+ return services;
+ }
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ http
+ .addFilterBefore(wwwAuthenticationFilter(), BasicAuthenticationFilter.class)
+ .authorizeRequests()
+ .antMatchers("/settings", "/pm/**", "/**/bl", "/_twitter", "/post", "/post2", "/comment")
+ .authenticated()
+ .anyRequest().permitAll()
+ .and()
+ .anonymous().principal(JuickUser.ANONYMOUS_USER).authorities(JuickUser.ANONYMOUS_AUTHORITY)
+ .and()
+ .sessionManagement().invalidSessionUrl("/")
+ .and()
+ .logout()
+ .invalidateHttpSession(true)
+ .logoutUrl("/logout")
+ .logoutSuccessUrl("/login?logout")
+ .deleteCookies("hash", COOKIE_NAME)
+ .and()
+ .formLogin()
+ .loginPage("/login")
+ .permitAll()
+ .defaultSuccessUrl("/")
+ .loginProcessingUrl("/login")
+ .usernameParameter("username")
+ .passwordParameter("password")
+ .failureUrl("/login?error=1")
+ .and()
+ .rememberMe()
+ .rememberMeCookieDomain(webDomain).key(rememberMeKey)
+ .rememberMeServices(hashCookieServices())
+ .and()
+ .csrf().disable()
+ .headers().defaultsDisabled().cacheControl();
+ }
+ @Override
+ public void configure(WebSecurity web) {
+ web.debug(false);
+ web.ignoring().antMatchers("/style*.css", "/scripts*.js", "/h2-console/**", "/.well-known/**", "/ws/**");
+ }
+ }
+}
diff --git a/src/main/java/com/juick/server/configuration/StorageConfiguration.java b/src/main/java/com/juick/server/configuration/StorageConfiguration.java
new file mode 100644
index 00000000..4101f37d
--- /dev/null
+++ b/src/main/java/com/juick/server/configuration/StorageConfiguration.java
@@ -0,0 +1,20 @@
+package com.juick.server.configuration;
+
+import com.juick.service.ImagesService;
+import com.juick.service.ImagesServiceImpl;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class StorageConfiguration {
+
+ @Value("${upload_tmp_dir:#{systemEnvironment['TEMP'] ?: '/tmp'}}")
+ private String tmpDir;
+ @Value("${img_path:#{systemEnvironment['TEMP'] ?: '/tmp'}}")
+ private String imgDir;
+ @Bean
+ public ImagesService imagesService() {
+ return new ImagesServiceImpl(imgDir, tmpDir);
+ }
+}
diff --git a/src/main/java/com/juick/server/configuration/TelegramConfig.java b/src/main/java/com/juick/server/configuration/TelegramConfig.java
new file mode 100644
index 00000000..ebd1fd15
--- /dev/null
+++ b/src/main/java/com/juick/server/configuration/TelegramConfig.java
@@ -0,0 +1,15 @@
+package com.juick.server.configuration;
+
+import com.juick.server.TelegramBotManager;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@ConditionalOnProperty(name = "telegram_token")
+public class TelegramConfig {
+ @Bean
+ public TelegramBotManager telegramBotManager() {
+ return new TelegramBotManager();
+ }
+}
diff --git a/src/main/java/com/juick/server/configuration/WwwAppConfiguration.java b/src/main/java/com/juick/server/configuration/WwwAppConfiguration.java
new file mode 100644
index 00000000..72889f96
--- /dev/null
+++ b/src/main/java/com/juick/server/configuration/WwwAppConfiguration.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2008-2017, Juick
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.juick.server.configuration;
+
+import com.juick.server.www.HelpService;
+import com.juick.service.TagService;
+import com.juick.service.UserService;
+import com.mitchellbosecke.pebble.PebbleEngine;
+import com.mitchellbosecke.pebble.extension.FormatterExtension;
+import com.mitchellbosecke.pebble.loader.ClasspathLoader;
+import com.mitchellbosecke.pebble.loader.Loader;
+import com.mitchellbosecke.pebble.spring.PebbleViewResolver;
+import com.mitchellbosecke.pebble.spring.extension.SpringExtension;
+import org.apache.commons.codec.CharEncoding;
+import org.commonmark.ext.autolink.AutolinkExtension;
+import org.commonmark.node.Link;
+import org.commonmark.parser.Parser;
+import org.commonmark.renderer.html.HtmlRenderer;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.cache.caffeine.CaffeineCacheManager;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.ViewResolver;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+import javax.inject.Inject;
+import java.util.Collections;
+
+/**
+ * Created by aalexeev on 11/22/16.
+ */
+@Configuration
+@EnableCaching
+public class WwwAppConfiguration implements WebMvcConfigurer {
+ @Inject
+ private UserService userService;
+ @Inject
+ private TagService tagService;
+ @Bean
+ public CaffeineCacheManager cacheManager() {
+ return new CaffeineCacheManager("help");
+ }
+
+ @Bean
+ public HelpService helpService() {
+ return new HelpService("help");
+ }
+
+ @Bean
+ public Parser cmParser() {
+ return Parser.builder().extensions(Collections.singletonList(AutolinkExtension.create())).build();
+ }
+ @Bean
+ public HtmlRenderer helpRenderer() {
+ return HtmlRenderer.builder()
+ .attributeProviderFactory(context -> (node, tagName, attributes) -> {
+ if (node instanceof Link) {
+ Link link = (Link) node;
+ if (link.getDestination().startsWith("/")) {
+ String destination = "/" + helpService().getHelpPath() + link.getDestination();
+ link.setDestination(destination);
+ attributes.put("href", destination);
+ }
+ }
+ })
+ .build();
+ }
+ @Bean
+ public Loader templateLoader() {
+ return new ClasspathLoader();
+ }
+
+ @Bean
+ public SpringExtension springExtension() {
+ return new SpringExtension();
+ }
+
+ @Bean
+ public PebbleEngine pebbleEngine() {
+ boolean devToolsArePresent = false;
+ try {
+ Class.forName("org.springframework.boot.devtools.livereload.Connection");
+ devToolsArePresent = true;
+ } catch (ClassNotFoundException e) {
+ // release mode
+ }
+ return new PebbleEngine.Builder()
+ .loader(this.templateLoader())
+ .cacheActive(!devToolsArePresent)
+ .extension(springExtension())
+ .extension(new FormatterExtension())
+ .strictVariables(true)
+ .build();
+ }
+
+ @Bean
+ public ViewResolver viewResolver() {
+ PebbleViewResolver viewResolver = new PebbleViewResolver();
+ viewResolver.setPrefix("templates");
+ viewResolver.setSuffix(".html");
+ viewResolver.setPebbleEngine(pebbleEngine());
+ viewResolver.setCharacterEncoding(CharEncoding.UTF_8);
+ return viewResolver;
+ }
+}
diff --git a/src/main/java/com/juick/server/configuration/XMPPConfig.java b/src/main/java/com/juick/server/configuration/XMPPConfig.java
new file mode 100644
index 00000000..2feef286
--- /dev/null
+++ b/src/main/java/com/juick/server/configuration/XMPPConfig.java
@@ -0,0 +1,55 @@
+package com.juick.server.configuration;
+
+import com.juick.server.XMPPConnection;
+import com.juick.server.XMPPServer;
+import com.juick.server.xmpp.JidConverter;
+import com.juick.server.xmpp.iq.MessageQuery;
+import com.juick.server.xmpp.router.XMPPRouter;
+import com.juick.server.xmpp.s2s.BasicXmppSession;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.DependsOn;
+import org.springframework.core.convert.ConversionService;
+import org.springframework.format.support.DefaultFormattingConversionService;
+import rocks.xmpp.core.session.Extension;
+import rocks.xmpp.core.session.XmppSessionConfiguration;
+import rocks.xmpp.core.session.debug.LogbackDebugger;
+
+import java.time.Duration;
+
+@Configuration
+@ConditionalOnProperty("xmppbot_jid")
+public class XMPPConfig {
+ @Value("${hostname:localhost}")
+ private String hostname;
+ @Bean
+ public BasicXmppSession session() {
+ XmppSessionConfiguration configuration = XmppSessionConfiguration.builder()
+ .extensions(Extension.of(com.juick.Message.class), Extension.of(MessageQuery.class))
+ .debugger(LogbackDebugger.class)
+ .defaultResponseTimeout(Duration.ofMillis(120000))
+ .build();
+ return BasicXmppSession.create(hostname, configuration);
+ }
+ @Bean
+ public static ConversionService conversionService() {
+ DefaultFormattingConversionService cs = new DefaultFormattingConversionService();
+ cs.addConverter(new JidConverter());
+ return cs;
+ }
+ @Bean
+ public XMPPServer xmppServer() {
+ return new XMPPServer();
+ }
+ @Bean
+ public XMPPRouter xmppRouter() {
+ return new XMPPRouter();
+ }
+ @Bean
+ @DependsOn("xmppRouter")
+ public XMPPConnection xmppConnection() {
+ return new XMPPConnection();
+ }
+}