Merge branch 'feature/SUPPORT-8458_file' into release/1.0.0
This commit is contained in:
commit
371cffabbd
15 changed files with 363 additions and 75 deletions
|
|
@ -244,6 +244,10 @@
|
|||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.amazonaws</groupId>
|
||||
<artifactId>aws-java-sdk-s3</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<finalName>${parent.artifactId}</finalName>
|
||||
|
|
|
|||
|
|
@ -34,7 +34,8 @@ public class ReplyingKafkaConfig {
|
|||
private String groupId;
|
||||
@Value("${ervu.kafka.reply.timeout:30}")
|
||||
private long replyTimeout;
|
||||
|
||||
@Value("${ervu.kafka.excerpt.reply.topic}")
|
||||
private String excerptReplyTopic;
|
||||
@Value("${ervu.kafka.security.protocol}")
|
||||
private String securityProtocol;
|
||||
@Value("${ervu.kafka.login.module:org.apache.kafka.common.security.scram.ScramLoginModule}")
|
||||
|
|
@ -85,6 +86,24 @@ public class ReplyingKafkaConfig {
|
|||
return factory;
|
||||
}
|
||||
|
||||
@Bean()
|
||||
@Qualifier("excerpt-container")
|
||||
public ConcurrentMessageListenerContainer<String, String> excerptReplyContainer(
|
||||
ConcurrentKafkaListenerContainerFactory<String, String> factory) {
|
||||
ConcurrentMessageListenerContainer<String, String> container = factory.createContainer(
|
||||
excerptReplyTopic);
|
||||
container.getContainerProperties().setGroupId(groupId);
|
||||
return container;
|
||||
}
|
||||
|
||||
@Bean()
|
||||
@Qualifier("excerpt-template")
|
||||
public ReplyingKafkaTemplate<String, String, String> excerptReplyingKafkaTemplate(
|
||||
@Qualifier("ervu") ProducerFactory<String, String> pf,
|
||||
@Qualifier("excerpt-container") ConcurrentMessageListenerContainer<String, String> container) {
|
||||
return initReplyingKafkaTemplate(pf, container);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Qualifier("org")
|
||||
public ConcurrentMessageListenerContainer<String, String> replyContainer(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,83 @@
|
|||
package ru.micord.ervu.kafka.controller;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.core.io.InputStreamResource;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import ru.micord.ervu.kafka.model.Data;
|
||||
import ru.micord.ervu.kafka.model.ErvuOrgResponse;
|
||||
import ru.micord.ervu.kafka.model.ExcerptResponse;
|
||||
import ru.micord.ervu.kafka.service.ReplyingKafkaService;
|
||||
import ru.micord.ervu.s3.S3Service;
|
||||
import ru.micord.ervu.security.webbpm.jwt.model.Token;
|
||||
import ru.micord.ervu.security.webbpm.jwt.service.JwtTokenService;
|
||||
|
||||
/**
|
||||
* @author Eduard Tihomirov
|
||||
*/
|
||||
@RestController
|
||||
public class ErvuKafkaController {
|
||||
|
||||
@Autowired
|
||||
@Qualifier("excerpt-service")
|
||||
private ReplyingKafkaService replyingKafkaService;
|
||||
|
||||
@Autowired
|
||||
private S3Service s3Service;
|
||||
|
||||
@Autowired
|
||||
private JwtTokenService jwtTokenService;
|
||||
|
||||
@Value("${ervu.kafka.excerpt.reply.topic}")
|
||||
private String requestReplyTopic;
|
||||
|
||||
@Value("${ervu.kafka.excerpt.request.topic}")
|
||||
private String requestTopic;
|
||||
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@RequestMapping(value = "/kafka/excerpt")
|
||||
public ResponseEntity<InputStreamResource> getExcerptFile(HttpServletRequest request) {
|
||||
try {
|
||||
String authToken = getAuthToken(request);
|
||||
Token token = jwtTokenService.getToken(authToken);
|
||||
String[] split = token.getUserAccountId().split(":");
|
||||
String prnOid = split[0];
|
||||
String ervuId = split[1];
|
||||
Data data = new Data();
|
||||
data.setOrgId_ERVU(ervuId);
|
||||
data.setPrnOid(prnOid);
|
||||
String kafkaResponse = replyingKafkaService.sendMessageAndGetReply(requestTopic, requestReplyTopic,
|
||||
objectMapper.writeValueAsString(data)
|
||||
);
|
||||
ExcerptResponse excerptResponse = objectMapper.readValue(kafkaResponse, ExcerptResponse.class);
|
||||
return s3Service.getFile(excerptResponse.getFileUrl());
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private String getAuthToken(HttpServletRequest request) {
|
||||
Cookie[] cookies = request.getCookies();
|
||||
if (cookies != null) {
|
||||
for (Cookie cookie : cookies) {
|
||||
if (cookie.getName().equals("auth_token")) {
|
||||
return cookie.getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
package ru.micord.ervu.kafka.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
/**
|
||||
* @author Eduard Tihomirov
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class ExcerptResponse implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String excerptId;
|
||||
|
||||
private String orgId;
|
||||
|
||||
private String fileUrl;
|
||||
|
||||
@JsonFormat(pattern = "dd.MM.yyyy HH:mm")
|
||||
private Date departureDateTime;
|
||||
|
||||
private String timeZone;
|
||||
|
||||
public String getExcerptId() {
|
||||
return excerptId;
|
||||
}
|
||||
|
||||
public void setExcerptId(String excerptId) {
|
||||
this.excerptId = excerptId;
|
||||
}
|
||||
|
||||
public String getOrgId() {
|
||||
return orgId;
|
||||
}
|
||||
|
||||
public void setOrgId(String orgId) {
|
||||
this.orgId = orgId;
|
||||
}
|
||||
|
||||
public Date getDepartureDateTime() {
|
||||
return departureDateTime;
|
||||
}
|
||||
|
||||
public void setDepartureDateTime(Date departureDateTime) {
|
||||
this.departureDateTime = departureDateTime;
|
||||
}
|
||||
|
||||
public String getTimeZone() {
|
||||
return timeZone;
|
||||
}
|
||||
|
||||
public void setTimeZone(String timeZone) {
|
||||
this.timeZone = timeZone;
|
||||
}
|
||||
|
||||
public String getFileUrl() {
|
||||
return fileUrl;
|
||||
}
|
||||
|
||||
public void setFileUrl(String fileUrl) {
|
||||
this.fileUrl = fileUrl;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package ru.micord.ervu.kafka.service.impl;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.kafka.requestreply.ReplyingKafkaTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @author Eduard Tihomirov
|
||||
*/
|
||||
@Service
|
||||
@Qualifier("excerpt-service")
|
||||
public class ExcerptReplyingKafkaServiceImpl extends BaseReplyingKafkaServiceImpl {
|
||||
|
||||
@Autowired
|
||||
@Qualifier("excerpt-template")
|
||||
private ReplyingKafkaTemplate<String, String, String> excerptReplyingKafkaTemplate;
|
||||
|
||||
@Override
|
||||
protected ReplyingKafkaTemplate<String, String, String> getReplyingKafkaTemplate() {
|
||||
return excerptReplyingKafkaTemplate;
|
||||
}
|
||||
}
|
||||
45
backend/src/main/java/ru/micord/ervu/s3/S3Connection.java
Normal file
45
backend/src/main/java/ru/micord/ervu/s3/S3Connection.java
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
package ru.micord.ervu.s3;
|
||||
|
||||
import com.amazonaws.auth.AWSCredentials;
|
||||
import com.amazonaws.auth.AWSStaticCredentialsProvider;
|
||||
import com.amazonaws.auth.BasicAWSCredentials;
|
||||
import com.amazonaws.client.builder.AwsClientBuilder;
|
||||
import com.amazonaws.regions.Region;
|
||||
import com.amazonaws.regions.Regions;
|
||||
import com.amazonaws.services.s3.AmazonS3;
|
||||
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @author Eduard Tihomirov
|
||||
*/
|
||||
@Configuration
|
||||
public class S3Connection {
|
||||
@Value("${s3.out.endpoint}")
|
||||
private String endpointOut;
|
||||
@Value("${s3.out.port:9000}")
|
||||
private int portOut;
|
||||
@Value("${s3.out.access_key}")
|
||||
private String accessKeyOut;
|
||||
@Value("${s3.out.secret_key}")
|
||||
private String secretKeyOut;
|
||||
|
||||
@Bean("outClient")
|
||||
public AmazonS3 getS3OutClient() {
|
||||
return getS3Client(endpointOut, portOut, accessKeyOut, secretKeyOut);
|
||||
}
|
||||
|
||||
private static AmazonS3 getS3Client(String endpoint, int port, String accessKey,
|
||||
String secretKey) {
|
||||
AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);
|
||||
String s3Endpoint = endpoint + ":" + port;
|
||||
String region = Region.getRegion(Regions.DEFAULT_REGION).toString();
|
||||
|
||||
return AmazonS3ClientBuilder.standard()
|
||||
.withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(s3Endpoint, region))
|
||||
.withCredentials(new AWSStaticCredentialsProvider(credentials))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
42
backend/src/main/java/ru/micord/ervu/s3/S3Service.java
Normal file
42
backend/src/main/java/ru/micord/ervu/s3/S3Service.java
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
package ru.micord.ervu.s3;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
|
||||
import com.amazonaws.AmazonServiceException;
|
||||
import com.amazonaws.services.s3.AmazonS3;
|
||||
import com.amazonaws.services.s3.AmazonS3URI;
|
||||
import com.amazonaws.services.s3.model.S3Object;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.io.InputStreamResource;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
/**
|
||||
* @author Eduard Tihomirov
|
||||
*/
|
||||
@Service
|
||||
public class S3Service {
|
||||
private final AmazonS3 outClient;
|
||||
|
||||
@Autowired
|
||||
public S3Service(AmazonS3 outClient) {
|
||||
this.outClient = outClient;
|
||||
}
|
||||
|
||||
public ResponseEntity<InputStreamResource> getFile(String fileUrl) {
|
||||
try {
|
||||
AmazonS3URI uri = new AmazonS3URI(fileUrl);
|
||||
S3Object s3Object = outClient.getObject(uri.getBucket(), uri.getKey());
|
||||
InputStreamResource resource = new InputStreamResource(s3Object.getObjectContent());
|
||||
return ResponseEntity.ok()
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + uri.getKey())
|
||||
.contentType(MediaType.APPLICATION_OCTET_STREAM)
|
||||
.body(resource);
|
||||
}
|
||||
catch (AmazonServiceException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -433,8 +433,6 @@ public class EsiaAuthService {
|
|||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private OrgInfo copyToOrgInfo(OrganizationModel organizationModel, EmployeeModel employeeModel, EmployeeModel chiefModel ) {
|
||||
|
|
|
|||
|
|
@ -40,3 +40,5 @@ ERVU_KAFKA_SECURITY_PROTOCOL=SASL_PLAINTEXT
|
|||
ERVU_KAFKA_SASL_MECHANISM=SCRAM-SHA-256
|
||||
ERVU_KAFKA_USERNAME=user1
|
||||
ERVU_KAFKA_PASSWORD=Blfi9d2OFG
|
||||
ERVU_KAFKA_EXCERPT_REPLY_TOPIC=ervu.lkrp.excerpt.response
|
||||
ERVU_KAFKA_EXCERPT_REQUEST_TOPIC=ervu.lkrp.excerpt.request
|
||||
|
|
|
|||
|
|
@ -89,6 +89,8 @@
|
|||
<property name="esnsi.okopf.url" value="https://esnsi.gosuslugi.ru/rest/ext/v1/classifiers/11465/file?extension=JSON&encoding=UTF_8"/>
|
||||
<property name="ervu.kafka.journal.request.topic" value="ervu.organization.journal.request"/>
|
||||
<property name="ervu.kafka.journal.reply.topic" value="ervu.organization.journal.response"/>
|
||||
<property name="ervu.kafka.excerpt.reply.topic" value="ervu.lkrp.excerpt.response"/>
|
||||
<property name="ervu.kafka.excerpt.request.topic" value="ervu.lkrp.excerpt.request"/>
|
||||
</system-properties>
|
||||
<management>
|
||||
<audit-log>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
<div>
|
||||
<button type="button"
|
||||
[disabled]="!isEnabled()"
|
||||
class="btn btn-secondary"
|
||||
[ngbTooltip]="tooltip | emptyIfNull"
|
||||
(click)="onClick()"
|
||||
(focus)="onFocus()"
|
||||
(blur)="onBlur()">{{caption}}</button>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef} from "@angular/core";
|
||||
import {AbstractButton, NotNull} from "@webbpm/base-package";
|
||||
import {HttpClient} from "@angular/common/http";
|
||||
|
||||
/**
|
||||
* @author: Eduard Tihomirov
|
||||
*/
|
||||
@Component({
|
||||
selector: 'ervu-download-file-button',
|
||||
templateUrl: "./../../../../../src/resources/template/ervu/component/button/Button.html",
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class ErvuDownloadFileButton extends AbstractButton {
|
||||
private httpClient: HttpClient;
|
||||
|
||||
@NotNull()
|
||||
public fileName: string;
|
||||
|
||||
constructor(el: ElementRef, cd: ChangeDetectorRef) {
|
||||
super(el, cd);
|
||||
}
|
||||
|
||||
initialize() {
|
||||
super.initialize();
|
||||
this.httpClient = this.injector.get(HttpClient);
|
||||
}
|
||||
|
||||
public doClickActions(): Promise<any> {
|
||||
return this.httpClient.get('kafka/excerpt', {
|
||||
responseType: 'blob'
|
||||
}).toPromise().then((response) => {
|
||||
const url = window.URL.createObjectURL(response);
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = this.fileName;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
window.URL.revokeObjectURL(url);
|
||||
a.remove();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -24,6 +24,7 @@ import {AppProgressIndicationService} from "./service/app-progress-indication.se
|
|||
import {FileUploadModule} from "ng2-file-upload";
|
||||
import {ErvuFileUpload} from "../../ervu/component/fileupload/ErvuFileUpload";
|
||||
import {InMemoryStaticGrid} from "../../ervu/component/grid/InMemoryStaticGrid";
|
||||
import {ErvuDownloadFileButton} from "../../ervu/component/button/ErvuDownloadFileButton";
|
||||
|
||||
registerLocaleData(localeRu);
|
||||
export const DIRECTIVES = [
|
||||
|
|
@ -34,6 +35,7 @@ export const DIRECTIVES = [
|
|||
forwardRef(() => AccessDeniedComponent),
|
||||
forwardRef(() => AppProgressIndicationComponent),
|
||||
forwardRef(() => ErvuFileUpload),
|
||||
forwardRef(() => ErvuDownloadFileButton),
|
||||
forwardRef(() => InMemoryStaticGrid)
|
||||
];
|
||||
|
||||
|
|
|
|||
5
pom.xml
5
pom.xml
|
|
@ -367,6 +367,11 @@
|
|||
<artifactId>log4j-web</artifactId>
|
||||
<version>2.23.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.amazonaws</groupId>
|
||||
<artifactId>aws-java-sdk-s3</artifactId>
|
||||
<version>1.12.759</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
<repositories>
|
||||
|
|
|
|||
|
|
@ -638,76 +638,6 @@
|
|||
</entry>
|
||||
</properties>
|
||||
</scripts>
|
||||
<scripts id="1996166f-7922-4f28-a571-9646d956ef37">
|
||||
<properties>
|
||||
<entry>
|
||||
<key>enableCellTextSelection</key>
|
||||
<value>
|
||||
<simple>null</simple>
|
||||
</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>fetchSize</key>
|
||||
<value>
|
||||
<simple>20.0</simple>
|
||||
</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>headerHeight</key>
|
||||
<value>
|
||||
<simple>40.0</simple>
|
||||
</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>loadingOverlayMessage</key>
|
||||
<value>
|
||||
<simple>"Загрузка данных, пожалуйста, подождите."</simple>
|
||||
</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>loadingOverlayType</key>
|
||||
<value>
|
||||
<simple>"PROGRESS_BAR"</simple>
|
||||
</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>noRowsOverlayMessage</key>
|
||||
<value>
|
||||
<simple>"Данные отсутствуют"</simple>
|
||||
</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>rowClickSelectionType</key>
|
||||
<value>
|
||||
<simple>"SINGLE_SELECT_CLICK"</simple>
|
||||
</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>rowHeight</key>
|
||||
<value>
|
||||
<simple>40.0</simple>
|
||||
</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>rowModelType</key>
|
||||
<value>
|
||||
<simple>"CLIENT_SIDE"</simple>
|
||||
</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>showRowNumber</key>
|
||||
<value>
|
||||
<simple>null</simple>
|
||||
</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>theme</key>
|
||||
<value>
|
||||
<simple>null</simple>
|
||||
</value>
|
||||
</entry>
|
||||
</properties>
|
||||
</scripts>
|
||||
<scripts id="be8fe0e1-4909-4224-8664-be55168595c6"/>
|
||||
<scripts id="f0a59cd9-acf8-4b1d-89fa-a5d618fc4664">
|
||||
<classRef type="JAVA">
|
||||
|
|
@ -1347,6 +1277,16 @@
|
|||
<container>false</container>
|
||||
<childrenReordered>false</childrenReordered>
|
||||
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f">
|
||||
<removed>true</removed>
|
||||
<expanded>false</expanded>
|
||||
</scripts>
|
||||
<scripts id="38036714-7fff-4404-98d3-b0f5cc846368">
|
||||
<classRef type="TS">
|
||||
<className>ErvuDownloadFileButton</className>
|
||||
<packageName>ervu.component.button</packageName>
|
||||
</classRef>
|
||||
<enabled>true</enabled>
|
||||
<expanded>true</expanded>
|
||||
<properties>
|
||||
<entry>
|
||||
<key>caption</key>
|
||||
|
|
@ -1355,9 +1295,15 @@
|
|||
</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>tooltip</key>
|
||||
<key>fileName</key>
|
||||
<value>
|
||||
<simple>null</simple>
|
||||
<simple>"Выписка"</simple>
|
||||
</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>visible</key>
|
||||
<value>
|
||||
<simple>true</simple>
|
||||
</value>
|
||||
</entry>
|
||||
</properties>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue