chore: add files
commit
aad59e55b0
|
@ -0,0 +1,4 @@
|
|||
HITPHONE_DESKTOP_SERVER_ORIGINS="http://172.31.187.195:4000"
|
||||
API_KEY="ASDASDASDASD"
|
||||
ENCRYPTION_KEY="abc123"
|
||||
ENVIRONMENT="DEV"
|
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"env": {
|
||||
"node": true,
|
||||
"jest": true
|
||||
},
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"project": "tsconfig.json",
|
||||
"sourceType": "module"
|
||||
},
|
||||
"plugins": ["@typescript-eslint"],
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"standard-with-typescript"
|
||||
],
|
||||
"rules": {
|
||||
"@typescript-eslint/prefer-nullish-coalescing": "off",
|
||||
"@typescript-eslint/strict-boolean-expressions": "off",
|
||||
"@typescript-eslint/explicit-function-return-type": "off",
|
||||
"@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }],
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"semi": ["error", "never"],
|
||||
"comma-dangle": ["error", "never"]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
# compiled output
|
||||
/dist
|
||||
/node_modules
|
||||
/build
|
||||
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
pnpm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
|
||||
# Tests
|
||||
/coverage
|
||||
/.nyc_output
|
||||
|
||||
# IDEs and editors
|
||||
/.idea
|
||||
.project
|
||||
.classpath
|
||||
.c9/
|
||||
*.launch
|
||||
.settings/
|
||||
*.sublime-workspace
|
||||
|
||||
# IDE - VSCode
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
|
||||
# dotenv environment variable files
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# temp directory
|
||||
.temp
|
||||
.tmp
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
cert-hitphone.key
|
||||
cert-hitphone.pem
|
||||
localhost-key.pem
|
||||
localhost.pem
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"singleQuote": true,
|
||||
"trailingComma": "all"
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
# Variáveis de ambiente necessárias
|
||||
|
||||
- `HITPHONE_DESKTOP_SERVER_ORIGINS`: Campo do cors utilizado pelo servidor electron criado no desktop do cliente Hitphone
|
||||
- `API_KEY`: Chave de API utilizada pelo client.
|
||||
|
||||
# Arquivos necessários
|
||||
|
||||
- Arquivo `cert-hitphone.key` na raiz do projeto: Chave privada do certificado SSL
|
||||
- Arquivo `cert-hitphone.pem` na raiz do projeto: Certificado público do certificado SSL
|
|
@ -0,0 +1,47 @@
|
|||
# Objetivo
|
||||
|
||||
- Implementar uma Inbox de API que tem suporte para o provedor de SMS InfoBIP
|
||||
|
||||
## Chatwoot -> HIT-SMS-API
|
||||
|
||||
- [ ] Rota de envio dos eventos oriundos do Chatwoot
|
||||
- [ ] POST https://hit-sms-api.omnihit.app.br/api/chatwoot/webhook/sms/:provider_infobip/:apikey/:inbox_123
|
||||
- [ ] Evento: message_created
|
||||
- Parâmetros Requisição:
|
||||
```json
|
||||
{
|
||||
"id": 0,
|
||||
"content": "This is a incoming message from API Channel",
|
||||
"created_at": "2020-08-30T15:43:04.000Z",
|
||||
"message_type": "incoming",
|
||||
"content_type": null,
|
||||
"content_attributes": {},
|
||||
"source_id": null,
|
||||
"sender": {
|
||||
"id": 0,
|
||||
"name": "contact-name",
|
||||
"avatar": "",
|
||||
"type": "contact"
|
||||
},
|
||||
"inbox": {
|
||||
"id": 0,
|
||||
"name": "API Channel"
|
||||
},
|
||||
"conversation": {
|
||||
"additional_attributes": null,
|
||||
"channel": "Channel::Api",
|
||||
"id": 0,
|
||||
"inbox_id": 0,
|
||||
"status": "open",
|
||||
"agent_last_seen_at": 0,
|
||||
"contact_last_seen_at": 0,
|
||||
"timestamp": 0
|
||||
},
|
||||
"account": {
|
||||
"id": 1,
|
||||
"name": "API testing"
|
||||
},
|
||||
"event": "message_created"
|
||||
}
|
||||
```
|
||||
-
|
|
@ -0,0 +1,4 @@
|
|||
### Requisição para obter a configuração do servidor
|
||||
GET http://localhost:3435/api/hub/config
|
||||
Content-Type: application/json
|
||||
X-API-KEY: ASDASDASDASD
|
|
@ -0,0 +1,25 @@
|
|||
services:
|
||||
redis-sms-api:
|
||||
container_name: redis-sms-api
|
||||
hostname: redis-sms-api
|
||||
image: redis
|
||||
ports:
|
||||
- "6389:6379"
|
||||
restart: always
|
||||
volumes:
|
||||
- redis-data:/data
|
||||
|
||||
redis-commander-sms-api:
|
||||
container_name: redis-commander-sms-api
|
||||
hostname: redis-commander-sms-api
|
||||
image: ghcr.io/joeferner/redis-commander:latest
|
||||
#build: .
|
||||
environment:
|
||||
- REDIS_HOSTS=local:redis-sms-api:6379
|
||||
ports:
|
||||
- "8095:8081"
|
||||
depends_on:
|
||||
- redis-sms-api
|
||||
volumes:
|
||||
redis-data:
|
||||
driver: local
|
|
@ -0,0 +1,14 @@
|
|||
module.exports = {
|
||||
apps: [
|
||||
{
|
||||
name: 'hitphone-hub',
|
||||
script: 'dist/main.js',
|
||||
instances: 'max',
|
||||
exec_mode: 'cluster',
|
||||
env: {
|
||||
NODE_ENV: 'production'
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"$schema": "https://json.schemastore.org/nest-cli",
|
||||
"collection": "@nestjs/schematics",
|
||||
"sourceRoot": "src",
|
||||
"compilerOptions": {
|
||||
"deleteOutDir": true
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,75 @@
|
|||
{
|
||||
"name": "hitphone-hub",
|
||||
"version": "0.0.1",
|
||||
"description": "",
|
||||
"author": "",
|
||||
"private": true,
|
||||
"license": "UNLICENSED",
|
||||
"scripts": {
|
||||
"start": "nest start",
|
||||
"start:dev": "nest start --watch",
|
||||
"start:debug": "nest start --debug --watch",
|
||||
"start:prod": "npm run build && pm2 start ecosystem.config.js && pm2 reload hitphone-hub && pm2 save",
|
||||
"build": "nest build",
|
||||
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
|
||||
"lint": "eslint 'src/**/*.{ts,js}'",
|
||||
"lint:fix": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix"
|
||||
},
|
||||
"dependencies": {
|
||||
"@infobip-api/sdk": "^0.3.2",
|
||||
"@nestjs/common": "^10.4.4",
|
||||
"@nestjs/config": "^3.2.3",
|
||||
"@nestjs/core": "^10.0.0",
|
||||
"@nestjs/mapped-types": "*",
|
||||
"@nestjs/platform-express": "^10.0.0",
|
||||
"crypto-js": "^4.2.0",
|
||||
"dotenv": "^16.4.5",
|
||||
"morgan": "^1.10.0",
|
||||
"reflect-metadata": "^0.2.0",
|
||||
"rxjs": "^7.8.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nestjs/cli": "^10.0.0",
|
||||
"@nestjs/schematics": "^10.0.0",
|
||||
"@nestjs/testing": "^10.0.0",
|
||||
"@types/crypto-js": "^4.2.2",
|
||||
"@types/express": "^4.17.17",
|
||||
"@types/jest": "^29.5.2",
|
||||
"@types/morgan": "^1.9.9",
|
||||
"@types/node": "^20.3.1",
|
||||
"@types/supertest": "^6.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "^7.18.0",
|
||||
"@typescript-eslint/parser": "^7.18.0",
|
||||
"eslint": "^8.57.1",
|
||||
"eslint-config-prettier": "^9.0.0",
|
||||
"eslint-config-standard-with-typescript": "^43.0.1",
|
||||
"eslint-plugin-prettier": "^5.0.0",
|
||||
"jest": "^29.5.0",
|
||||
"prettier": "^3.0.0",
|
||||
"source-map-support": "^0.5.21",
|
||||
"standard": "^17.1.2",
|
||||
"supertest": "^7.0.0",
|
||||
"ts-jest": "^29.1.0",
|
||||
"ts-loader": "^9.4.3",
|
||||
"ts-node": "^10.9.1",
|
||||
"tsconfig-paths": "^4.2.0",
|
||||
"typescript": "^5.1.3"
|
||||
},
|
||||
"jest": {
|
||||
"moduleFileExtensions": [
|
||||
"js",
|
||||
"json",
|
||||
"ts"
|
||||
],
|
||||
"rootDir": "src",
|
||||
"testRegex": ".*\\.spec\\.ts$",
|
||||
"transform": {
|
||||
"^.+\\.(t|j)s$": "ts-jest"
|
||||
},
|
||||
"collectCoverageFrom": [
|
||||
"**/*.(t|j)s"
|
||||
],
|
||||
"coverageDirectory": "../coverage",
|
||||
"testEnvironment": "node"
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,24 @@
|
|||
import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common'
|
||||
import { ConfigModule } from '@nestjs/config'
|
||||
import { HubModule } from './hub/hub.module'
|
||||
import { LoggerMiddleware } from './middlewares/logger.middleware'
|
||||
import { SmsModule } from './sms/sms.module';
|
||||
import { ChatwootModule } from './chatwoot/chatwoot.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
ConfigModule.forRoot({
|
||||
isGlobal: true
|
||||
}),
|
||||
HubModule,
|
||||
SmsModule,
|
||||
ChatwootModule
|
||||
],
|
||||
providers: [HubModule]
|
||||
})
|
||||
export class AppModule implements NestModule {
|
||||
configure (consumer: MiddlewareConsumer) {
|
||||
consumer.apply(LoggerMiddleware)
|
||||
.forRoutes('*')
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common'
|
||||
import { ChatwootService } from './chatwoot.service'
|
||||
|
||||
@Controller('chatwoot')
|
||||
export class ChatwootController {
|
||||
constructor (private readonly chatwootService: ChatwootService) {}
|
||||
|
||||
@Post('/webhook/:sms/:provider/:apikey/:inbox')
|
||||
create (
|
||||
@Param() params: { sms: string, provider: 'infobip', apikey: string, inbox: string }
|
||||
|
||||
) {
|
||||
|
||||
}
|
||||
|
||||
@Get()
|
||||
findAll () {
|
||||
return this.chatwootService.findAll()
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
findOne (@Param('id') id: string) {
|
||||
return this.chatwootService.findOne(+id)
|
||||
}
|
||||
|
||||
@Patch(':id')
|
||||
update (@Param('id') id: string, @Body() updateChatwootDto: UpdateChatwootDto) {
|
||||
return this.chatwootService.update(+id, updateChatwootDto)
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
remove (@Param('id') id: string) {
|
||||
return this.chatwootService.remove(+id)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { ChatwootService } from './chatwoot.service';
|
||||
import { ChatwootController } from './chatwoot.controller';
|
||||
|
||||
@Module({
|
||||
controllers: [ChatwootController],
|
||||
providers: [ChatwootService],
|
||||
})
|
||||
export class ChatwootModule {}
|
|
@ -0,0 +1,18 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { ChatwootService } from './chatwoot.service';
|
||||
|
||||
describe('ChatwootService', () => {
|
||||
let service: ChatwootService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [ChatwootService],
|
||||
}).compile();
|
||||
|
||||
service = module.get<ChatwootService>(ChatwootService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,26 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import { CreateChatwootDto } from './dto/create-chatwoot.dto';
|
||||
import { UpdateChatwootDto } from './dto/update-chatwoot.dto';
|
||||
|
||||
@Injectable()
|
||||
export class ChatwootService {
|
||||
create(createChatwootDto: CreateChatwootDto) {
|
||||
return 'This action adds a new chatwoot';
|
||||
}
|
||||
|
||||
findAll() {
|
||||
return `This action returns all chatwoot`;
|
||||
}
|
||||
|
||||
findOne(id: number) {
|
||||
return `This action returns a #${id} chatwoot`;
|
||||
}
|
||||
|
||||
update(id: number, updateChatwootDto: UpdateChatwootDto) {
|
||||
return `This action updates a #${id} chatwoot`;
|
||||
}
|
||||
|
||||
remove(id: number) {
|
||||
return `This action removes a #${id} chatwoot`;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
import { CanActivate, ExecutionContext, Injectable, UnauthorizedException } from '@nestjs/common'
|
||||
import { Request } from 'express'
|
||||
|
||||
@Injectable()
|
||||
export class ApiKeyGuard implements CanActivate {
|
||||
canActivate (context: ExecutionContext): boolean {
|
||||
const request = context.switchToHttp().getRequest<Request>()
|
||||
const apiKey = request.headers['x-api-key']
|
||||
|
||||
const validApiKey = process.env.API_KEY
|
||||
|
||||
if (apiKey && apiKey === validApiKey) {
|
||||
return true
|
||||
}
|
||||
|
||||
throw new UnauthorizedException('API key is invalid or missing')
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
import { Controller, Get, InternalServerErrorException, Logger, UseGuards } from '@nestjs/common'
|
||||
import { HubService } from './hub.service'
|
||||
import { ApiKeyGuard } from 'src/guards/api-key.guard'
|
||||
|
||||
@Controller('hub')
|
||||
@UseGuards(ApiKeyGuard)
|
||||
export class HubController {
|
||||
constructor (private readonly hubService: HubService) { }
|
||||
|
||||
@Get('/config')
|
||||
async findHitphoneDesktopServerConfig () {
|
||||
try {
|
||||
const hitphoneDesktopServerConfig = await this.hubService.findHitphoneDesktopServerConfig()
|
||||
return {
|
||||
...hitphoneDesktopServerConfig
|
||||
}
|
||||
} catch (error) {
|
||||
Logger.error(`Error reading certificate or key file: ${error.message}`)
|
||||
throw new InternalServerErrorException({
|
||||
message: 'Error reading config informations'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
import { Module } from '@nestjs/common'
|
||||
import { HubService } from './hub.service'
|
||||
import { HubController } from './hub.controller'
|
||||
|
||||
@Module({
|
||||
controllers: [HubController],
|
||||
providers: [HubService]
|
||||
})
|
||||
export class HubModule {}
|
|
@ -0,0 +1,47 @@
|
|||
import { Injectable } from '@nestjs/common'
|
||||
import { ConfigService } from '@nestjs/config'
|
||||
import * as fs from 'fs/promises'
|
||||
import * as path from 'path'
|
||||
|
||||
import encrypt from 'src/utils/encrypt'
|
||||
|
||||
@Injectable()
|
||||
export class HubService {
|
||||
constructor (private readonly configService: ConfigService) { }
|
||||
|
||||
async findHitphoneDesktopServerConfig () {
|
||||
try {
|
||||
const ENCRYPTION_KEY = this.configService.get<string>('ENCRYPTION_KEY')
|
||||
|
||||
const origin = this.configService.get<string>('HITPHONE_DESKTOP_SERVER_ORIGINS')
|
||||
const certificatePem = await fs.readFile(path.join(__dirname, '../../cert-hitphone.pem'), 'utf8')
|
||||
const certificateKey = await fs.readFile(path.join(__dirname, '../../cert-hitphone.key'), 'utf8')
|
||||
|
||||
if (!origin || !certificatePem || !certificateKey || !ENCRYPTION_KEY) {
|
||||
throw new Error("ENCRYPTION_KEY, HITPHONE_DESKTOP_SERVER_ORIGINS, cert-hitphone.pem or cert-hitphone.key doesn't exist")
|
||||
}
|
||||
|
||||
const originSplit = origin.split(',')
|
||||
|
||||
// return keys
|
||||
const encryptedOriginReturnKey = encrypt('origin', ENCRYPTION_KEY)
|
||||
const encryptedCertificateKeyReturnKey = encrypt('certificateKey', ENCRYPTION_KEY)
|
||||
const encryptedCertificatePemReturnKey = encrypt('certificatePem', ENCRYPTION_KEY)
|
||||
|
||||
// return values
|
||||
const originEncrypted = originSplit.map((origin) => {
|
||||
return encrypt(origin, ENCRYPTION_KEY)
|
||||
})
|
||||
const encryptedCertificateKey = encrypt(certificateKey, ENCRYPTION_KEY)
|
||||
const encryptedCertificatePem = encrypt(certificatePem, ENCRYPTION_KEY)
|
||||
|
||||
return {
|
||||
[encryptedOriginReturnKey]: originEncrypted,
|
||||
[encryptedCertificateKeyReturnKey]: encryptedCertificateKey,
|
||||
[encryptedCertificatePemReturnKey]: encryptedCertificatePem
|
||||
}
|
||||
} catch (error) {
|
||||
throw new Error('Error reading certificate or key file: ' + error.message)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
import { NestFactory } from '@nestjs/core'
|
||||
import { AppModule } from './app.module'
|
||||
|
||||
async function bootstrap () {
|
||||
const app = await NestFactory.create(AppModule)
|
||||
|
||||
app.setGlobalPrefix('api')
|
||||
app.enableCors({
|
||||
origin: '*'
|
||||
})
|
||||
|
||||
await app.listen(3435)
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
bootstrap()
|
|
@ -0,0 +1,49 @@
|
|||
import { Injectable, NestMiddleware } from '@nestjs/common'
|
||||
import * as morgan from 'morgan'
|
||||
import { IncomingMessage, ServerResponse } from 'http'
|
||||
|
||||
@Injectable()
|
||||
export class LoggerMiddleware implements NestMiddleware {
|
||||
private readonly morganMiddleware: any
|
||||
|
||||
constructor () {
|
||||
// Define os tokens personalizados
|
||||
morgan.token('timestamp', () => {
|
||||
const date = new Date()
|
||||
return date.toLocaleString('pt-BR', {
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
second: '2-digit',
|
||||
day: '2-digit',
|
||||
month: '2-digit',
|
||||
year: 'numeric',
|
||||
hour12: false
|
||||
})
|
||||
})
|
||||
|
||||
morgan.token('statusColor', (req: IncomingMessage, res: ServerResponse) => {
|
||||
const status = res.headersSent ? res.statusCode : undefined
|
||||
const color = status !== undefined
|
||||
? (
|
||||
status >= 500
|
||||
? 31
|
||||
: status >= 400
|
||||
? 33
|
||||
: status >= 300
|
||||
? 36
|
||||
: status >= 200
|
||||
? 32
|
||||
: 0
|
||||
)
|
||||
: 0
|
||||
|
||||
return `\x1b[${color}m${status}\x1b[0m`
|
||||
})
|
||||
|
||||
this.morganMiddleware = morgan(':timestamp - :method :url :statusColor :response-time ms - :res[content-length]')
|
||||
}
|
||||
|
||||
use (req: IncomingMessage, res: ServerResponse, next: () => void) {
|
||||
this.morganMiddleware(req, res, next)
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
export class CreateSmDto {}
|
|
@ -0,0 +1,4 @@
|
|||
import { PartialType } from '@nestjs/mapped-types';
|
||||
import { CreateSmDto } from './create-sm.dto';
|
||||
|
||||
export class UpdateSmDto extends PartialType(CreateSmDto) {}
|
|
@ -0,0 +1 @@
|
|||
export class Sm {}
|
|
@ -0,0 +1,45 @@
|
|||
import { Controller, Get, Post, Body, Patch, Param, Delete, InternalServerErrorException, Logger } from '@nestjs/common'
|
||||
import { SmsService } from './sms.service'
|
||||
import { CreateSmDto } from './dto/create-sm.dto'
|
||||
import { UpdateSmDto } from './dto/update-sm.dto'
|
||||
|
||||
@Controller('sms')
|
||||
export class SmsController {
|
||||
constructor (private readonly smsService: SmsService) {}
|
||||
|
||||
@Post('/:provider')
|
||||
createSmsMessage (@Body() smsMessage: CreateSmDto) {
|
||||
try {
|
||||
const hitphoneDesktopServerConfig = await this.hubService.findHitphoneDesktopServerConfig()
|
||||
return {
|
||||
...hitphoneDesktopServerConfig
|
||||
}
|
||||
} catch (error) {
|
||||
Logger.error(`Error reading certificate or key file: ${error.message}`)
|
||||
throw new InternalServerErrorException({
|
||||
message: 'Error reading config informations'
|
||||
})
|
||||
}
|
||||
// return this.smsService.create(createSmDto)
|
||||
}
|
||||
|
||||
@Get()
|
||||
findAll () {
|
||||
return this.smsService.findAll()
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
findOne (@Param('id') id: string) {
|
||||
return this.smsService.findOne(+id)
|
||||
}
|
||||
|
||||
@Patch(':id')
|
||||
update (@Param('id') id: string, @Body() updateSmDto: UpdateSmDto) {
|
||||
return this.smsService.update(+id, updateSmDto)
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
remove (@Param('id') id: string) {
|
||||
return this.smsService.remove(+id)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
import { Module } from '@nestjs/common'
|
||||
import { SmsService } from './sms.service'
|
||||
import { SmsController } from './sms.controller'
|
||||
|
||||
@Module({
|
||||
controllers: [SmsController],
|
||||
providers: [SmsService]
|
||||
})
|
||||
export class SmsModule {}
|
|
@ -0,0 +1,18 @@
|
|||
import { Test, type TestingModule } from '@nestjs/testing'
|
||||
import { SmsService } from './sms.service'
|
||||
|
||||
describe('SmsService', () => {
|
||||
let service: SmsService
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [SmsService]
|
||||
}).compile()
|
||||
|
||||
service = module.get<SmsService>(SmsService)
|
||||
})
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined()
|
||||
})
|
||||
})
|
|
@ -0,0 +1,26 @@
|
|||
import { Injectable } from '@nestjs/common'
|
||||
import { CreateSmDto } from './dto/create-sm.dto'
|
||||
import { UpdateSmDto } from './dto/update-sm.dto'
|
||||
|
||||
@Injectable()
|
||||
export class SmsService {
|
||||
create (createSmDto: CreateSmDto) {
|
||||
return 'This action adds a new sm'
|
||||
}
|
||||
|
||||
findAll () {
|
||||
return 'This action returns all sms'
|
||||
}
|
||||
|
||||
findOne (id: number) {
|
||||
return `This action returns a #${id} sm`
|
||||
}
|
||||
|
||||
update (id: number, updateSmDto: UpdateSmDto) {
|
||||
return `This action updates a #${id} sm`
|
||||
}
|
||||
|
||||
remove (id: number) {
|
||||
return `This action removes a #${id} sm`
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
import * as CryptoJS from 'crypto-js'
|
||||
|
||||
function encrypt (string: string, ENCRYPTION_KEY: string): string {
|
||||
const encryptedText = CryptoJS.AES.encrypt(string, ENCRYPTION_KEY)
|
||||
const ciphertext = encryptedText.toString()
|
||||
|
||||
return ciphertext
|
||||
}
|
||||
|
||||
export default encrypt
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"exclude": ["node_modules", "test", "dist", "**/*spec.ts"]
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"declaration": true,
|
||||
"removeComments": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"target": "ES2021",
|
||||
"sourceMap": true,
|
||||
"outDir": "./dist",
|
||||
"baseUrl": "./",
|
||||
"incremental": true,
|
||||
"skipLibCheck": true,
|
||||
"strictNullChecks": true,
|
||||
"noImplicitAny": true,
|
||||
"strictBindCallApply": false,
|
||||
"forceConsistentCasingInFileNames": false,
|
||||
"noFallthroughCasesInSwitch": false,
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue