Compare commits

...

4 Commits

Author SHA1 Message Date
RM
884b5bf9a0 fix docker-compose.yaml 2026-10-01 21:01:31 +03:00
RM
15f0b1b4eb migration to cloud config 2026-10-01 20:47:18 +03:00
RM
9e6e68411b hide creds in env 2026-09-30 18:07:55 +03:00
RM
3ba15225ff try to fix ssl 2026-09-30 17:54:39 +03:00
8 changed files with 99 additions and 73 deletions

5
.gitignore vendored
View File

@@ -31,3 +31,8 @@ build/
### VS Code ### ### VS Code ###
.vscode/ .vscode/
### Environment variables ###
.env
application-prod.properties
application-local.properties

View File

@@ -1,3 +1,3 @@
FROM amazoncorretto:25-alpine-jdk FROM amazoncorretto:26-alpine-jdk
COPY torgi-0.0.1-SNAPSHOT.jar /home/torgi-0.0.1-SNAPSHOT.jar COPY torgi-0.0.1-SNAPSHOT.jar /home/torgi-0.0.1-SNAPSHOT.jar
CMD ["java", "-XX:+UseContainerSupport", "-XX:MaxRAMPercentage=75", "-XX:InitialRAMPercentage=50", "-Xms512m", "-Xmx4096m", "-jar","/home/torgi-0.0.1-SNAPSHOT.jar","from:m.ryabyh@gmail.com","runHeadless:true","token:changeit","to:m.ryabyh@gmail.com,AAAtapina@sberbank.ru,Oreshkina.V.V@sberbank.ru,MEvRyabykh@sberbank.ru","days:1"] ENTRYPOINT ["java", "-XX:+UseContainerSupport", "-XX:MaxRAMPercentage=75", "-XX:InitialRAMPercentage=50", "-Xms512m", "-Xmx4096m", "-jar", "/home/torgi-0.0.1-SNAPSHOT.jar"]

View File

@@ -11,9 +11,9 @@ services:
- service-db - service-db
environment: environment:
- SERVER_PORT=8181 - SERVER_PORT=8181
- SPRING_DATASOURCE_URL=jdbc:postgresql://service-db/torgi - SERVER_PORT=8181
- SPRING_DATASOURCE_USERNAME=username - SPRING_CLOUD_CONFIG_URI=http://192.168.2.22:10022
- SPRING_DATASOURCE_PASSWORD=password - SPRING_CLOUD_CONFIG_PROFILE=prod
restart: always restart: always
healthcheck: healthcheck:
test: wget --no-verbose --tries=1 --spider http://localhost:8181/health || exit 1 test: wget --no-verbose --tries=1 --spider http://localhost:8181/health || exit 1

17
pom.xml
View File

@@ -28,6 +28,7 @@
</scm> </scm>
<properties> <properties>
<java.version>17</java.version> <java.version>17</java.version>
<spring-cloud.version>2025.0.0</spring-cloud.version>
</properties> </properties>
<dependencies> <dependencies>
<dependency> <dependency>
@@ -84,8 +85,24 @@
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId> <artifactId>spring-boot-starter-actuator</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
</dependencies> </dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build> <build>
<plugins> <plugins>
<plugin> <plugin>

View File

@@ -1,9 +1,6 @@
package com.pledge.torgi.service; package com.pledge.torgi.service;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.pledge.torgi.model.TorgiEvent; import com.pledge.torgi.model.TorgiEvent;
import com.pledge.torgi.repositories.TorgiEventRepository; import com.pledge.torgi.repositories.TorgiEventRepository;
import lombok.SneakyThrows; import lombok.SneakyThrows;
@@ -26,7 +23,6 @@ import java.nio.file.FileSystems;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.*; import java.util.*;
import java.util.regex.Pattern;
import static com.pledge.torgi.utils.AppUtils.EMPTY; import static com.pledge.torgi.utils.AppUtils.EMPTY;
import static java.util.Objects.nonNull; import static java.util.Objects.nonNull;
@@ -34,15 +30,17 @@ import static java.util.Objects.nonNull;
public class DownloadHeadlessService { public class DownloadHeadlessService {
private final Logger logger = LoggerFactory.getLogger(DownloadHeadlessService.class); private final Logger logger = LoggerFactory.getLogger(DownloadHeadlessService.class);
private final ObjectMapper objectMapper = new ObjectMapper().configure(JsonParser.Feature.INCLUDE_SOURCE_IN_LOCATION, true).configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false).enable(JsonParser.Feature.INCLUDE_SOURCE_IN_LOCATION);
Pattern cadastralPattern = Pattern.compile("\\d{1,2}:\\d{1,2}:\\d{1,7}:\\d{1,9}");
Pattern vinPattern = Pattern.compile("\\b[A-HJ-NPR-Z0-9-]{12,17}\\b");
@SneakyThrows @SneakyThrows
public Map<String, Lot> downloadExcel(int retryCount, String link) { public Map<String, Lot> downloadExcel(int retryCount, String link) {
try { try {
HttpURLConnection connection = (HttpURLConnection) new URL(link).openConnection(); HttpURLConnection connection = (HttpURLConnection) new URL(link).openConnection();
connection.setRequestMethod("GET"); connection.setRequestMethod("GET");
connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36");
connection.setRequestProperty("Accept", "application/json, text/plain, */*");
connection.setRequestProperty("Accept-Language", "ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7");
connection.setConnectTimeout(5000);
connection.setReadTimeout(10000);
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) { if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
Map<String, Lot> data = new HashMap<>(); Map<String, Lot> data = new HashMap<>();
Workbook wb = new XSSFWorkbook(connection.getInputStream()); Workbook wb = new XSSFWorkbook(connection.getInputStream());

View File

@@ -4,66 +4,32 @@ import com.pledge.torgi.controller.storage.FileService;
import com.pledge.torgi.model.Emails; import com.pledge.torgi.model.Emails;
import com.pledge.torgi.repositories.EmailsRepository; import com.pledge.torgi.repositories.EmailsRepository;
import com.pledge.torgi.utils.StartParams; import com.pledge.torgi.utils.StartParams;
import lombok.SneakyThrows; import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.net.ssl.*;
import java.security.cert.X509Certificate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List; import java.util.List;
@Slf4j @Slf4j
@Service @Service
@AllArgsConstructor
public class EmailService { public class EmailService {
private final FileService fileService; private final FileService fileService;
private final EmailsRepository emailsRepository; private final EmailsRepository emailsRepository;
@SneakyThrows
public EmailService(FileService fileService, EmailsRepository emailsRepository) {
this.emailsRepository = emailsRepository;
this.fileService = fileService;
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
// Ничего не проверяем
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
// Ничего не проверяем
}
}
};
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
}
public void processEmails(StartParams params) { public void processEmails(StartParams params) {
log.error("Start email processing"); log.info("Start email processing");
if (!params.getEnableEmailScan()) { if (!params.getEnableEmailScan()) {
log.error("Email processing disabled"); log.info("Email processing disabled");
return; return;
} }
List<Emails> alreadyProcessed = emailsRepository.findTop10ByOrderByIdDesc(); List<Emails> alreadyProcessed = emailsRepository.findTop10ByOrderByIdDesc();
List<EmailData> emailData = new ReceiveEmailService("imap.gmail.com", 993, params.getFrom(), params.getToken(), params.getSpecialEmail(), log) List<EmailData> emailData = new ReceiveEmailService("imap.gmail.com", 993, params.getFrom(), params.getToken(), params.getSpecialEmail(), log)
.downloadEmails(alreadyProcessed); .downloadEmails(alreadyProcessed);
int sendLetters = 0; int sendLetters = 0;
log.error("Extracted letters = {}", emailData.size()); log.info("Extracted letters = {}", emailData.size());
for (EmailData data : emailData) { for (EmailData data : emailData) {
if (alreadyProcessed(data.getEmailId())) { if (alreadyProcessed(data.getEmailId())) {
continue; continue;
@@ -72,7 +38,7 @@ public class EmailService {
saveProcessedEmail(data); saveProcessedEmail(data);
sendLetters++; sendLetters++;
} }
log.error("End email processing, send letters = {}", sendLetters); log.info("End email processing, send letters = {}", sendLetters);
} }
private boolean alreadyProcessed(String emailId) { private boolean alreadyProcessed(String emailId) {

View File

@@ -2,28 +2,81 @@ package com.pledge.torgi.service;
import com.pledge.torgi.controller.DownloadHeadlessController; import com.pledge.torgi.controller.DownloadHeadlessController;
import com.pledge.torgi.utils.StartParams; import com.pledge.torgi.utils.StartParams;
import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.net.ssl.*;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@Service @Service
@Slf4j
@EnableScheduling @EnableScheduling
@AllArgsConstructor
public class MainService { public class MainService {
private final StartParams params; private final StartParams params;
private final DownloadHeadlessController headlessController; private final DownloadHeadlessController headlessController;
private final EmailService emailService; private final EmailService emailService;
private static final String ISSUER_NAME = "CN=Russian Trusted Sub CA,O=The Ministry of Digital Development and Communications,C=RU";
@Scheduled(timeUnit = TimeUnit.SECONDS, fixedRate = 120) public MainService(StartParams params, DownloadHeadlessController headlessController, EmailService emailService) {
this.params = params;
this.headlessController = headlessController;
this.emailService = emailService;
initSSL();
}
private void initSSL() {
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
// Ничего не проверяем
}
public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {
if (certs.length != 1) {
throw new CertificateException();
}
X509Certificate cert = certs[0];
if (!cert.getIssuerX500Principal().getName().equals(ISSUER_NAME))
{
throw new CertificateException("Current issuer name = %s, expected = %s".formatted(cert.getIssuerX500Principal().getName(), ISSUER_NAME));
}
}
}
};
try {
SSLContext sc = SSLContext.getInstance("TLSv1.2");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
} catch (Exception ex) {
log.error("Error during ssl init", ex);
}
}
@Scheduled(timeUnit = TimeUnit.SECONDS, fixedRate = 120, initialDelay = 5)
public void getNewData() { public void getNewData() {
headlessController.process(); headlessController.process();
headlessController.richData(); headlessController.richData();
} }
@Scheduled(timeUnit = TimeUnit.SECONDS, fixedRate = 600) @Scheduled(timeUnit = TimeUnit.SECONDS, fixedRate = 600, initialDelay = 10)
public void checkEmail() { public void checkEmail() {
emailService.processEmails(params); emailService.processEmails(params);
} }

View File

@@ -1,17 +1,4 @@
pledge.params.from=changeit@gmail.com spring.application.name=torgi
pledge.params.token=changeit spring.config.import=configserver:http://192.168.2.22:10022
pledge.params.to=m.ryabyh@gmail.com,AAAtapina@sberbank.ru,Oreshkina.V.V@sberbank.ru,MEvRyabykh@sberbank.ru spring.cloud.config.fail-fast=true
pledge.params.days=1 spring.cloud.config.profile=dev
pledge.params.special-email=m.ryabyh+torgi@gmail.com
pledge.params.enable-email-scan=false
spring.datasource.url=jdbc:postgresql://localhost:5432/torgi
spring.datasource.username=torgi
spring.datasource.password=17maxim02
spring.datasource.driver-class-name=org.postgresql.Driver
spring.servlet.multipart.max-file-size=20MB
spring.servlet.multipart.max-request-size=20MB
server.tomcat.connection-timeout=300000
server.tomcat.keep-alive-timeout=300000
server.connection-timeout=300000
management.endpoints.web.exposure.include=health,metrics,prometheus
management.endpoint.health.show-details=always