mirror of
https://github.com/dadosfera/maestro.git
synced 2026-10-09 06:59:08 +00:00
Merge branch 'feat/catalog-external-datasets-using-api-call' of github.com:dadosfera/maestro into feat/catalog-external-datasets-using-api-call
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
import { IdResponse } from '@dadosfera/protospack-v2/dist/lib/Duc/interfaces/messages';
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
@@ -18,7 +17,6 @@ import {
|
||||
Authenticated,
|
||||
RequireAllPermissions,
|
||||
} from 'src/decorators/authentication.decorator';
|
||||
import { ApiInternalOnlyEndpoint } from 'src/decorators/swagger.decorator';
|
||||
import { GrpcToHttpExceptionFilter } from 'src/error/grpc-to-http-exception.filter';
|
||||
import { CustomersService } from './customers.service';
|
||||
import { CustomerLinkRequest, CustomerLinksResponse } from './dtos/customers';
|
||||
@@ -28,7 +26,6 @@ import { PackTheMetadata } from 'src/utils/ PackTheMetadata';
|
||||
|
||||
@ApiTags('Customers')
|
||||
@Controller('customers')
|
||||
@Authenticated()
|
||||
@UseFilters(GrpcToHttpExceptionFilter)
|
||||
export class CustomersController {
|
||||
logger: DadosferaLogger;
|
||||
@@ -42,6 +39,7 @@ export class CustomersController {
|
||||
}
|
||||
|
||||
@Get(':id/links')
|
||||
@Authenticated()
|
||||
@ApiOkResponse({ type: CustomerLinksResponse })
|
||||
async getCustomerLinks(@Param('id') id: string) {
|
||||
this.logger.info('getCustomerLinks', { id });
|
||||
@@ -50,6 +48,7 @@ export class CustomersController {
|
||||
}
|
||||
|
||||
@Put(':id/links')
|
||||
@Authenticated()
|
||||
@RequireAllPermissions(PERMISSIONS_GROUPS.USERS.permissions.ADMIN)
|
||||
@ApiOkResponse()
|
||||
@HttpCode(HttpStatus.OK)
|
||||
@@ -63,6 +62,7 @@ export class CustomersController {
|
||||
}
|
||||
|
||||
@Get('token')
|
||||
@Authenticated()
|
||||
@RequireAllPermissions(PERMISSIONS_GROUPS.AUTH.permissions.GENERATE_TOKEN)
|
||||
@ApiProduces('text/plain')
|
||||
async getCustomerToken(
|
||||
@@ -79,6 +79,7 @@ export class CustomersController {
|
||||
}
|
||||
|
||||
@Get('monitoring-dashboard')
|
||||
@Authenticated()
|
||||
@RequireAllPermissions(
|
||||
PERMISSIONS_GROUPS.CUSTOMER.permissions.MONITORING_DASHBOARD,
|
||||
)
|
||||
|
||||
@@ -28,19 +28,24 @@ import {
|
||||
} from '@dadosfera/protospack-v2/dist/lib/PipelineV2';
|
||||
import { Metadata } from '@grpc/grpc-js';
|
||||
import { PipelinesClientConfiguration } from '../pipelinesV2/pipelines-client';
|
||||
import DadosferaLogger from '@dadosfera/dadosfera-logs';
|
||||
|
||||
// This function will accept any string, which may result in a bug.
|
||||
@Injectable()
|
||||
export class CustomersService implements OnModuleInit {
|
||||
private customerService: CustomersProtoService;
|
||||
|
||||
private logger: DadosferaLogger;
|
||||
private pipelineReadService: ReadService.PipelineV2ReadService;
|
||||
|
||||
constructor(
|
||||
@Inject(DucClient.name) private readonly grpcClient: ClientGrpc,
|
||||
@Inject(PipelinesClientConfiguration.name)
|
||||
private readonly pipelinesGrpcClient: ClientGrpc,
|
||||
) {}
|
||||
@Inject(DadosferaLogger)
|
||||
dadosferaLogger: DadosferaLogger,
|
||||
) {
|
||||
this.logger = dadosferaLogger.logger;
|
||||
}
|
||||
|
||||
onModuleInit() {
|
||||
this.customerService = this.grpcClient.getService<CustomersProtoService>(
|
||||
|
||||
@@ -20,3 +20,4 @@ export class CustomerLinksResponse {
|
||||
@ApiProperty({ type: [CustomerLink] })
|
||||
links: CustomerLink[];
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,8 @@ export class DucClient {
|
||||
objects: true,
|
||||
arrays: true,
|
||||
},
|
||||
maxSendMessageLength: 15 * 1024 * 1024, // 15 MB por mensagem
|
||||
maxReceiveMessageLength: 15 * 1024 * 1024,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
import { ApiProperty } from "@nestjs/swagger";
|
||||
|
||||
export class CreateUserOpenDataDTO {
|
||||
@ApiProperty()
|
||||
firstName: string;
|
||||
@ApiProperty()
|
||||
lastName: string;
|
||||
@ApiProperty()
|
||||
email: string;
|
||||
@ApiProperty()
|
||||
organization: string;
|
||||
@ApiProperty()
|
||||
enquiryType: string;
|
||||
}
|
||||
|
||||
type FormField = {
|
||||
id: string;
|
||||
type: string;
|
||||
title: string;
|
||||
value: string;
|
||||
raw_value: string;
|
||||
required: string;
|
||||
};
|
||||
|
||||
type MetaData = {
|
||||
title: string;
|
||||
value: string;
|
||||
};
|
||||
|
||||
export type WordpressForm = {
|
||||
form: {
|
||||
id: string;
|
||||
name: string;
|
||||
};
|
||||
fields: {
|
||||
[key: string]: FormField;
|
||||
};
|
||||
meta: {
|
||||
date: MetaData;
|
||||
time: MetaData;
|
||||
page_url: MetaData;
|
||||
user_agent: MetaData;
|
||||
remote_ip: MetaData;
|
||||
credit: MetaData;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
import DadosferaLogger from '@dadosfera/dadosfera-logs';
|
||||
import { Body, Controller, ForbiddenException, Header, HttpCode, Inject, Param, Post, Query, Req, UseFilters, UseGuards, UseInterceptors } from '@nestjs/common';
|
||||
import { ApiCreatedResponse, ApiHeaders, ApiOkResponse, ApiTags } from '@nestjs/swagger';
|
||||
import { ApiInternalOnlyController } from 'src/decorators/swagger.decorator';
|
||||
import { GrpcToHttpExceptionFilter } from 'src/error/grpc-to-http-exception.filter';
|
||||
import { LanguageEnum } from 'src/utils/languages.enum';
|
||||
import { UsersService } from '../users/users.service';
|
||||
import { Language } from 'src/decorators/language.decorator';
|
||||
import { OpenDataService } from './open-data.service';
|
||||
import { CreateUserOpenDataDTO, WordpressForm } from './dto/wordpres-form';
|
||||
import { Metadata } from '@grpc/grpc-js';
|
||||
import { PackTheMetadata } from 'src/utils/ PackTheMetadata';
|
||||
import { request } from 'http';
|
||||
import { Request } from 'express';
|
||||
|
||||
@Controller('open-data')
|
||||
@ApiInternalOnlyController()
|
||||
@ApiTags('OpenData')
|
||||
@ApiHeaders([{ name: 'dadosfera-lang', enum: LanguageEnum, required: false }])
|
||||
@UseFilters(GrpcToHttpExceptionFilter)
|
||||
export class OpenDataController {
|
||||
logger: DadosferaLogger;
|
||||
|
||||
constructor(
|
||||
@Inject(DadosferaLogger)
|
||||
dadosferaLogger: DadosferaLogger,
|
||||
private openDataService: OpenDataService,
|
||||
) {
|
||||
this.logger = dadosferaLogger.logger;
|
||||
}
|
||||
|
||||
@Post("/sharing-ocean-data")
|
||||
@HttpCode(200)
|
||||
@Header('content-type', 'application/json')
|
||||
@ApiOkResponse()
|
||||
async createUser(
|
||||
@Body()
|
||||
body: WordpressForm,
|
||||
@Query('language')
|
||||
language: string,
|
||||
@Req()
|
||||
request: Request,
|
||||
) {
|
||||
this.logger.info('createUser for open data');
|
||||
|
||||
this.logger.info('user-agent', request.headers['user-agent']);
|
||||
|
||||
const OPENDATA_CUSTOMER_ID = process.env.OPEN_CUSTOMER_ID;
|
||||
const OPENDATA_GROUP_ID = process.env.OPEN_GROUP_ID;
|
||||
const roles = [process.env.OPEN_GROUP_ID];
|
||||
const metadata = PackTheMetadata({
|
||||
language: language || 'en-us'
|
||||
});
|
||||
|
||||
const data = {}
|
||||
|
||||
try {
|
||||
Object.keys(body.fields)
|
||||
.filter(key => body.fields[key].required === "1")
|
||||
.forEach(key => {
|
||||
const field = body.fields[key]
|
||||
data[field.id] = field.value
|
||||
});
|
||||
} catch (e) {
|
||||
this.logger.error('user data ' + e.message);
|
||||
}
|
||||
|
||||
const user: CreateUserOpenDataDTO = {
|
||||
email: data["email"],
|
||||
enquiryType: data["enquiry_type"],
|
||||
firstName: data["first_name"],
|
||||
lastName: data["last_name"],
|
||||
organization: data["organization"]
|
||||
}
|
||||
this.logger.info(`user request to group ${OPENDATA_CUSTOMER_ID} with role ${OPENDATA_GROUP_ID}`);
|
||||
|
||||
try {
|
||||
const id = await this.openDataService.createUser(OPENDATA_CUSTOMER_ID, user, roles, metadata);
|
||||
this.logger.info('user created with id: '+ id);
|
||||
return {
|
||||
success: true,
|
||||
status: 'success',
|
||||
message: 'user created with succesfull'
|
||||
}
|
||||
} catch (e) {
|
||||
this.logger.error('failed with exception: ' + e.message);
|
||||
return {
|
||||
success: false,
|
||||
status: 'failed',
|
||||
message: e.message
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { OpenDataController } from './open-data.controller';
|
||||
import { UsersService } from '../users/users.service';
|
||||
import { ClientsModule } from '@nestjs/microservices'
|
||||
import { DucClient } from '../duc/client.config';
|
||||
import DadosferaLogger from '@dadosfera/dadosfera-logs';
|
||||
import { RolesModule } from '../roles/roles.module';
|
||||
import { PermissionsModule } from '../permissions/permissions.module';
|
||||
import { OpenDataService } from './open-data.service';
|
||||
|
||||
const client = new DucClient();
|
||||
|
||||
@Module({
|
||||
controllers: [OpenDataController],
|
||||
imports: [
|
||||
ClientsModule.register([client.providerOptions]),
|
||||
RolesModule,
|
||||
// PermissionsModule,
|
||||
],
|
||||
providers: [DadosferaLogger, UsersService, OpenDataService]
|
||||
})
|
||||
export class OpenDataModule {}
|
||||
@@ -0,0 +1,51 @@
|
||||
import { Inject, Injectable, OnModuleInit } from '@nestjs/common';
|
||||
import { lastValueFrom } from 'rxjs';
|
||||
import { CreateUserOpenDataDTO } from './dto/wordpres-form';
|
||||
import DadosferaLogger from '@dadosfera/dadosfera-logs';
|
||||
import { UsersProtoService } from '@dadosfera/protospack-v2/dist/lib/Duc/interfaces/write-service';
|
||||
import { DucClient } from '../duc/client.config';
|
||||
import { ClientGrpc } from '@nestjs/microservices';
|
||||
import { ProtoServices } from '@dadosfera/protospack-v2/dist/lib/Duc';
|
||||
import { Metadata } from '@grpc/grpc-js';
|
||||
|
||||
@Injectable()
|
||||
export class OpenDataService implements OnModuleInit {
|
||||
logger: DadosferaLogger;
|
||||
|
||||
private usersClientService: UsersProtoService;
|
||||
constructor(
|
||||
@Inject(DadosferaLogger)
|
||||
private dadosferaLogger: DadosferaLogger,
|
||||
@Inject(DucClient.name)
|
||||
private readonly grpcClient: ClientGrpc,
|
||||
) {
|
||||
this.logger = dadosferaLogger.logger;
|
||||
}
|
||||
|
||||
onModuleInit() {
|
||||
this.usersClientService = this.grpcClient.getService(
|
||||
ProtoServices.UsersProtoService,
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
async createUser(customerId: string, data: CreateUserOpenDataDTO, roleIds: string[], metadata: Metadata) {
|
||||
const body = {
|
||||
email: data.email,
|
||||
name: data.firstName + " " + data.lastName,
|
||||
department: data.organization,
|
||||
jobTitle: data.enquiryType,
|
||||
customerId: customerId,
|
||||
roleIds: roleIds
|
||||
}
|
||||
|
||||
try {
|
||||
const { user } = await lastValueFrom(
|
||||
this.usersClientService.SimpleUserCreate(body, metadata),
|
||||
);
|
||||
return user.id;
|
||||
} catch(err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -328,7 +328,7 @@ export class PipelinesService implements OnModuleInit {
|
||||
const res = await lastValueFrom(
|
||||
this.pipelineReadService.PipelineV2GetDashboardUrl(
|
||||
{
|
||||
dashboard_id: '83',
|
||||
dashboard_id: '95',
|
||||
exp: '15m',
|
||||
metabase_customer_name: 'dadosferatech',
|
||||
},
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
import { Link, Theme } from '@dadosfera/protospack-v2/dist/lib/Duc/interfaces/entities';
|
||||
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
||||
|
||||
export class CustomerLink implements Link {
|
||||
@ApiProperty()
|
||||
href: string;
|
||||
@ApiProperty()
|
||||
name: string;
|
||||
@ApiProperty()
|
||||
description: string;
|
||||
@ApiPropertyOptional()
|
||||
iconSrc: string;
|
||||
}
|
||||
export class CustomerLinkRequest {
|
||||
@ApiProperty({ type: [CustomerLink] })
|
||||
links: CustomerLink[];
|
||||
}
|
||||
|
||||
export class CustomerLinksResponse {
|
||||
@ApiProperty({ type: [CustomerLink] })
|
||||
links: CustomerLink[];
|
||||
}
|
||||
|
||||
export class CustomerTheme implements Theme {
|
||||
@ApiProperty()
|
||||
backgroundColor: string;
|
||||
@ApiProperty()
|
||||
textColor: string;
|
||||
@ApiProperty()
|
||||
logo: string;
|
||||
@ApiProperty()
|
||||
logoLogin: string;
|
||||
}
|
||||
|
||||
export class CustomerThemeResponse {
|
||||
@ApiProperty()
|
||||
theme: CustomerTheme;
|
||||
}
|
||||
|
||||
export class CustomerThemeRequest {
|
||||
@ApiProperty()
|
||||
displayName: string;
|
||||
@ApiProperty()
|
||||
backgroundColor: string;
|
||||
@ApiProperty()
|
||||
textColor: string;
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
import {
|
||||
Body,
|
||||
Controller,
|
||||
Get,
|
||||
HttpException,
|
||||
HttpStatus,
|
||||
Inject,
|
||||
Param,
|
||||
Post,
|
||||
Put,
|
||||
Query,
|
||||
UploadedFiles,
|
||||
UseFilters,
|
||||
UseInterceptors,
|
||||
HttpCode
|
||||
} from '@nestjs/common';
|
||||
import { ApiOkResponse, ApiTags } from '@nestjs/swagger';
|
||||
import { PERMISSIONS_GROUPS } from 'src/authentication/permissions.enum';
|
||||
import {
|
||||
Authenticated,
|
||||
RequireAllPermissions,
|
||||
} from 'src/decorators/authentication.decorator';
|
||||
import { GrpcToHttpExceptionFilter } from 'src/error/grpc-to-http-exception.filter';
|
||||
import { CustomerThemeRequest, CustomerThemeResponse } from './dtos/customers';
|
||||
|
||||
import ErrorCodes from 'src/utils/errorCodes';
|
||||
import { AnyFilesInterceptor } from '@nestjs/platform-express';
|
||||
import { ThemeService } from './theme.service';
|
||||
|
||||
@ApiTags('Theme')
|
||||
@Controller('customers')
|
||||
@UseFilters(GrpcToHttpExceptionFilter)
|
||||
export class ThemeController {
|
||||
logger: DadosferaLogger;
|
||||
|
||||
constructor(
|
||||
@Inject(DadosferaLogger)
|
||||
dadosferaLogger: DadosferaLogger,
|
||||
private themeService: ThemeService,
|
||||
) {
|
||||
this.logger = dadosferaLogger.logger;
|
||||
}
|
||||
|
||||
|
||||
@Post('/:id/theme')
|
||||
@Authenticated()
|
||||
@RequireAllPermissions(PERMISSIONS_GROUPS.USERS.permissions.ADMIN)
|
||||
@ApiOkResponse({ type: CustomerThemeResponse })
|
||||
@UseInterceptors(AnyFilesInterceptor())
|
||||
@HttpCode(HttpStatus.OK)
|
||||
async saveCustomertheme(
|
||||
@Param('id') id: string,
|
||||
@Body() data: CustomerThemeRequest,
|
||||
@UploadedFiles() files: Array<Express.Multer.File>
|
||||
) {
|
||||
|
||||
this.logger.info('saveCustomertheme' + JSON.stringify({
|
||||
id,
|
||||
}));
|
||||
|
||||
const logo = files.find(file => file.fieldname === 'logo');
|
||||
const logoLogin = files.find(file => file.fieldname === 'logoLogin');
|
||||
|
||||
this.validFileSize(logo);
|
||||
this.validFileSize(logoLogin);
|
||||
this.validMimeType(logo);
|
||||
this.validMimeType(logoLogin);
|
||||
|
||||
try {
|
||||
const theme = await this.themeService.createThemeByCustomer(id, {
|
||||
...data,
|
||||
logo,
|
||||
logoLogin
|
||||
});
|
||||
this.logger.info('saveCustomertheme' + JSON.stringify(theme));
|
||||
return theme;
|
||||
} catch (err) {
|
||||
if (err.details === ErrorCodes.CUSTOMER.NOT_FOUND) {
|
||||
this.logger.error('Error - saveCustomertheme - Expect CUSTOMER.NOT_FOUND');
|
||||
throw new HttpException(err.details, HttpStatus.NOT_FOUND);
|
||||
} else {
|
||||
this.logger.error('Error - saveCustomertheme Unknown Error:' + err?.message);
|
||||
return { theme: null };
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private validFileSize(file: Express.Multer.File) {
|
||||
const maxFileSize = 10 * 1024 * 1024; // 10MB
|
||||
|
||||
if (file && file.size > maxFileSize) {
|
||||
throw new HttpException(`O Arquivo ${file.filename} possui mais de 10MB`, HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
|
||||
private validMimeType(file: Express.Multer.File) {
|
||||
const mimeTypesValid = ['image/jpeg', 'image/jpg', 'image/png'];
|
||||
|
||||
if (file && !mimeTypesValid.includes(file.mimetype)) {
|
||||
throw new HttpException(`O Arquivo ${file.fieldname} deve ser jpeg, jpg, ou png`, HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
|
||||
@Get('/:id/theme')
|
||||
@ApiOkResponse({ type: CustomerThemeResponse })
|
||||
async getCustomerTheme(@Param('id') id: string) {
|
||||
this.logger.info('getCustomerTheme with id' + id);
|
||||
|
||||
try {
|
||||
const data = await this.themeService.getThemeByCustomer(id);
|
||||
this.logger.info('Success - getCustomerTheme'+ JSON.stringify(data));
|
||||
if (data?.theme) return data;
|
||||
|
||||
return { theme: null };
|
||||
}catch (err) {
|
||||
if (err.details === ErrorCodes.CUSTOMER.NOT_FOUND) {
|
||||
this.logger.error('Error - getCustomerTheme - Expect CUSTOMER.NOT_FOUND');
|
||||
throw new HttpException(err.details, HttpStatus.NOT_FOUND);
|
||||
} else {
|
||||
this.logger.error('Error - getCustomerTheme Unknown Error:' + err?.message);
|
||||
return { theme: null };
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { DadosferaLogger } from '@dadosfera/dadosfera-logs';
|
||||
import { ClientsModule } from '@nestjs/microservices';
|
||||
import { ThemeController } from './theme.controller';
|
||||
import { ThemeService } from './theme.service';
|
||||
import { DucClient } from '../duc/client.config';
|
||||
|
||||
const ducClient = new DucClient();
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
ClientsModule.register([
|
||||
ducClient.providerOptions,
|
||||
]),
|
||||
],
|
||||
controllers: [ThemeController],
|
||||
providers: [ThemeService, DadosferaLogger],
|
||||
exports: [ThemeService],
|
||||
})
|
||||
export class ThemeModule {}
|
||||
@@ -0,0 +1,158 @@
|
||||
import {
|
||||
OnModuleInit,
|
||||
Inject,
|
||||
Injectable,
|
||||
HttpException,
|
||||
HttpStatus,
|
||||
InternalServerErrorException,
|
||||
} from '@nestjs/common';
|
||||
|
||||
import { firstValueFrom, lastValueFrom, ReplaySubject } from 'rxjs';
|
||||
import { Link } from '@dadosfera/protospack-v2/dist/lib/Duc/interfaces/entities';
|
||||
import { DucClient } from '../duc/client.config';
|
||||
import { ClientGrpc } from '@nestjs/microservices';
|
||||
import { ProtoServices } from '@dadosfera/protospack-v2/dist/lib/Duc';
|
||||
import { CustomerUpdateRequest } from '@dadosfera/protospack-v2/dist/lib/Duc/interfaces/messages';
|
||||
import { ThemeProtoService } from '@dadosfera/protospack-v2/dist/lib/Duc/interfaces/write-service';
|
||||
import { ThemeRequest } from '@dadosfera/protospack-v2/dist/lib/Duc/interfaces/messages';
|
||||
import { CustomerThemeRequest, CustomerThemeResponse } from './dtos/customers';
|
||||
import DadosferaLogger from '@dadosfera/dadosfera-logs';
|
||||
import { resolve } from 'path';
|
||||
import { Readable } from 'stream';
|
||||
|
||||
type Files = {
|
||||
logo: Express.Multer.File,
|
||||
logoLogin: Express.Multer.File,
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class ThemeService implements OnModuleInit {
|
||||
private themeService: ThemeProtoService;
|
||||
private logger: DadosferaLogger;
|
||||
|
||||
constructor(
|
||||
@Inject(DucClient.name) private readonly grpcClient: ClientGrpc,
|
||||
@Inject(DadosferaLogger)
|
||||
dadosferaLogger: DadosferaLogger,
|
||||
) {
|
||||
this.logger = dadosferaLogger.logger;
|
||||
}
|
||||
|
||||
onModuleInit() {
|
||||
this.themeService = this.grpcClient.getService<ThemeProtoService>(
|
||||
ProtoServices.ThemeProtoService,
|
||||
);
|
||||
}
|
||||
|
||||
async createThemeByCustomer(id: string, theme: CustomerThemeRequest & Files) {
|
||||
if (!id) {
|
||||
this.logger.error('Error - saveCustomertheme - not found id:' + id);
|
||||
throw new HttpException(null, HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
const customerThemeRequest$ = new ReplaySubject<ThemeRequest>();
|
||||
|
||||
customerThemeRequest$.next({
|
||||
customerId: id,
|
||||
displayName: theme.displayName,
|
||||
backgroundColor: theme.backgroundColor,
|
||||
textColor: theme.textColor,
|
||||
isMetadata: true,
|
||||
filename: '',
|
||||
chunk: Buffer.alloc(0)
|
||||
})
|
||||
|
||||
if(theme.logo) {
|
||||
await this.sendFile(theme.logo, customerThemeRequest$);
|
||||
}
|
||||
|
||||
if(theme.logoLogin) {
|
||||
await this.sendFile(theme.logoLogin, customerThemeRequest$);
|
||||
}
|
||||
customerThemeRequest$.complete();
|
||||
|
||||
const stream = this.themeService.CustomerCreateTheme(customerThemeRequest$);
|
||||
|
||||
return lastValueFrom(stream);
|
||||
}
|
||||
|
||||
async getThemeByCustomer(id: string): Promise<CustomerThemeResponse> {
|
||||
if (!id) {
|
||||
this.logger.error('Error - getCustomerTheme - not found id:' + id);
|
||||
throw new HttpException(null, HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
const { theme } = await firstValueFrom(
|
||||
this.themeService.CustomerGetTheme({
|
||||
id
|
||||
}),
|
||||
);
|
||||
|
||||
return {
|
||||
theme
|
||||
}
|
||||
}
|
||||
|
||||
private async sendFile(file: Express.Multer.File, stream$: ReplaySubject<ThemeRequest>) {
|
||||
const chunkSize = 4 * 1024 * 1024;
|
||||
const bufferStream = new CustomBufferStream(file.buffer, chunkSize);
|
||||
const parseMimitypeForExtension = {
|
||||
'image/jpeg': '.jpeg',
|
||||
'image/jpg': '.jpg',
|
||||
'image/png': '.png',
|
||||
'image/svg+xml': '.svg',
|
||||
}
|
||||
|
||||
const extension = parseMimitypeForExtension[file.mimetype];
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
bufferStream.on('data', (chunk) => {
|
||||
const filename = file.fieldname.concat(extension);
|
||||
stream$.next({
|
||||
customerId: '',
|
||||
displayName: '',
|
||||
backgroundColor: '',
|
||||
textColor: '',
|
||||
isMetadata: false,
|
||||
filename: filename,
|
||||
chunk: chunk
|
||||
});
|
||||
});
|
||||
|
||||
bufferStream.on('end', () => {
|
||||
resolve(file.filename)
|
||||
});
|
||||
|
||||
bufferStream.on('error', (err) => {
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class CustomBufferStream extends Readable {
|
||||
buffer: Buffer;
|
||||
offset: number;
|
||||
chunkSize: number;
|
||||
|
||||
constructor(buffer: Buffer, chunkSize: number) {
|
||||
super({ highWaterMark: chunkSize }); // Configura o tamanho do chunk
|
||||
this.buffer = buffer;
|
||||
this.offset = 0;
|
||||
this.chunkSize = chunkSize;
|
||||
}
|
||||
|
||||
_read() {
|
||||
if (this.offset < this.buffer.length) {
|
||||
const end = Math.min(this.offset + this.chunkSize, this.buffer.length);
|
||||
|
||||
const copiedBuf = Uint8Array.prototype.slice.call(this.buffer);
|
||||
const chunk = copiedBuf.slice(this.offset, end);
|
||||
this.offset = end;
|
||||
this.push(chunk);
|
||||
} else {
|
||||
this.push(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user