Deck of Cards |
---|
startHidden | false |
---|
effectDuration | 0.5 |
---|
id | configuracao-tecnica |
---|
| Card |
---|
effectDuration | 0.5 |
---|
id | instalacao |
---|
label | Instalação |
---|
title | Instalação |
---|
| Clone dos Projetos O AppLinker possui dois repositórios. Um contém o projeto Frontend e o outro o Backend. Segue os links para os repositórios: |
Card |
---|
effectDuration | 0.5 |
---|
id | ambiente-desenvolvimento |
---|
label | Ambiente de Desenvolvimento |
---|
title | Ambiente de Desenvolvimento |
---|
| Configurar MáquinaPara subir o client e o server do AppLinker em uma máquina para fins de desenvolvimento, é necessário instalar algumas dependencias. Segue uma lista de tecnologias que devem estar presentes. Para subir o client: Para subir o server: Instale o Banco de Dados Postgree para testes locais. As branchs para iniciar o desenvolvimento de qualquer feature devem ser feitas a partir da "develop" (tanto client como server). |
Card |
---|
effectDuration | 0.5 |
---|
id | aponte-local |
---|
label | Aponte para Local |
---|
title | Aponte para Local |
---|
| Deck of Cards |
---|
effectDuration | 0.5 |
---|
id | arquivos |
---|
| Card |
---|
effectDuration | 0.5 |
---|
id | frontend |
---|
label | Frontend |
---|
title | Frontend |
---|
| Alterando para LocalHost Aviso |
---|
Todas as requisições são feitas para ambiente de produção. Altere os arquivos para que sejam direcionadas para localhost. |
Note a seguir que o client faz todas as suas requisições usando um provider HttpService. Neste HttpService usamos uma constante que possui a URL para onde estamos apontando, para localhost ou produção. Bloco de código |
---|
language | js |
---|
theme | Midnight |
---|
firstline | 1 |
---|
title | AppLinkerClient/app/src/app/providers/http.service.ts |
---|
| import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { environment } from '../../environments/environment';
const APP_API = environment.api;
@Injectable({
providedIn: 'root'
})
export class HttpService {
constructor(private http: HttpClient) { }
get(endpoint) {
return this.http.get(`${APP_API}/${endpoint}`);
}
post(endpoint, body = {}) {
return this.http.post(`${APP_API}/${endpoint}`, body);
}
} |
No arquivo environment.ts altere o valor do objeto de: Bloco de código |
---|
language | js |
---|
theme | Midnight |
---|
firstline | 1 |
---|
title | AppLinkerClient/app/src/environments/environment.ts |
---|
| export const environment = {
production: true,
api: 'https://applinkerserver.applinker.engpro.totvs.com.br'
}; |
para: Bloco de código |
---|
language | js |
---|
theme | Midnight |
---|
firstline | 1 |
---|
title | AppLinkerClient/app/src/environments/environment.ts |
---|
| export const environment = {
production: false,
api: 'http://localhost:3000'
}; |
|
Card |
---|
effectDuration | 0.5 |
---|
id | backend |
---|
label | Backend |
---|
title | Backend |
---|
| Serviço de E-mails Aviso |
---|
Todas as requisições são feitas para ambiente de produção. Altere os arquivos para que sejam direcionadas para localhost. |
Para que as funcionalidades "Ativação de Usuários", "Recuperação de Senha" funcionem em ambiente local, altere os dados da configuração do banco e do ambiente de produção. No arquivo config_db.ts altere o valor do objeto de: Bloco de código |
---|
language | js |
---|
theme | Midnight |
---|
firstline | 1 |
---|
title | AppLinkerServer/server/modules/database/config_db.ts |
---|
| export class ConfigDB {
private conn;
public async connectDB() {
const { Pool, Client } = require('pg')
const connectionString = "postgres://applinker:dado_sensivel@postgres:5432/applinker"
const pool = new Pool({
connectionString: connectionString,
})
pool
.connect()
.then( ()=> console.info('conectado com sucesso'))
.catch( () => console.info('falha ao conectar com o banco de dados.'))
return await pool
}
}
|
para: Bloco de código |
---|
language | js |
---|
theme | Midnight |
---|
firstline | 1 |
---|
title | AppLinkerServer/server/modules/database/config_db.ts |
---|
| export class ConfigDB {
private conn;
public async connectDB() {
const { Pool, Client } = require('pg')
const connectionString = "postgres://postgres:123456@localhost:5432/applinker";
const pool = new Pool({
connectionString: connectionString,
})
pool
.connect()
.then( ()=> console.info('conectado com sucesso'))
.catch( () => console.info('falha ao conectar com o banco de dados.'))
return await pool
}
}
|
No arquivo controller.ts altere o código de: Bloco de código |
---|
language | js |
---|
theme | Midnight |
---|
firstline | 1 |
---|
title | AppLinkerServer/server/modules/auth/controller.ts |
---|
| import { ConfigDB } from './../database/config_db';
import { Request, Response } from 'express';
import * as ldap from 'ldapjs';
import * as jwt from 'jsonwebtoken';
import * as nodemailer from 'nodemailer';
import { google } from 'googleapis';
const SMTP_CONFIG = require('./../../config/env/smtp')
const config = require('../../config/env/')();
// declaracao do OAuth2
const OAuth2 = google.auth.OAuth2;
export class AuthController {
protected client;
protected adSuffix = "dc=local";
constructor() {
// this.client = ldap.createClient({
// url: config.activeDirectory.url
// });
// this.client.bind(config.activeDirectory.user, config.activeDirectory.password, err => {
// if (err) {
// throw new Error('user LDAP não autenticado!');
// }
// });
}
public auth(req: Request, res: Response, next: any) {
this.authWithoutAD(req, res, next);
}
// public authWithAD(req: Request, res: Response, next: any) {
// const searchOptions = {
// scope: "sub",
// filter: `(&(objectClass=person)(sAMAccountName=${req.body.user})(!(userAccountControl:1.2.840.113556.1.4.803:=2)))`
// };
// this.client.search(this.adSuffix,searchOptions,(err, response) => {
// console.log('logando...');
// if (err) {
// console.log(`erro ao efetuar as busca ${err}`);
// }
// response.on('searchEntry', entry => {
// console.log('buscando login...');
// this.client.bind(entry.object.dn, req.body.password, (err) => {
// if (err) {
// res.status(400);
// res.send({error: "Unauthorized"});
// } else {
// res.send({
// user: entry.object.sAMAccountName,
// userEmail: entry.object.mail,
// token: jwt.sign({user: entry.object.sAMAccountName}, config.masterKey)
// });
// }
// res.end();
// });
// });
// });
// req.setTimeout(20000);
// }
public async register(req: Request, res: Response, next: any) {
const db = new ConfigDB();
try {
const conn = await db.connectDB();
let result = await conn.query("select * from tb_users where email = $1 ", [req.body.user]);
if (result.rows.length > 0) {
return res.status(400).send({ error: "O email ja esta sendo utilizado." });
}
result = await conn.query("insert into tb_users (email, password,enable) values ($1, md5($2),false)", [req.body.user, req.body.password]);
if (!result.err) {
res.send({
userEmail: req.body.user
});
await this.sentEmail(req.body.user)
} else {
res.status(400).send({ error: "Não foi possivel cadastrar" });
}
conn.end();
} catch (err) {
return res.status(500).send({ error: err.name });
}
}
public async authWithoutAD(req: Request, res: Response, next: any) {
const db = new ConfigDB();
try {
const conn = await db.connectDB();
let result = await conn.query("select email from tb_users where email = $1 and password = md5($2) and enable = true", [req.body.user, req.body.password]);
if (result.rowCount > 0) {
res.send({
user: req.body.user.split("@")[0],
userEmail: req.body.user,
token: jwt.sign({ user: req.body.user }, config.masterKey)
});
} else {
result = await conn.query("select email from tb_users where email = $1 and password = md5($2) and enable = false", [req.body.user, req.body.password]);
if (result.rowCount > 0) {
res.status(401).send({ error: "Usuário aguardando aprovação " });
} else {
res.status(403).send({ error: "Senha ou email incorretos " });
}
}
} catch (err) {
res.status(500).send({ error: err.name });
}
}
// Acrescentando OAuth2 Authentication
public async sentEmail(email: string): Promise<void> {
const emailToken = jwt.sign({ email }, config.masterKey);
const oauth2Client = new OAuth2(SMTP_CONFIG.client_id, SMTP_CONFIG.secret_key, SMTP_CONFIG.redirect_uri);
oauth2Client.setCredentials({
refresh_token: SMTP_CONFIG.refresh_token
})
const accessToken = await oauth2Client.getAccessToken().then((token) => {
return token.token;
})
const transporter = await nodemailer.createTransport({
host: SMTP_CONFIG.host,
port: SMTP_CONFIG.port,
secure: true,
auth: {
type: 'OAuth2',
user: SMTP_CONFIG.user,
clientId: SMTP_CONFIG.client_id,
clientSecret: SMTP_CONFIG.secret_key,
refreshToken: SMTP_CONFIG.refresh_token,
accessToken: accessToken
}
})
await transporter.sendMail({
subject: 'Verificação de acesso ao AppLinker',
from: 'Protheus Mobile' + `<${SMTP_CONFIG.user}>`,
to: `${email}`,
html: `<div>
<div
style="background:#4DBFBF;background-color:#4DBFBF;margin:0px auto;max-width:600px;"
>
<table
align="center"
border="0"
cellpadding="0"
cellspacing="0"
role="presentation"
style="background:#4DBFBF;background-color:#ffffff;width:100%;"
>
<tbody>
<tr>
<td
style="direction:ltr;font-size:0px;padding:20px 0;text-align:center;vertical-align:top;"
>
<div
class="dys-column-per-100 outlook-group-fix"
style="direction:ltr;display:inline-block;font-size:13px;text-align:left;vertical-align:top;width:100%;"
>
<table
border="0"
cellpadding="0"
cellspacing="0"
role="presentation"
style="vertical-align:top;"
width="100%"
>
<tr>
<td
align="center"
style="font-size:0px;padding:10px 25px;word-break:break-word;"
>
<div
style='color:#0c9abe;font-family:"Droid Sans", "Helvetica Neue", Arial, sans-serif;font-size:36px;line-height:1;text-align:center;'
>
Boas Vindas
</div>
</td>
</tr>
<tr>
<td
align="center"
style="font-size:0px;padding:10px 25px;word-break:break-word;"
>
<div
style='color:#586a6e;font-family:"Droid Sans", "Helvetica Neue", Arial, sans-serif;font-size:16px;line-height:20px;text-align:center;'
>
<br />
Para ativar sua conta no AppLinker clique no botão abaixo:
<br />
<br />
</div>
</td>
</tr>
<tr>
<td
align="center"
style="font-size:0px;padding:10px 25px;word-break:break-word;"
vertical-align="middle"
>
<table
border="0"
cellpadding="0"
cellspacing="0"
role="presentation"
style="border-collapse:separate;line-height:100%;width:200px;"
>
<tr>
<td
align="center"
bgcolor="#178F8F"
role="presentation"
style='background-color:#0c9abe; border:"solid 1px red";border-radius:4px;cursor:auto;padding:10px 25px;'
valign="middle"
>
<a
href="https://applinkerserver.applinker.engpro.totvs.com.br/auth/validate/${emailToken}"
style='background-color:#0c9abe; color:white;font-family:"Droid Sans", "Helvetica Neue", Arial, sans-serif;font-size:16px;font-weight:bold;line-height:30px;margin:0;text-decoration:none;text-transform:none;'
target="_blank"
>
Ativar
</a>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td
align="center"
style="font-size:0px;padding:10px 25px;word-break:break-word;"
>
<div
style=' color:#586a6e;font-family:"Droid Sans", "Helvetica Neue", Arial, sans-serif;font-size:12px;margin-top:10;text-decoration:none;text-transform:none;'
>
Para mais detalhes a respeito do uso da AppLinker <a href="https://tdn.totvs.com/x/KHbQHw">clique aqui!<a/>
</div>
</td>
</tr>
</table>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
>`
}).catch(error => {
console.log(error)
})
}
public async sentEmailToReset(req: Request, res: Response, next: any): Promise<void> {
try {
const email = req.body.user;
const emailToken = jwt.sign({ email }, config.masterKey);
const oauth2Client = new OAuth2(SMTP_CONFIG.client_id, SMTP_CONFIG.secret_key, SMTP_CONFIG.redirect_uri);
oauth2Client.setCredentials({
refresh_token: SMTP_CONFIG.refresh_token
})
const accessToken = await oauth2Client.getAccessToken().then((token) => {
return token.token;
})
const transporter = await nodemailer.createTransport({
host: SMTP_CONFIG.host,
port: SMTP_CONFIG.port,
secure: true,
auth: {
type: 'OAuth2',
user: SMTP_CONFIG.user,
clientId: SMTP_CONFIG.client_id,
clientSecret: SMTP_CONFIG.secret_key,
refreshToken: SMTP_CONFIG.refresh_token,
accessToken: accessToken
}
})
await transporter.sendMail({
subject: 'Verificação de acesso ao AppLinker',
from: 'Protheus Mobile' + `<${SMTP_CONFIG.user}>`,
to: `${email}`,
html: `<div>
<div
style="background:#4DBFBF;background-color:#4DBFBF;margin:0px auto;max-width:600px;"
>
<table
align="center"
border="0"
cellpadding="0"
cellspacing="0"
role="presentation"
style="background:#4DBFBF;background-color:#ffffff;width:100%;"
>
<tbody>
<tr>
<td
style="direction:ltr;font-size:0px;padding:20px 0;text-align:center;vertical-align:top;"
>
<div
class="dys-column-per-100 outlook-group-fix"
style="direction:ltr;display:inline-block;font-size:13px;text-align:left;vertical-align:top;width:100%;"
>
<table
border="0"
cellpadding="0"
cellspacing="0"
role="presentation"
style="vertical-align:top;"
width="100%"
>
<tr>
<td
align="center"
style="font-size:0px;padding:10px 25px;word-break:break-word;"
>
<div
style='color:#0c9abe;font-family:"Droid Sans", "Helvetica Neue", Arial, sans-serif;font-size:36px;line-height:1;text-align:center;'
>
Boas Vindas
</div>
</td>
</tr>
<tr>
<td
align="center"
style="font-size:0px;padding:10px 25px;word-break:break-word;"
>
<div
style='color:#586a6e;font-family:"Droid Sans", "Helvetica Neue", Arial, sans-serif;font-size:16px;line-height:20px;text-align:center;'
>
<br />
Para alterar a senha cadastrada no AppLinker clique no botão abaixo:
<br />
<br />
</div>
</td>
</tr>
<tr>
<td
align="center"
style="font-size:0px;padding:10px 25px;word-break:break-word;"
vertical-align="middle"
>
<table
border="0"
cellpadding="0"
cellspacing="0"
role="presentation"
style="border-collapse:separate;line-height:100%;width:200px;"
>
<tr>
<td
align="center"
bgcolor="#178F8F"
role="presentation"
style='background-color:#0c9abe; border:"solid 1px red";border-radius:4px;cursor:auto;padding:10px 25px;'
valign="middle"
>
<a
href="https://applinker.engpro.totvs.com.br/reset-password?token=${emailToken}"
style='background-color:#0c9abe; color:white;font-family:"Droid Sans", "Helvetica Neue", Arial, sans-serif;font-size:16px;font-weight:bold;line-height:30px;margin:0;text-decoration:none;text-transform:none;'
target="_blank"
>
Alterar Senha
</a>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td
align="center"
style="font-size:0px;padding:10px 25px;word-break:break-word;"
>
<div
style=' color:#586a6e;font-family:"Droid Sans", "Helvetica Neue", Arial, sans-serif;font-size:12px;margin-top:10;text-decoration:none;text-transform:none;'
>
Para mais detalhes a respeito do uso da AppLinker <a href="https://tdn.totvs.com/x/KHbQHw">clique aqui!<a/>
</div>
</td>
</tr>
</table>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>`
}).then(() => {
res.status(200).send({ message: 'Email enviado com sucesso.' });
}).catch(error => {
res.status(500).send({ message: 'Não foi possivel enviar o email.' })
})
} catch (err) {
console.log('aqui')
res.status(500).send({ error: err.name });
}
}
public async validate(req: Request, res: Response, next: any) {
const db = new ConfigDB();
try {
const conn = await db.connectDB();
const token = req.params.token;
if (token) {
jwt.verify(token, config.masterKey, async (err, decodedToken) => {
if (err) {
return res.status(400).json({ error: 'Incorrect token' });
}
const { email } = decodedToken;
let result = await conn.query("update tb_users set enable = true where email = $1 and enable = false", [email]);
return res.redirect('https://applinker.engpro.totvs.com.br/login?isActive=true')
})
} else {
res.status(500).send({ error: 'Invalid token' });
}
} catch (err) {
res.status(500).send({ error: err.name });
}
}
public async resetPassword(req: Request, res: Response, next: any) {
const db = new ConfigDB();
try {
const conn = await db.connectDB();
const token = req.body.token;
if (token) {
jwt.verify(token, config.masterKey, async (err, decodedToken) => {
if (err) {
return res.status(400).json({ error: 'Incorrect token' });
}
const { email } = decodedToken;
let result = await conn.query("update tb_users set password = md5($2) where email = $1", [email, req.body.password]);
if (result.rowCount > 0) {
res.status(200).send({ message: "Senha alterada com sucesso" });
} else {
res.status(403).send({ error: "Não foi possivel alterar a senha." });
}
})
} else {
res.status(500).send({ error: 'Invalid token' });
}
} catch (err) {
res.status(500).send({ error: err.name });
}
}
}
|
para: Bloco de código |
---|
language | js |
---|
theme | Midnight |
---|
firstline | 1 |
---|
title | AppLinkerServer/server/modules/auth/controller.ts |
---|
| import { ConfigDB } from './../database/config_db';
import { Request, Response } from 'express';
import * as jwt from 'jsonwebtoken';
import * as nodemailer from 'nodemailer';
import { google } from 'googleapis';
const SMTP_CONFIG = require('./../../config/env/smtp')
const config = require('../../config/env/')();
// declaracao do OAuth2
const OAuth2 = google.auth.OAuth2;
export class AuthController {
protected client;
protected adSuffix = "dc=local";
constructor() {}
public auth(req: Request, res: Response, next: any) {
this.authWithoutAD(req, res, next);
}
public async register(req: Request, res: Response, next: any) {
const db = new ConfigDB();
try {
const conn = await db.connectDB();
let result = await conn.query("select * from tb_users where email = $1 ", [req.body.user]);
if (result.rows.length > 0) {
return res.status(400).send({ error: "O email ja esta sendo utilizado." });
}
await conn.query("insert into tb_users (email, password,enable) values ($1, md5($2),false)", [req.body.user, req.body.password]).then(res => {
result = res
}).catch(error => {
console.log(error);
});
if (!result.err) {
res.send({
userEmail: req.body.user
});
await this.sentEmail(req.body.user)
} else {
res.status(400).send({ error: "Não foi possivel cadastrar" });
}
conn.end();
} catch (err) {
return res.status(500).send({ error: err.name });
}
}
public async authWithoutAD(req: Request, res: Response, next: any) {
const db = new ConfigDB();
try {
const conn = await db.connectDB();
let result = await conn.query("select email from tb_users where email = $1 and password = md5($2) and enable = true", [req.body.user, req.body.password]);
if (result.rowCount > 0) {
res.send({
user: req.body.user.split("@")[0],
userEmail: req.body.user,
token: jwt.sign({ user: req.body.user }, config.masterKey)
});
} else {
result = await conn.query("select email from tb_users where email = $1 and password = md5($2) and enable = false", [req.body.user, req.body.password]);
if (result.rowCount > 0) {
res.status(401).send({ error: "Usuário aguardando aprovação " });
} else {
res.status(403).send({ error: "Senha ou email incorretos " });
}
}
} catch (err) {
res.status(500).send({ error: err.name });
}
}
// Acrescentando OAuth2 Authentication
public async sentEmail(email: string): Promise<void> {
const emailToken = jwt.sign({ email }, config.masterKey);
const oauth2Client = new OAuth2(SMTP_CONFIG.client_id, SMTP_CONFIG.secret_key, SMTP_CONFIG.redirect_uri);
oauth2Client.setCredentials({
refresh_token: SMTP_CONFIG.refresh_token
})
const accessToken = await oauth2Client.getAccessToken().then((token) => {
return token.token;
})
const transporter = await nodemailer.createTransport({
host: SMTP_CONFIG.host,
port: SMTP_CONFIG.port,
secure: true,
auth: {
type: 'OAuth2',
user: SMTP_CONFIG.user,
clientId: SMTP_CONFIG.client_id,
clientSecret: SMTP_CONFIG.secret_key,
refreshToken: SMTP_CONFIG.refresh_token,
accessToken: accessToken
}
})
await transporter.sendMail({
subject: 'Verificação de acesso ao AppLinker',
from: 'Protheus Mobile' + `<${SMTP_CONFIG.user}>`,
to: `${email}`,
html: `<div>
<div
style="background:#4DBFBF;background-color:#4DBFBF;margin:0px auto;max-width:600px;"
>
<table
align="center"
border="0"
cellpadding="0"
cellspacing="0"
role="presentation"
style="background:#4DBFBF;background-color:#ffffff;width:100%;"
>
<tbody>
<tr>
<td
style="direction:ltr;font-size:0px;padding:20px 0;text-align:center;vertical-align:top;"
>
<div
class="dys-column-per-100 outlook-group-fix"
style="direction:ltr;display:inline-block;font-size:13px;text-align:left;vertical-align:top;width:100%;"
>
<table
border="0"
cellpadding="0"
cellspacing="0"
role="presentation"
style="vertical-align:top;"
width="100%"
>
<tr>
<td
align="center"
style="font-size:0px;padding:10px 25px;word-break:break-word;"
>
<div
style='color:#0c9abe;font-family:"Droid Sans", "Helvetica Neue", Arial, sans-serif;font-size:36px;line-height:1;text-align:center;'
>
Boas Vindas
</div>
</td>
</tr>
<tr>
<td
align="center"
style="font-size:0px;padding:10px 25px;word-break:break-word;"
>
<div
style='color:#586a6e;font-family:"Droid Sans", "Helvetica Neue", Arial, sans-serif;font-size:16px;line-height:20px;text-align:center;'
>
<br />
Para ativar sua conta no AppLinker clique no botão abaixo:
<br />
<br />
</div>
</td>
</tr>
<tr>
<td
align="center"
style="font-size:0px;padding:10px 25px;word-break:break-word;"
vertical-align="middle"
>
<table
border="0"
cellpadding="0"
cellspacing="0"
role="presentation"
style="border-collapse:separate;line-height:100%;width:200px;"
>
<tr>
<td
align="center"
bgcolor="#178F8F"
role="presentation"
style='background-color:#0c9abe; border:"solid 1px red";border-radius:4px;cursor:auto;padding:10px 25px;'
valign="middle"
>
<a
href="http://localhost:3000/auth/validate/${emailToken}"
style='background-color:#0c9abe; color:white;font-family:"Droid Sans", "Helvetica Neue", Arial, sans-serif;font-size:16px;font-weight:bold;line-height:30px;margin:0;text-decoration:none;text-transform:none;'
target="_blank"
>
Ativar
</a>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td
align="center"
style="font-size:0px;padding:10px 25px;word-break:break-word;"
>
<div
style=' color:#586a6e;font-family:"Droid Sans", "Helvetica Neue", Arial, sans-serif;font-size:12px;margin-top:10;text-decoration:none;text-transform:none;'
>
Para mais detalhes a respeito do uso da AppLinker <a href="https://tdn.totvs.com/x/KHbQHw">clique aqui!<a/>
</div>
</td>
</tr>
</table>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
>`
}).catch(error => {
console.log(error)
})
}
public async sentEmailToReset(req: Request, res: Response, next: any): Promise<void> {
try {
const email = req.body.user;
const emailToken = jwt.sign({ email }, config.masterKey);
const oauth2Client = new OAuth2(SMTP_CONFIG.client_id, SMTP_CONFIG.secret_key, SMTP_CONFIG.redirect_uri);
oauth2Client.setCredentials({
refresh_token: SMTP_CONFIG.refresh_token
})
const accessToken = await oauth2Client.getAccessToken().then((token) => {
return token.token;
})
const transporter = await nodemailer.createTransport({
host: SMTP_CONFIG.host,
port: SMTP_CONFIG.port,
secure: true,
auth: {
type: 'OAuth2',
user: SMTP_CONFIG.user,
clientId: SMTP_CONFIG.client_id,
clientSecret: SMTP_CONFIG.secret_key,
refreshToken: SMTP_CONFIG.refresh_token,
accessToken: accessToken
}
})
await transporter.sendMail({
subject: 'Verificação de acesso ao AppLinker',
from: 'Protheus Mobile' + `<${SMTP_CONFIG.user}>`,
to: `${email}`,
html: `<div>
<div
style="background:#4DBFBF;background-color:#4DBFBF;margin:0px auto;max-width:600px;"
>
<table
align="center"
border="0"
cellpadding="0"
cellspacing="0"
role="presentation"
style="background:#4DBFBF;background-color:#ffffff;width:100%;"
>
<tbody>
<tr>
<td
style="direction:ltr;font-size:0px;padding:20px 0;text-align:center;vertical-align:top;"
>
<div
class="dys-column-per-100 outlook-group-fix"
style="direction:ltr;display:inline-block;font-size:13px;text-align:left;vertical-align:top;width:100%;"
>
<table
border="0"
cellpadding="0"
cellspacing="0"
role="presentation"
style="vertical-align:top;"
width="100%"
>
<tr>
<td
align="center"
style="font-size:0px;padding:10px 25px;word-break:break-word;"
>
<div
style='color:#0c9abe;font-family:"Droid Sans", "Helvetica Neue", Arial, sans-serif;font-size:36px;line-height:1;text-align:center;'
>
Boas Vindas
</div>
</td>
</tr>
<tr>
<td
align="center"
style="font-size:0px;padding:10px 25px;word-break:break-word;"
>
<div
style='color:#586a6e;font-family:"Droid Sans", "Helvetica Neue", Arial, sans-serif;font-size:16px;line-height:20px;text-align:center;'
>
<br />
Para alterar a senha cadastrada no AppLinker clique no botão abaixo:
<br />
<br />
</div>
</td>
</tr>
<tr>
<td
align="center"
style="font-size:0px;padding:10px 25px;word-break:break-word;"
vertical-align="middle"
>
<table
border="0"
cellpadding="0"
cellspacing="0"
role="presentation"
style="border-collapse:separate;line-height:100%;width:200px;"
>
<tr>
<td
align="center"
bgcolor="#178F8F"
role="presentation"
style='background-color:#0c9abe; border:"solid 1px red";border-radius:4px;cursor:auto;padding:10px 25px;'
valign="middle"
>
<a
href="http://localhost:3000/reset-password?token=${emailToken}"
style='background-color:#0c9abe; color:white;font-family:"Droid Sans", "Helvetica Neue", Arial, sans-serif;font-size:16px;font-weight:bold;line-height:30px;margin:0;text-decoration:none;text-transform:none;'
target="_blank"
>
Alterar Senha
</a>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td
align="center"
style="font-size:0px;padding:10px 25px;word-break:break-word;"
>
<div
style=' color:#586a6e;font-family:"Droid Sans", "Helvetica Neue", Arial, sans-serif;font-size:12px;margin-top:10;text-decoration:none;text-transform:none;'
>
Para mais detalhes a respeito do uso da AppLinker <a href="https://tdn.totvs.com/x/KHbQHw">clique aqui!<a/>
</div>
</td>
</tr>
</table>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>`
}).then(() => {
res.status(200).send({ message: 'Email enviado com sucesso.' });
}).catch(error => {
res.status(500).send({ message: 'Não foi possivel enviar o email.' })
})
} catch (err) {
res.status(500).send({ error: err.name });
}
}
public async validate(req: Request, res: Response, next: any) {
const db = new ConfigDB();
try {
const conn = await db.connectDB();
const token = req.params.token;
if (token) {
jwt.verify(token, config.masterKey, async (err, decodedToken) => {
if (err) {
return res.status(400).json({ error: 'Incorrect token' });
}
const { email } = decodedToken;
let result = await conn.query("update tb_users set enable = true where email = $1 and enable = false", [email]);
return res.redirect('http://localhost:4200/login?isActive=true')
})
} else {
res.status(500).send({ error: 'Invalid token' });
}
} catch (err) {
res.status(500).send({ error: err.name });
}
}
public async resetPassword(req: Request, res: Response, next: any) {
const db = new ConfigDB();
try {
const conn = await db.connectDB();
const token = req.body.token;
if (token) {
jwt.verify(token, config.masterKey, async (err, decodedToken) => {
if (err) {
return res.status(400).json({ error: 'Incorrect token' });
}
const { email } = decodedToken;
let result = await conn.query("update tb_users set password = md5($2) where email = $1", [email, req.body.password]);
if (result.rowCount > 0) {
res.status(200).send({ message: "Senha alterada com sucesso" });
} else {
res.status(403).send({ error: "Não foi possivel alterar a senha." });
}
})
} else {
res.status(500).send({ error: 'Invalid token' });
}
} catch (err) {
res.status(500).send({ error: err.name });
}
}
} |
|
|
|
Card |
---|
effectDuration | 0.5 |
---|
id | banco-dados |
---|
label | Banco de Dados |
---|
title | Banco de Dados |
---|
| Deck of Cards |
---|
| Card |
---|
effectDuration | 0.5 |
---|
id | crie-server |
---|
label | Crie um Server |
---|
title | Crie um Server |
---|
| Criando o DataBasePara criar um Banco de Dados clique com o botão direito em "Databases" e depois em "Create". De o nome de "applinker" e clique em "Save". Painel |
---|
| Image Removed |
|
Card |
---|
id | tabela |
---|
label | Tabela |
---|
title | Tabela |
---|
| Criando a TabelaPara criar uma tabela no Banco de Dados clique com o botão direito em "Tables" e depois em "Query Tool". Com o editor de querys aberto execute o script. Bloco de código |
---|
language | sql |
---|
theme | Confluence |
---|
firstline | 1 |
---|
title | Ambiente Local |
---|
| CREATE TABLE public.tb_users
(
id serial NOT NULL,
email character varying(50) COLLATE pg_catalog."default" NOT NULL,
password character varying(50) COLLATE pg_catalog."default",
enable boolean,
register text COLLATE pg_catalog."default" DEFAULT now()
) |
Segue a baixo uma representação: Painel |
---|
| Image Removed |
|
|
|
|
|