From a608baeed738894433aacfa041e2617f60ce959f Mon Sep 17 00:00:00 2001
From: Vitaly Takmazov
Date: Sat, 4 Apr 2020 01:15:01 +0300
Subject: Initialize all components from configuration
---
.../config/ActivityPubClientErrorHandler.java | 52 +++++
.../java/com/juick/config/ActivityPubConfig.java | 79 ++++++++
src/main/java/com/juick/config/MailConfig.java | 32 +++
src/main/java/com/juick/config/RssConfig.java | 39 ++++
src/main/java/com/juick/config/SapeConfig.java | 39 ++++
src/main/java/com/juick/config/SecurityConfig.java | 224 +++++++++++++++++++++
.../com/juick/config/SignInWithAppleConfig.java | 45 +++++
src/main/java/com/juick/config/StorageConfig.java | 37 ++++
src/main/java/com/juick/config/TelegramConfig.java | 32 +++
src/main/java/com/juick/config/TwitterConfig.java | 32 +++
src/main/java/com/juick/config/WebConfig.java | 181 +++++++++++++++++
src/main/java/com/juick/config/XMPPConfig.java | 41 ++++
12 files changed, 833 insertions(+)
create mode 100644 src/main/java/com/juick/config/ActivityPubClientErrorHandler.java
create mode 100644 src/main/java/com/juick/config/ActivityPubConfig.java
create mode 100644 src/main/java/com/juick/config/MailConfig.java
create mode 100644 src/main/java/com/juick/config/RssConfig.java
create mode 100644 src/main/java/com/juick/config/SapeConfig.java
create mode 100644 src/main/java/com/juick/config/SecurityConfig.java
create mode 100644 src/main/java/com/juick/config/SignInWithAppleConfig.java
create mode 100644 src/main/java/com/juick/config/StorageConfig.java
create mode 100644 src/main/java/com/juick/config/TelegramConfig.java
create mode 100644 src/main/java/com/juick/config/TwitterConfig.java
create mode 100644 src/main/java/com/juick/config/WebConfig.java
create mode 100644 src/main/java/com/juick/config/XMPPConfig.java
(limited to 'src/main/java/com/juick/config')
diff --git a/src/main/java/com/juick/config/ActivityPubClientErrorHandler.java b/src/main/java/com/juick/config/ActivityPubClientErrorHandler.java
new file mode 100644
index 00000000..cd67fb5e
--- /dev/null
+++ b/src/main/java/com/juick/config/ActivityPubClientErrorHandler.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2008-2019, 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 .
+ */
+
+package com.juick.config;
+
+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("ActivityPub");
+
+ @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/config/ActivityPubConfig.java b/src/main/java/com/juick/config/ActivityPubConfig.java
new file mode 100644
index 00000000..0411d0c7
--- /dev/null
+++ b/src/main/java/com/juick/config/ActivityPubConfig.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2008-2019, 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 .
+ */
+
+package com.juick.config;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.juick.ActivityPubManager;
+import com.juick.SignatureManager;
+import com.juick.www.api.activity.model.Activity;
+import com.juick.util.HeaderRequestInterceptor;
+import org.apache.http.client.config.CookieSpecs;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.protocol.HttpClientContext;
+import org.apache.http.protocol.HttpContext;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
+import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
+import org.springframework.web.client.RestTemplate;
+
+import javax.inject.Inject;
+import java.net.URI;
+import java.util.Collections;
+
+@Configuration
+public class ActivityPubConfig {
+ @Inject
+ ActivityPubClientErrorHandler activityPubClientErrorHandler;
+ @Inject
+ ObjectMapper jsonMapper;
+ @Bean
+ public MappingJackson2HttpMessageConverter mappingJacksonHttpMessageConverter() {
+ MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
+ converter.setObjectMapper(jsonMapper);
+ return converter;
+ }
+ @Bean
+ public ActivityPubManager activityPubManager() {
+ return new ActivityPubManager();
+ }
+ @Bean
+ public RestTemplate apClient() {
+ RestTemplate restTemplate = new RestTemplate();
+ restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory() {
+ @Override
+ protected HttpContext createHttpContext(HttpMethod httpMethod, URI uri) {
+ HttpClientContext context = HttpClientContext.create();
+ context.setRequestConfig(getRequestConfig());
+ return context;
+ }
+ RequestConfig getRequestConfig() {
+ RequestConfig.Builder builder = RequestConfig.custom()
+ .setCookieSpec(CookieSpecs.IGNORE_COOKIES);
+ return builder.build();
+ }
+ });
+ restTemplate.getMessageConverters().add(0, mappingJacksonHttpMessageConverter());
+ restTemplate.setErrorHandler(activityPubClientErrorHandler);
+ restTemplate.setInterceptors(Collections.singletonList(
+ new HeaderRequestInterceptor("Accept", Activity.ACTIVITY_MEDIA_TYPE)));
+ return restTemplate;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/juick/config/MailConfig.java b/src/main/java/com/juick/config/MailConfig.java
new file mode 100644
index 00000000..209796be
--- /dev/null
+++ b/src/main/java/com/juick/config/MailConfig.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2008-2020, 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 .
+ */
+
+package com.juick.config;
+
+import com.juick.EmailManager;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@ConditionalOnProperty("service_email")
+public class MailConfig {
+ @Bean
+ public EmailManager emailManager() {
+ return new EmailManager();
+ }
+}
diff --git a/src/main/java/com/juick/config/RssConfig.java b/src/main/java/com/juick/config/RssConfig.java
new file mode 100644
index 00000000..9619f2f7
--- /dev/null
+++ b/src/main/java/com/juick/config/RssConfig.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2008-2019, 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 .
+ */
+
+package com.juick.config;
+
+import com.juick.www.rss.MessagesView;
+import com.juick.www.rss.RepliesView;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.view.feed.AbstractRssFeedView;
+
+/**
+ * Created by aalexeev on 11/12/16.
+ */
+@Configuration
+public class RssConfig {
+ @Bean
+ AbstractRssFeedView messagesView() {
+ return new MessagesView();
+ }
+ @Bean
+ AbstractRssFeedView repliesView() {
+ return new RepliesView();
+ }
+}
diff --git a/src/main/java/com/juick/config/SapeConfig.java b/src/main/java/com/juick/config/SapeConfig.java
new file mode 100644
index 00000000..279cc88f
--- /dev/null
+++ b/src/main/java/com/juick/config/SapeConfig.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2008-2019, 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 .
+ */
+
+package com.juick.config;
+
+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 SapeConfig {
+ @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/config/SecurityConfig.java b/src/main/java/com/juick/config/SecurityConfig.java
new file mode 100644
index 00000000..8f6325f6
--- /dev/null
+++ b/src/main/java/com/juick/config/SecurityConfig.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2008-2020, 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 .
+ */
+
+package com.juick.config;
+
+import com.juick.SignatureManager;
+import com.juick.service.UserService;
+import com.juick.service.security.HTTPSignatureAuthenticationFilter;
+import com.juick.service.security.HashParamAuthenticationFilter;
+import com.juick.service.security.JuickUserDetailsService;
+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.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.NullRememberMeServices;
+import org.springframework.security.web.authentication.RememberMeServices;
+import org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices;
+import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint;
+import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
+import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
+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;
+
+ private static final String COOKIE_NAME = "juick-remember-me";
+
+ @Bean
+ public UserDetailsService userDetailsService() {
+ return new JuickUserDetailsService(userService);
+ }
+ @Bean
+ static 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);
+ source.registerCorsConfiguration("/u/**", configuration);
+ source.registerCorsConfiguration("/n/**", configuration);
+ return source;
+ }
+
+ @Configuration
+ @Order(1)
+ public static class ApiConfig extends WebSecurityConfigurerAdapter {
+ @Value("${auth_remember_me_key:secret}")
+ private String rememberMeKey;
+ @Resource
+ private UserService userService;
+ @Resource
+ private SignatureManager signatureManager;
+ ApiConfig() {
+ super(true);
+ }
+ @Bean
+ RememberMeServices apiTokenServices() {
+ return new NullRememberMeServices();
+ }
+ @Bean
+ public HashParamAuthenticationFilter apiAuthenticationFilter() {
+ return new HashParamAuthenticationFilter(userService, apiTokenServices());
+ }
+
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ http.antMatcher("/api/**")
+ .addFilterBefore(apiAuthenticationFilter(), BasicAuthenticationFilter.class)
+ .addFilterBefore(new HTTPSignatureAuthenticationFilter(signatureManager, userService), BasicAuthenticationFilter.class)
+ .authorizeRequests()
+ .antMatchers(HttpMethod.OPTIONS).permitAll()
+ .antMatchers("/api/", "/api/messages", "/api/avatar", "/api/messages/discussions",
+ "/api/users", "/api/thread", "/api/tags", "/api/tlgmbtwbhk", "/api/fbwbhk",
+ "/api/skypebotendpoint", "/api/_fblogin", "/api/_vklogin", "/api/_tglogin",
+ "/api/_google", "/api/_applelogin", "/api/signup", "/api/inbox", "/api/events", "/api/info/**",
+ "/api/nodeinfo/2.0").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() {
+ var entryPoint = new BasicAuthenticationEntryPoint();
+ entryPoint.setRealmName("Juick");
+ return entryPoint;
+ }
+
+ @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()
+ .antMatchers("/actuator/**").hasRole("ADMIN")
+ .anyRequest().permitAll()
+ .and()
+ .anonymous().principal(JuickUser.ANONYMOUS_USER).authorities(JuickUser.ANONYMOUS_AUTHORITY)
+ .and().cors().configurationSource(corsConfigurationSource())
+ .and().sessionManagement()
+ .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
+ .invalidSessionUrl("/")
+ .and()
+ .logout()
+ .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
+ .invalidateHttpSession(true)
+ .logoutUrl("/logout")
+ .logoutSuccessUrl("/")
+ .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/**");
+ }
+ }
+}
diff --git a/src/main/java/com/juick/config/SignInWithAppleConfig.java b/src/main/java/com/juick/config/SignInWithAppleConfig.java
new file mode 100644
index 00000000..0b41cb7e
--- /dev/null
+++ b/src/main/java/com/juick/config/SignInWithAppleConfig.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2008-2019, 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 .
+ */
+
+package com.juick.config;
+
+import com.github.scribejava.apis.AppleClientSecretGenerator;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.io.Resource;
+
+import java.io.IOException;
+import java.security.NoSuchAlgorithmException;
+import java.security.spec.InvalidKeySpecException;
+
+@Configuration
+public class SignInWithAppleConfig {
+ @Value("${apple_app_id:com.example.app}")
+ private String appId;
+ @Value("${apple_team_id:teamid}")
+ private String teamId;
+ @Value("${apple_key_id:keyid}")
+ private String keyId;
+ @Value("${apple_key_path:classpath:testkey.p8}")
+ private Resource keyPath;
+
+ @Bean
+ public AppleClientSecretGenerator clientSecretGenerator() throws IOException, InvalidKeySpecException, NoSuchAlgorithmException {
+ return new AppleClientSecretGenerator(appId, teamId, keyId, keyPath.getFile().toPath());
+ }
+}
diff --git a/src/main/java/com/juick/config/StorageConfig.java b/src/main/java/com/juick/config/StorageConfig.java
new file mode 100644
index 00000000..d46b0a4f
--- /dev/null
+++ b/src/main/java/com/juick/config/StorageConfig.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2008-2019, 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 .
+ */
+
+package com.juick.config;
+
+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 StorageConfig {
+
+ @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/config/TelegramConfig.java b/src/main/java/com/juick/config/TelegramConfig.java
new file mode 100644
index 00000000..fb0abd4f
--- /dev/null
+++ b/src/main/java/com/juick/config/TelegramConfig.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2008-2019, 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 .
+ */
+
+package com.juick.config;
+
+import com.juick.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/config/TwitterConfig.java b/src/main/java/com/juick/config/TwitterConfig.java
new file mode 100644
index 00000000..22540dc5
--- /dev/null
+++ b/src/main/java/com/juick/config/TwitterConfig.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2008-2020, 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 .
+ */
+
+package com.juick.config;
+
+import com.juick.TwitterManager;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@ConditionalOnProperty("twitter_consumer_key")
+public class TwitterConfig {
+ @Bean
+ public TwitterManager twitterManager() {
+ return new TwitterManager();
+ }
+}
diff --git a/src/main/java/com/juick/config/WebConfig.java b/src/main/java/com/juick/config/WebConfig.java
new file mode 100644
index 00000000..506c4dcf
--- /dev/null
+++ b/src/main/java/com/juick/config/WebConfig.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2008-2019, 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 .
+ */
+
+package com.juick.config;
+
+import com.juick.*;
+import com.juick.service.HelpService;
+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.extension.SpringExtension;
+import com.mitchellbosecke.pebble.spring.servlet.PebbleViewResolver;
+import com.overzealous.remark.Options;
+import com.overzealous.remark.Remark;
+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.beans.factory.annotation.Value;
+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.core.io.Resource;
+import org.springframework.http.CacheControl;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.web.servlet.ViewResolver;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+import org.springframework.web.servlet.resource.ResourceUrlEncodingFilter;
+import org.springframework.web.servlet.resource.VersionResourceResolver;
+
+import java.net.MalformedURLException;
+import java.nio.file.Paths;
+import java.util.Collections;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Created by aalexeev on 11/22/16.
+ */
+@Configuration
+@EnableCaching
+@EnableAsync(proxyTargetClass = true)
+@EnableScheduling
+public class WebConfig implements WebMvcConfigurer {
+ @Value("${img_path:#{systemEnvironment['TEMP'] ?: '/tmp'}}")
+ private String imgDir;
+ @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())
+ .newLineTrimming(false)
+ .strictVariables(true)
+ .build();
+ }
+
+ @Value("${keystore:classpath:juick-test-key.p12}")
+ private Resource keystore;
+ @Value("${keystore_password:secret}")
+ private String keystorePassword;
+ @Bean
+ public ResourceUrlEncodingFilter resourceUrlEncodingFilter() {
+ return new ResourceUrlEncodingFilter();
+ }
+ @Bean
+ public KeystoreManager keystoreManager() {
+ return new KeystoreManager(keystore, keystorePassword);
+ }
+ @Bean
+ public Remark remarkConverter() {
+ Options options = new Options();
+ options.inlineLinks = true;
+ return new Remark(options);
+ }
+ @Bean
+ public CommandsManager commandsManager() {
+ return new CommandsManager();
+ }
+ @Bean
+ public ServerManager serverManager() {
+ return new ServerManager();
+ }
+ @Bean
+ public SignatureManager signatureManager() {
+ return new SignatureManager();
+ }
+ @Bean
+ public TopManager topManager() {
+ return new TopManager();
+ }
+
+ @Bean
+ public ViewResolver viewResolver() {
+ PebbleViewResolver viewResolver = new PebbleViewResolver();
+ viewResolver.setPrefix("templates");
+ viewResolver.setSuffix(".html");
+ viewResolver.setPebbleEngine(pebbleEngine());
+ viewResolver.setCharacterEncoding(CharEncoding.UTF_8);
+ return viewResolver;
+ }
+ @Override
+ public void addResourceHandlers(ResourceHandlerRegistry registry) {
+ try {
+ registry
+ .addResourceHandler("/**", "/i/a/**")
+ .addResourceLocations("classpath:/static/", Paths.get(imgDir, "/a/").toUri().toURL().toString())
+ .setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS))
+ .resourceChain(false)
+ .addResolver(new VersionResourceResolver().addContentVersionStrategy("/**", "/i/a/**"));
+ } catch (MalformedURLException e) {
+ e.printStackTrace();
+ }
+ }
+
+}
diff --git a/src/main/java/com/juick/config/XMPPConfig.java b/src/main/java/com/juick/config/XMPPConfig.java
new file mode 100644
index 00000000..8a8fa4cc
--- /dev/null
+++ b/src/main/java/com/juick/config/XMPPConfig.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2008-2019, 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 .
+ */
+
+package com.juick.config;
+
+import com.juick.XMPPManager;
+import com.juick.util.xmpp.JidConverter;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.convert.ConversionService;
+import org.springframework.format.support.DefaultFormattingConversionService;
+
+@Configuration
+@ConditionalOnProperty("xmppbot_jid")
+public class XMPPConfig {
+ @Bean
+ public static ConversionService conversionService() {
+ DefaultFormattingConversionService cs = new DefaultFormattingConversionService();
+ cs.addConverter(new JidConverter());
+ return cs;
+ }
+ @Bean
+ public XMPPManager xmppConnection() {
+ return new XMPPManager();
+ }
+}
--
cgit v1.2.3