Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

[Snyk] Security upgrade node from 20.7.0-alpine to 20.18.1-alpine #30

Open
wants to merge 30 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
d962915
feat: env to hide index and manager
gabrielpastori1 Sep 9, 2023
d48ce9f
fix: add PORT as env alias to SERVER_PORT
gabrielpastori1 Sep 9, 2023
bd7294c
fix: default options to CORS_ORIGIN and CORS_METHODS
gabrielpastori1 Sep 9, 2023
b63648c
add heroku app.json
gabrielpastori1 Sep 10, 2023
f6efb7d
fix: heroku non required env
gabrielpastori1 Sep 10, 2023
a371164
fix: RABBITMQ_URI non required
gabrielpastori1 Sep 10, 2023
42d0c30
feat: alias to DATABASE_CONNECTION_URI for heroku deploy
gabrielpastori1 Sep 10, 2023
05c9732
feat: add Procfile
gabrielpastori1 Sep 10, 2023
391c10e
add heroku to readme
gabrielpastori1 Sep 10, 2023
88011da
fix: removal of very expensive heroku mongoDB
gabrielpastori1 Sep 10, 2023
0505338
fix: add HEROKU_ENV
gabrielpastori1 Sep 10, 2023
af2f883
fix: DATABASE_CONNECTION_URI required
gabrielpastori1 Sep 10, 2023
93d255f
fix: add LOG_LEVEL env
gabrielpastori1 Sep 10, 2023
b99f099
fix: force http in heroku
gabrielpastori1 Sep 11, 2023
d775a45
fix: revert delete instance router
gabrielpastori1 Sep 14, 2023
2d51647
add Procfile
gabrielpastori1 Sep 7, 2023
c2a8685
fix: procfile
gabrielpastori1 Sep 7, 2023
cf58498
fix: procfile
gabrielpastori1 Sep 7, 2023
7a74cea
comment env force 8080
gabrielpastori1 Sep 7, 2023
dead37d
hide index
gabrielpastori1 Sep 7, 2023
a020eb2
add rabbitMQ log
gabrielpastori1 Sep 8, 2023
f0b9353
fix: rabbitMQ event hook
gabrielpastori1 Sep 8, 2023
18d52a7
feat: link preview and hide manager
gabrielpastori1 Sep 8, 2023
9e977d4
Merge branch 'main' into heroku-button
gabrielpastori1 Oct 24, 2023
215f3d5
Merge pull request #5 from gabrielpastori1/heroku-button
gabrielpastori1 Oct 24, 2023
26d1f83
Merge pull request #6 from EvolutionAPI/main
gabrielpastori1 Oct 24, 2023
8e362a9
Update issue templates
gabrielpastori1 Dec 19, 2023
f5ecd8e
Merge branch 'EvolutionAPI:main' into main
gabrielpastori1 Dec 19, 2023
236af88
Merge remote-tracking branch 'upstream/main'
gabrielpastori1 Mar 20, 2024
0a604c6
fix: Dockerfile to reduce vulnerabilities
snyk-bot Dec 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM node:20.7.0-alpine AS builder
FROM node:20.18.1-alpine AS builder

LABEL version="1.7.0" description="Api to control whatsapp features through http requests."
LABEL maintainer="Davidson Gomes" git="https://github.com/DavidsonGomes"
Expand All @@ -17,7 +17,7 @@ COPY . .

RUN npm run build

FROM node:20.7.0-alpine AS final
FROM node:20.18.1-alpine AS final

ENV TZ=America/Sao_Paulo
ENV DOCKER_ENV=true
Expand Down
2 changes: 2 additions & 0 deletions Procfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
web: node ./dist/src/main.js

26 changes: 22 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

[![Whatsapp Group](https://img.shields.io/badge/Group-WhatsApp-%2322BC18)](https://evolution-api.com/whatsapp)
[![Discord Community](https://img.shields.io/badge/Discord-Community-blue)](https://evolution-api.com/discord)
[![Postman Collection](https://img.shields.io/badge/Postman-Collection-orange)](https://evolution-api.com/postman)
[![Postman Collection](https://img.shields.io/badge/Postman-Collection-orange)](https://evolution-api.com/postman)
[![Documentation](https://img.shields.io/badge/Documentation-Official-green)](https://doc.evolution-api.com)
[![License](https://img.shields.io/badge/license-GPL--3.0-orange)](./LICENSE)
[![Support](https://img.shields.io/badge/Donation-picpay-green)](https://app.picpay.com/user/davidsongomes1998)
Expand All @@ -16,20 +16,38 @@

## WhatsApp-Api-NodeJs

This project is based on the [CodeChat](https://github.com/code-chat-br/whatsapp-api). The original project is an implementation of [Baileys](https://github.com/WhiskeySockets/Baileys), serving as a Restful API service that controls WhatsApp functions.</br>
This project is based on the [CodeChat](https://github.com/code-chat-br/whatsapp-api). The original project is an implementation of [Baileys](https://github.com/WhiskeySockets/Baileys), serving as a Restful API service that controls WhatsApp functions.</br>
The code allows the creation of multiservice chats, service bots, or any other system that utilizes WhatsApp. The documentation provides instructions on how to set up and use the project, as well as additional information about its features and configuration options.

## SSL

To install the SSL certificate, follow the **[instructions](https://certbot.eff.org/instructions?ws=other&os=ubuntufocal)** below.

## Installation

### Self-hosted (VPS)

For self-hosted installation, you will need a VPS with at least 2GB of RAM and 2vCPU. The installation process is simple, just follow the steps below.
<https://doc.evolution-api.com/help-center/articles/7/introduction#important-recomentations>

<!-- RECOMEND https://hetzner.cloud/?ref=E1AsUeCv1soz -->
We recommend using the [Hetzner](https://hetzner.cloud/?ref=E1AsUeCv1soz) cloud service, which offers a 20 EUR credit for new accounts and helps the project with a small commission.

### Heroku Button

Automatically deploy to Heroku with the button below. You will need to create a free account on Heroku to use this feature. Average cost of hosting on Heroku is $7/month.

For use heroku you need to use a MongoDB database, you can use [MongoDB Atlas](https://www.mongodb.com/atlas) for free. Before deploying to Heroku, create a database and copy the connection string to `DATABASE_CONNECTION_URI` environment variable.

[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy)

# Note

This code is in no way affiliated with WhatsApp. Use at your own discretion. Don't spam this.

This code was produced based on the baileys library and it is still under development.

# Donate to the project.
# Donate to the project

#### PicPay

Expand All @@ -48,4 +66,4 @@ This code was produced based on the baileys library and it is still under develo
<p><b>CHAVE PIX (Telefone):</b> (74)99987-9409</p>
</div>

</br>
</br>
193 changes: 193 additions & 0 deletions app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
{
"name": "EvolutionAPI",
"description": "A Restful API service that controls WhatsApp functions.",
"keywords": [
"whatsapp",
"api",
"restful",
"whatsapp api"
],
"website": "https://evolution-api.com/",
"repository": "https://github.com/EvolutionAPI/evolution-api",
"logo": "https://github.com/EvolutionAPI/evolution-api/blob/main/public/images/atendai-logo.png?raw=true",
"success_url": "/manager",
"env": {
"SERVER_TYPE": {
"description": "The type of server to run. For heroku, this should be 'http'.",
"value": "http"
},
"SERVER_URL": {
"description": "The URL of the server. For heroku, change this before first deploy to the heroku app URL.",
"required": false
},
"SERVER_HIDE_INDEX": {
"description": "Hide the index page.",
"value": "false"
},
"SERVER_HIDE_MANAGER": {
"description": "Hide the manager page.",
"value": "false"
},
"CORS_ORIGIN": {
"description": "The origin to allow CORS requests from.",
"required": false
},
"CORS_METHODS": {
"description": "The methods to allow CORS requests for.",
"required": false
},
"CORS_CREDENTIALS": {
"description": "Allow CORS requests to send credentials.",
"required": false
},
"SSL_CONF_PRIVKEY": {
"description": "The path to the SSL private key. For heroku, this should be empty.",
"required": false
},
"SSL_CONF_FULLCHAIN": {
"description": "The path to the SSL full chain. For heroku, this should be empty.",
"required": false
},
"STORE_MESSAGES": {
"description": "Enable message storage. (true/false)",
"value": "true"
},
"STORE_MESSAGE_UP": {
"description": "Enable message upload storage. (true/false)",
"value": "true"
},
"STORE_CONTACTS": {
"description": "Enable contact storage. (true/false)",
"value": "true"
},
"STORE_CHATS": {
"description": "Enable chat storage. (true/false)",
"value": "true"
},
"CLEAN_STORE_CLEANING_TERMINAL": {
"description": "Interval in seconds between cleaning terminal. default: 7200 (2 hours)",
"value": "7200"
},
"CLEAN_STORE_MESSAGES": {
"description": "Enable message cleaning. (true/false)",
"value": "true"
},
"CLEAN_STORE_MESSAGE_UP": {
"description": "Enable message upload cleaning. (true/false)",
"value": "true"
},
"CLEAN_STORE_CONTACTS": {
"description": "Enable contact cleaning. (true/false)",
"value": "true"
},
"CLEAN_STORE_CHATS": {
"description": "Enable chat cleaning. (true/false)",
"value": "true"
},
"DATABASE_ENABLED": {
"description": "Enable database. (true/false)",
"value": "true"
},
"DATABASE_CONNECTION_URI": {
"description": "The connection URI for the database. For heroku, this is required."
},
"DATABASE_CONNECTION_DB_PREFIX_NAME": {
"description": "The prefix name for the database.",
"value": "evolution"
},
"DATABASE_SAVE_DATA_INSTANCE": {
"description": "Enable instance data storage. For heroku, this should be true.",
"value": "true"
},
"DATABASE_SAVE_DATA_NEW_MESSAGE": {
"description": "Enable new message data storage. (true/false)",
"value": "false"
},
"DATABASE_SAVE_MESSAGE_UPDATE": {
"description": "Enable message update data storage. (true/false)",
"value": "false"
},
"DATABASE_SAVE_DATA_CONTACTS": {
"description": "Enable contacts data storage. (true/false)",
"value": "false"
},
"DATABASE_SAVE_DATA_CHATS": {
"description": "Enable chats data storage. (true/false)",
"value": "false"
},
"REDIS_ENABLED": {
"description": "Enable redis. (true/false)",
"value": "false"
},
"REDIS_CONNECTION_URI": {
"description": "The connection URI for redis. (redis://[username:password@]host[:port][/db-number][?option=value])",
"required": false
},
"REDIS_PREFIX_KEY": {
"description": "The prefix key for redis.",
"value": "evolution"
},
"RABBITMQ_ENABLED": {
"description": "Enable rabbitmq. (true/false)",
"value": "false"
},
"RABBITMQ_URI": {
"description": "The URI for rabbitmq. (amqp://[username:password@]host[:port][/vhost])",
"required": false
},
"CONFIG_SESSION_PHONE_CLIENT": {
"description": "The client name for the whatsapp web session.",
"value": "EvolutionAPI"
},
"CONFIG_SESSION_PHONE_NAME": {
"description": "The browser name for the whatsapp web session. (Chrome | Firefox | Edge | Opera | Safari)",
"value": "Chrome"
},
"QRCODE_LIMIT": {
"description": "The limit of qrcode.",
"value": "30"
},
"QRCODE_COLOR": {
"description": "The color of qrcode. (hex color)",
"value": "#198754"
},
"AUTHENTICATION_TYPE": {
"description": "The type of authentication. (apikey | jwt)",
"value": "apikey"
},
"AUTHENTICATION_API_KEY": {
"description": "The api key for authentication. (only for apikey authentication)",
"generator": "secret"
},
"AUTHENTICATION_EXPOSE_IN_FETCH_INSTANCES": {
"description": "Expose the api key in fetch instances. (true/false)",
"value": "false"
},
"AUTHENTICATION_JWT_EXPIRIN_IN": {
"description": "The expiration time for jwt. (only for jwt authentication) (0 = never expires)",
"value": "0"
},
"AUTHENTICATION_JWT_SECRET": {
"description": "The secret for jwt. (only for jwt authentication)",
"generator": "secret"
},
"HEROKU_ENV": {
"description": "Enable heroku env. (true/false) (only for heroku)",
"value": "true"
},
"LOG_LEVEL": {
"description": "The log level. (error | warn | info | http | verbose | debug | silly)",
"value": "error,warn,info,http,verbose,debug,silly"
}
},
"formation": {
"web": {
"quantity": 1,
"size": "basic"
}
},
"image": "heroku/nodejs",
"addons": [
"logtail:free"
]
}
23 changes: 10 additions & 13 deletions src/config/env.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,11 +218,14 @@ export class ConfigService {
}

private loadEnv() {
this.env = !(process.env?.DOCKER_ENV === 'true') ? this.envYaml() : this.envProcess();
this.env =
!(process.env?.DOCKER_ENV === 'true') && !(process.env?.HEROKU_ENV === 'true')
? this.envYaml()
: this.envProcess();
this.env.PRODUCTION = process.env?.NODE_ENV === 'PROD';
if (process.env?.DOCKER_ENV === 'true') {
this.env.SERVER.TYPE = process.env.SERVER_TYPE as 'http' | 'http';
this.env.SERVER.PORT = Number.parseInt(process.env.SERVER_PORT) || 8080;
this.env.SERVER.TYPE = 'http';
this.env.SERVER.PORT = 8080;
}
}

Expand All @@ -233,15 +236,13 @@ export class ConfigService {
private envProcess(): Env {
return {
SERVER: {
TYPE: (process.env.SERVER_TYPE as 'http' | 'https') || 'http',
TYPE: process.env.SERVER_TYPE as 'http' | 'https',
PORT: Number.parseInt(process.env.SERVER_PORT) || 8080,
URL: process.env.SERVER_URL,
DISABLE_DOCS: process.env?.SERVER_DISABLE_DOCS === 'true',
DISABLE_MANAGER: process.env?.SERVER_DISABLE_MANAGER === 'true',
},
CORS: {
ORIGIN: process.env.CORS_ORIGIN.split(',') || ['*'],
METHODS: (process.env.CORS_METHODS.split(',') as HttpMethods[]) || ['POST', 'GET', 'PUT', 'DELETE'],
ORIGIN: process.env.CORS_ORIGIN?.split(',') || ['*'],
METHODS: (process.env.CORS_METHODS?.split(',') as HttpMethods[]) || ['POST', 'GET', 'PUT', 'DELETE'],
CREDENTIALS: process.env?.CORS_CREDENTIALS === 'true',
},
SSL_CONF: {
Expand All @@ -266,7 +267,7 @@ export class ConfigService {
},
DATABASE: {
CONNECTION: {
URI: process.env.DATABASE_CONNECTION_URI || '',
URI: process.env.DATABASE_CONNECTION_URI || process.env.DATABASE_CONNECTION_URL || '',
DB_PREFIX_NAME: process.env.DATABASE_CONNECTION_DB_PREFIX_NAME || 'evolution',
},
ENABLED: process.env?.DATABASE_ENABLED === 'true',
Expand Down Expand Up @@ -323,10 +324,6 @@ export class ConfigService {
DEL_INSTANCE: isBooleanString(process.env?.DEL_INSTANCE)
? process.env.DEL_INSTANCE === 'true'
: Number.parseInt(process.env.DEL_INSTANCE) || false,
DEL_TEMP_INSTANCES: isBooleanString(process.env?.DEL_TEMP_INSTANCES)
? process.env.DEL_TEMP_INSTANCES === 'true'
: true,
LANGUAGE: process.env?.LANGUAGE || 'en',
WEBHOOK: {
GLOBAL: {
URL: process.env?.WEBHOOK_GLOBAL_URL || '',
Expand Down
24 changes: 13 additions & 11 deletions src/whatsapp/routers/index.router.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Router } from 'express';
import fs from 'fs';

import { Auth, configService } from '../../config/env.config';
import { Auth, configService, HttpServer } from '../../config/env.config';
import { authGuard } from '../guards/auth.guard';
import { instanceExistsGuard, instanceLoggedGuard } from '../guards/instance.guard';
import { ChamaaiRouter } from './chamaai.router';
Expand Down Expand Up @@ -39,17 +39,19 @@ const packageJson = JSON.parse(fs.readFileSync('./package.json', 'utf8'));

if (!serverConfig.DISABLE_MANAGER) router.use('/manager', new ViewsRouter().router);

router.get('/', (req, res) => {
res.status(HttpStatus.OK).json({
status: HttpStatus.OK,
message: 'Welcome to the Evolution API, it is working!',
version: packageJson.version,
swagger: !serverConfig.DISABLE_DOCS ? `${req.protocol}://${req.get('host')}/docs` : undefined,
manager: !serverConfig.DISABLE_MANAGER ? `${req.protocol}://${req.get('host')}/manager` : undefined,
documentation: `https://doc.evolution-api.com`,
});
});
if (!httpServer.HIDE_MANAGER) router.use('/manager', new ViewsRouter().router);

router
.get('/', (req, res) => {
res.status(HttpStatus.OK).json({
status: HttpStatus.OK,
message: 'Welcome to the Evolution API, it is working!',
version: packageJson.version,
swagger: !serverConfig.DISABLE_DOCS ? `${req.protocol}://${req.get('host')}/docs` : undefined,
manager: !serverConfig.DISABLE_MANAGER ? `${req.protocol}://${req.get('host')}/manager` : undefined,
documentation: `https://doc.evolution-api.com`,
});
})
.use('/instance', new InstanceRouter(configService, ...guards).router)
.use('/message', new MessageRouter(...guards).router)
.use('/chat', new ChatRouter(...guards).router)
Expand Down
6 changes: 4 additions & 2 deletions src/whatsapp/services/whatsapp.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -684,15 +684,17 @@ export class WAStartupService {
const amqp = getAMQP();

if (amqp) {
this.logger.verbose('Sending data to rabbitMQ on channel: ' + this.instance.name);
if (Array.isArray(rabbitmqLocal) && rabbitmqLocal.includes(we)) {
const exchangeName = this.instanceName ?? 'evolution_exchange';
this.logger.verbose('Sending data to rabbitMQ on event: ' + event);
const exchangeName = this.instance.name ?? 'evolution_exchange';

amqp.assertExchange(exchangeName, 'topic', {
durable: true,
autoDelete: false,
});

const queueName = `${this.instanceName}.${event}`;
const queueName = `${this.instance.name}.${event}`;

amqp.assertQueue(queueName, {
durable: true,
Expand Down