Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
bajinho committed Dec 27, 2024
1 parent a00295d commit 40ecd0c
Show file tree
Hide file tree
Showing 43 changed files with 8,134 additions and 0 deletions.
9 changes: 9 additions & 0 deletions .env.production
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
NODE_ENV=production
DB_CONNECTION=
DB_HOST=
DB_PORT=3306
DB_DATABASE=
DB_USERNAME=
DB_PASSWORD=

JWT_SECRET=
16 changes: 16 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"env": {
"browser": true,
"es6": true
},
"extends": ["airbnb-base"],
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parserOptions": {
"ecmaVersion": 2018,
"sourceType": "module"
},
"rules": {}
}
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
node_modules
dbnodejs
.env.development
/config/*
.sequelizerc
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
16.20.2
31 changes: 31 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
version: "3.2"

services:
mariadbnodejs:
image: mariadb:latest
container_name: mariadbnodejs
restart: always
environment:
MYSQL_ROOT_PASSWORD: mysecret
MYSQL_DATABASE: default_schema
MYSQL_USER: mysql
MYSQL_PASSWORD: mysql
ports:
- "3306:3306"
volumes:
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
- ./dbnodejs/mysql/data/:/var/lib/mysql/ # data storage
networks:
- default

volumes:
dbnodejs:
driver: local
driver_opts:
type: disk
size: 5GB
device: ""

networks:
default:
driver: bridge
26 changes: 26 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import express from "express";
import sequelize from "./src/db";
import expressIP from "express-ip";
import dotenv from "dotenv";
import { Private, Public } from "./src/routes";

const app = express();

sequelize
.authenticate()
.then(() => {
console.log("Connection has been established successfully.");
})
.catch((err) => {
console.error("Unable to connect to the database:", err);
});

app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(expressIP().getIpInfoMiddleware);

app.use(Public);
app.use(Private);

app.set("PORT", 8089);
app.listen(app.get("PORT"));
37 changes: 37 additions & 0 deletions init.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
-- MySQL Script generated by MySQL Workbench
-- ter 24 dez 2024 19:53:13
-- Model: New Model Version: 1.0
-- MySQL Workbench Forward Engineering
-- -----------------------------------------------------
-- Schema default_schema
-- -----------------------------------------------------
CREATE SCHEMA IF NOT EXISTS `default_schema`;

USE `default_schema`;

-- -----------------------------------------------------
-- Table `default_schema`.`tb_usuarios`
-- -----------------------------------------------------
CREATE TABLE
IF NOT EXISTS `default_schema`.`tb_usuarios` (
`usuario_id` INT (11) NOT NULL AUTO_INCREMENT,
`usuario_nome` VARCHAR(45) NOT NULL,
`usuario_email` VARCHAR(240) NOT NULL,
`usuario_senha` VARCHAR(256) NOT NULL,
`createdAt` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
-- Correção aqui: sem parênteses
`updatedAt` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`usuario_id`)
) ENGINE = InnoDB;

-- -----------------------------------------------------
-- Table `default_schema`.`tb_token_blacklist`
-- -----------------------------------------------------
CREATE TABLE
IF NOT EXISTS `default_schema`.`tb_token_blacklist` (
`tokenblacklist_id` INT (11) NOT NULL,
`token` VARCHAR(512) NOT NULL,
`createdAt` DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
`updatedAt` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`tokenblacklist_id`)
) ENGINE = InnoDB;
35 changes: 35 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"name": "authentication",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"scripts": {
"dev": "NODE_ENV=development nodemon -r esm index.js",
"start": "NODE_ENV=production node -r esm index.js",
"format": "prettier --write \"src/**/*.js\"",
"docker": "docker-compose -f stack.yml up"
},
"dependencies": {
"authenticator": "^1.1.5",
"axios": "^0.19.0",
"bcrypt": "^3.0.6",
"cloudinary": "^1.15.0",
"date-period": "^2.5.0",
"express": "^4.17.1",
"express-ip": "^1.0.3",
"jsonwebtoken": "^8.5.1",
"moment": "^2.24.0",
"mysql2": "^1.7.0",
"prettier": "^3.3.2",
"read-markdown": "^1.0.2",
"sequelize": "^5.19.0",
"validator": "^11.1.0"
},
"devDependencies": {
"dotenv": "^8.1.0",
"eslint": "^6.4.0",
"eslint-config-airbnb-base": "^14.0.0",
"esm": "^3.2.25",
"nodemon": "^1.19.2"
}
}
11 changes: 11 additions & 0 deletions src/db/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import Sequelize from "sequelize";
import dotenv from "dotenv";

dotenv.config({ path: `.env.${process.env.NODE_ENV || 'development'}` });

// Configuração de acesso ao bando de dados
const sequelize = new Sequelize(
`mysql://${process.env.DB_USERNAME}:${process.env.DB_PASSWORD}@${process.env.DB_HOST}:${process.env.DB_PORT}/${process.env.DB_DATABASE}`
);

export default sequelize;
2 changes: 2 additions & 0 deletions src/db/model/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default as User } from "./user";
export { default as TokenBlacklist } from "./tokenBlacklist";
26 changes: 26 additions & 0 deletions src/db/model/tokenBlacklist.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import Sequelize from "sequelize";
import sequelize from "..";

const Model = Sequelize.Model;
class TokenBlacklist extends Model { }

TokenBlacklist.init(
{
// acess colums

tokenblacklist_id: {
type: Sequelize.INTEGER,
primaryKey: true,
},
token: { type: Sequelize.STRING },
},
{
sequelize,
modelName: "tb_token_blacklist",
freezeTableName: true,
timestamps: false,
// options
},
);

export default TokenBlacklist;
26 changes: 26 additions & 0 deletions src/db/model/user.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import Sequelize from "sequelize";
import sequelize from "..";

const Model = Sequelize.Model;
class User extends Model { }
User.init(
{
// acess colums
usuario_id: {
type: Sequelize.INTEGER,
primaryKey: true,
},
usuario_senha: { type: Sequelize.STRING },
usuario_email: { type: Sequelize.STRING },
usuario_nome: { type: Sequelize.STRING },
},
{
sequelize,
modelName: "tb_usuarios",
freezeTableName: true,
timestamps: false,
// options
},
);

export default User;
2 changes: 2 additions & 0 deletions src/routes/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default as Private } from "./private";
export { default as Public } from "./public";
9 changes: 9 additions & 0 deletions src/routes/private/api/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import express from "express";

import Profile from "./profile";

const router = express.Router();

router.use(Profile);

export default router;
18 changes: 18 additions & 0 deletions src/routes/private/api/profile/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import express from "express";

import { GenerateToken, Validation } from "./security";
import { Info } from "./info";
import { Password } from "./update";

const { Auth, Pin } = Validation;

const router = express.Router();

router.post("/api/profile/info", Info);
router.post("/api/profile/update/password", Password);

router.post("/api/profile/security/generateToken", GenerateToken);
router.post("/api/profile/security/validation/pin", Pin);
router.post("/api/profile/security/validation/auth", Auth);

export default router;
3 changes: 3 additions & 0 deletions src/routes/private/api/profile/info/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default (req, res) => {
res.sendFile(path.join(__dirname, '/', 'index.html'));
};
20 changes: 20 additions & 0 deletions src/routes/private/api/profile/security/generateToken.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Password } from "../../../../../security";
import Authenticator from "authenticator";

export default async (req, res) => {
try {
const Auth_Secret = Authenticator.generateToken();
//Não entendi o motivo de "testar o serviço" voltando pro cliente, então deixei só isso.
res.send({
Auth_Secret,
definePageSelection: "security",
});
} catch (err) {
res.send({
code: 0,
message:
"Alguma coisa deu errado. Entre em contato com os administradores",
error: err.message,
});
}
};
4 changes: 4 additions & 0 deletions src/routes/private/api/profile/security/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import * as validation from "./validation";

export const Validation = validation;
export { default as GenerateToken } from "./generateToken";
38 changes: 38 additions & 0 deletions src/routes/private/api/profile/security/validation/auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import Authenticator from "authenticator";

export default async (req, res) => {
try {
const { user, body } = req;
const { auth_code, auth_pin: authPin } = body;

if (!auth_code || !authPin)
return res.send({
code: 0,
message: "Envie o código e o pin.",
});

const authCode = new Buffer(auth_code, "base64");

const verified = Authenticator.verifyToken(authCode, authPin);

if (!verified)
return res.send({
code: 0,
message: "Código inválido.",
});

await user.update({ usuario_pin_auth: auth_code });

res.send({
code: 1,
message: "Validado com sucesso",
});
} catch (err) {
res.send({
code: 0,
message:
"Alguma coisa deu errado. Entre em contato com os administradores",
error: err.message,
});
}
};
2 changes: 2 additions & 0 deletions src/routes/private/api/profile/security/validation/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default as Auth } from "./auth";
export { default as Pin } from "./pin";
51 changes: 51 additions & 0 deletions src/routes/private/api/profile/security/validation/pin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import Authenticator from "authenticator";
import readMarkdown from "read-markdown";
import sgMail from "@sendgrid/mail";
import { Password } from "../../../../../../security";

const API_KEY = process.env.API_KEY;

sgMail.setApiKey(API_KEY);

export default async (req, res) => {
try {
const { user, body } = req;
const { pin_code } = body;

if (!pin_code)
return res.send({
code: 0,
message: "Envie o pin.",
});

const pinCode = Password.hash(pin_code);

await user.update({ usuario_pin: pinCode });

const Markdown = await readMarkdown("./resources/email-example.md");

//TODO: Talvez criar um "transactional template" seja melhor que o Markdown
await sgMail.send({
// FIXME: não encontrei nada na documentação sobre fromName nem toName
// fromName: "SISTEMA SUPORTE",
// toName: user.usuario_nome,
to: user.usuario_email,
from: "email@example.com",
subject: "PIN DE SEGURANÇA",
text: "Seu código de recuperação do e-mail",
html: Markdown.replace("%token%", pinCode),
});

res.send({
code: 1,
message: "Validado com sucesso",
});
} catch (err) {
res.send({
code: 0,
message:
"Alguma coisa deu errado. Entre em contato com os administradores",
error: err.message,
});
}
};
Loading

0 comments on commit 40ecd0c

Please sign in to comment.