|
|
@@ -1,8 +1,32 @@
|
|
|
import bcrypt from "bcryptjs";
|
|
|
+import { z } from "zod";
|
|
|
import { db } from "../db/knex.js";
|
|
|
import { signAccessToken, generateRefreshToken, hashRefreshToken } from "../services/authTokens.js";
|
|
|
import { config } from "../config/index.js";
|
|
|
|
|
|
+const criarSchema = z.object({
|
|
|
+ Nome: z.string().min(1).max(100),
|
|
|
+ Login: z.string().min(3).max(50),
|
|
|
+ Email: z.string().email().max(150),
|
|
|
+ Senha: z.string().min(6).max(128),
|
|
|
+ Nivel: z.enum(["1", "2", "3"]),
|
|
|
+ Setor: z.string().min(1).max(100)
|
|
|
+});
|
|
|
+
|
|
|
+const atualizarSchema = z.object({
|
|
|
+ Nome: z.string().min(1).max(100).optional(),
|
|
|
+ Email: z.string().email().max(150).optional(),
|
|
|
+ Nivel: z.enum(["1", "2", "3"]).optional(),
|
|
|
+ Setor: z.string().min(1).max(100).optional()
|
|
|
+}).refine(obj => Object.values(obj).some(v => v !== undefined), {
|
|
|
+ message: "Nenhum campo para atualizar"
|
|
|
+});
|
|
|
+
|
|
|
+const senhaSchema = z.object({
|
|
|
+ senhaAtual: z.string().min(1),
|
|
|
+ senhaNova: z.string().min(6).max(128)
|
|
|
+});
|
|
|
+
|
|
|
const _failedAttempts = new Map();
|
|
|
const MAX_ATTEMPTS = 5;
|
|
|
const BLOCK_MS = 15 * 60 * 1000;
|
|
|
@@ -178,31 +202,23 @@ export const UsuarioController = {
|
|
|
Criar: async function (req, res, next) {
|
|
|
if (!requireAdmin(req, res)) return;
|
|
|
try {
|
|
|
- const { Nome, Login, Email, Senha, Nivel, Setor } = req.body ?? {};
|
|
|
-
|
|
|
- if (!Nome || !Login || !Email || !Senha || !Nivel || !Setor) {
|
|
|
- return res.status(400).send({ status: false, msg: "Todos os campos são obrigatórios!" });
|
|
|
- }
|
|
|
-
|
|
|
- if (String(Senha).length < 6) {
|
|
|
- return res.status(400).send({ status: false, msg: "Senha deve ter pelo menos 6 caracteres!" });
|
|
|
- }
|
|
|
+ const { Nome, Login, Email, Senha, Nivel, Setor } = criarSchema.parse(req.body ?? {});
|
|
|
|
|
|
- const loginTrimado = String(Login).trim();
|
|
|
+ const loginTrimado = Login.trim();
|
|
|
const existente = await db("usuarios").where({ Login: loginTrimado }).first();
|
|
|
if (existente) {
|
|
|
return res.status(409).send({ status: false, msg: "Login já cadastrado!" });
|
|
|
}
|
|
|
|
|
|
- const senhaHash = await bcrypt.hash(String(Senha), 10);
|
|
|
+ const senhaHash = await bcrypt.hash(Senha, 10);
|
|
|
const [id] = await db("usuarios").insert({
|
|
|
- Nome: String(Nome).trim(),
|
|
|
+ Nome: Nome.trim(),
|
|
|
Login: loginTrimado,
|
|
|
- Email: String(Email).trim(),
|
|
|
+ Email: Email.trim(),
|
|
|
Senha: senhaHash,
|
|
|
Status: "1",
|
|
|
- Nivel: String(Nivel),
|
|
|
- Setor: String(Setor).trim()
|
|
|
+ Nivel,
|
|
|
+ Setor: Setor.trim()
|
|
|
});
|
|
|
|
|
|
const usuario = await db("usuarios").where({ Id: id }).first();
|
|
|
@@ -218,16 +234,12 @@ export const UsuarioController = {
|
|
|
const id = Number(req.params.id);
|
|
|
if (!id) return res.status(400).send({ status: false, msg: "ID inválido!" });
|
|
|
|
|
|
- const { Nome, Email, Nivel, Setor } = req.body ?? {};
|
|
|
+ const { Nome, Email, Nivel, Setor } = atualizarSchema.parse(req.body ?? {});
|
|
|
const updates = {};
|
|
|
- if (Nome) updates.Nome = String(Nome).trim();
|
|
|
- if (Email) updates.Email = String(Email).trim();
|
|
|
- if (Nivel !== undefined) updates.Nivel = String(Nivel);
|
|
|
- if (Setor) updates.Setor = String(Setor).trim();
|
|
|
-
|
|
|
- if (Object.keys(updates).length === 0) {
|
|
|
- return res.status(400).send({ status: false, msg: "Nenhum campo para atualizar!" });
|
|
|
- }
|
|
|
+ if (Nome !== undefined) updates.Nome = Nome.trim();
|
|
|
+ if (Email !== undefined) updates.Email = Email.trim();
|
|
|
+ if (Nivel !== undefined) updates.Nivel = Nivel;
|
|
|
+ if (Setor !== undefined) updates.Setor = Setor.trim();
|
|
|
|
|
|
await db("usuarios").where({ Id: id }).update(updates);
|
|
|
const usuario = await db("usuarios").where({ Id: id }).first();
|
|
|
@@ -262,24 +274,17 @@ export const UsuarioController = {
|
|
|
const id = Number(req.params.id);
|
|
|
if (!id) return res.status(400).send({ status: false, msg: "ID inválido!" });
|
|
|
|
|
|
- const { senhaAtual, senhaNova } = req.body ?? {};
|
|
|
- if (!senhaAtual || !senhaNova) {
|
|
|
- return res.status(400).send({ status: false, msg: "Senhas obrigatórias!" });
|
|
|
- }
|
|
|
+ const { senhaAtual, senhaNova } = senhaSchema.parse(req.body ?? {});
|
|
|
|
|
|
const usuario = await db("usuarios").where({ Id: id }).first();
|
|
|
if (!usuario) return res.status(404).send({ status: false, msg: "Usuário não encontrado!" });
|
|
|
|
|
|
- const senhaValida = bcrypt.compareSync(String(senhaAtual), String(usuario.Senha ?? ""));
|
|
|
+ const senhaValida = bcrypt.compareSync(senhaAtual, String(usuario.Senha ?? ""));
|
|
|
if (!senhaValida) {
|
|
|
return res.status(401).send({ status: false, msg: "Senha atual incorreta!" });
|
|
|
}
|
|
|
|
|
|
- if (String(senhaNova).length < 6) {
|
|
|
- return res.status(400).send({ status: false, msg: "Nova senha deve ter pelo menos 6 caracteres!" });
|
|
|
- }
|
|
|
-
|
|
|
- const novaHash = bcrypt.hashSync(String(senhaNova), 10);
|
|
|
+ const novaHash = bcrypt.hashSync(senhaNova, 10);
|
|
|
await db("usuarios").where({ Id: id }).update({ Senha: novaHash });
|
|
|
|
|
|
return res.status(200).send({ status: true, msg: "Senha alterada com sucesso!" });
|