feat: implement advanced access control system with user blocking, rate limiting, and enhanced login security; update UI components for improved user experience and documentation
This commit is contained in:
210
packages/backend/convex/migrarUsuariosAdmin.ts
Normal file
210
packages/backend/convex/migrarUsuariosAdmin.ts
Normal file
@@ -0,0 +1,210 @@
|
||||
import { internalMutation, query } from "./_generated/server";
|
||||
import { v } from "convex/values";
|
||||
|
||||
/**
|
||||
* Listar usuários usando o perfil "admin" antigo (nível 0)
|
||||
*/
|
||||
export const listarUsuariosAdminAntigo = query({
|
||||
args: {},
|
||||
returns: v.array(
|
||||
v.object({
|
||||
_id: v.id("usuarios"),
|
||||
matricula: v.string(),
|
||||
nome: v.string(),
|
||||
email: v.string(),
|
||||
roleId: v.id("roles"),
|
||||
roleNome: v.string(),
|
||||
roleNivel: v.number(),
|
||||
})
|
||||
),
|
||||
handler: async (ctx) => {
|
||||
// Buscar todos os perfis "admin"
|
||||
const allAdmins = await ctx.db
|
||||
.query("roles")
|
||||
.filter((q) => q.eq(q.field("nome"), "admin"))
|
||||
.collect();
|
||||
|
||||
console.log("Perfis 'admin' encontrados:", allAdmins.length);
|
||||
|
||||
// Identificar o admin antigo (nível 0)
|
||||
const adminAntigo = allAdmins.find((r) => r.nivel === 0);
|
||||
|
||||
if (!adminAntigo) {
|
||||
console.log("Nenhum admin antigo (nível 0) encontrado");
|
||||
return [];
|
||||
}
|
||||
|
||||
console.log("Admin antigo encontrado:", adminAntigo);
|
||||
|
||||
// Buscar usuários usando este perfil
|
||||
const usuarios = await ctx.db
|
||||
.query("usuarios")
|
||||
.withIndex("by_role", (q) => q.eq("roleId", adminAntigo._id))
|
||||
.collect();
|
||||
|
||||
console.log("Usuários usando admin antigo:", usuarios.length);
|
||||
|
||||
return usuarios.map((u) => ({
|
||||
_id: u._id,
|
||||
matricula: u.matricula,
|
||||
nome: u.nome,
|
||||
email: u.email || "",
|
||||
roleId: u.roleId,
|
||||
roleNome: adminAntigo.nome,
|
||||
roleNivel: adminAntigo.nivel,
|
||||
}));
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Migrar usuários do perfil "admin" antigo (nível 0) para o novo (nível 2)
|
||||
*/
|
||||
export const migrarUsuariosParaAdminNovo = internalMutation({
|
||||
args: {},
|
||||
returns: v.object({
|
||||
migrados: v.number(),
|
||||
usuariosMigrados: v.array(
|
||||
v.object({
|
||||
matricula: v.string(),
|
||||
nome: v.string(),
|
||||
roleAntigo: v.string(),
|
||||
roleNovo: v.string(),
|
||||
})
|
||||
),
|
||||
}),
|
||||
handler: async (ctx) => {
|
||||
// Buscar todos os perfis "admin"
|
||||
const allAdmins = await ctx.db
|
||||
.query("roles")
|
||||
.filter((q) => q.eq(q.field("nome"), "admin"))
|
||||
.collect();
|
||||
|
||||
// Identificar admin antigo (nível 0) e admin novo (nível 2)
|
||||
const adminAntigo = allAdmins.find((r) => r.nivel === 0);
|
||||
const adminNovo = allAdmins.find((r) => r.nivel === 2);
|
||||
|
||||
if (!adminAntigo) {
|
||||
console.log("❌ Admin antigo (nível 0) não encontrado");
|
||||
return { migrados: 0, usuariosMigrados: [] };
|
||||
}
|
||||
|
||||
if (!adminNovo) {
|
||||
console.log("❌ Admin novo (nível 2) não encontrado");
|
||||
return { migrados: 0, usuariosMigrados: [] };
|
||||
}
|
||||
|
||||
console.log("✅ Admin antigo ID:", adminAntigo._id, "- Nível:", adminAntigo.nivel);
|
||||
console.log("✅ Admin novo ID:", adminNovo._id, "- Nível:", adminNovo.nivel);
|
||||
|
||||
// Buscar usuários usando o admin antigo
|
||||
const usuarios = await ctx.db
|
||||
.query("usuarios")
|
||||
.withIndex("by_role", (q) => q.eq("roleId", adminAntigo._id))
|
||||
.collect();
|
||||
|
||||
console.log(`📊 Encontrados ${usuarios.length} usuário(s) para migrar`);
|
||||
|
||||
const usuariosMigrados: Array<{
|
||||
matricula: string;
|
||||
nome: string;
|
||||
roleAntigo: string;
|
||||
roleNovo: string;
|
||||
}> = [];
|
||||
|
||||
// Migrar cada usuário
|
||||
for (const usuario of usuarios) {
|
||||
await ctx.db.patch(usuario._id, {
|
||||
roleId: adminNovo._id,
|
||||
});
|
||||
|
||||
usuariosMigrados.push({
|
||||
matricula: usuario.matricula,
|
||||
nome: usuario.nome,
|
||||
roleAntigo: `admin (nível 0) - ${adminAntigo._id}`,
|
||||
roleNovo: `admin (nível 2) - ${adminNovo._id}`,
|
||||
});
|
||||
|
||||
console.log(
|
||||
`✅ MIGRADO: ${usuario.nome} (${usuario.matricula}) → admin nível 2`
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
migrados: usuarios.length,
|
||||
usuariosMigrados,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Remover perfil "admin" antigo (nível 0) após migração
|
||||
*/
|
||||
export const removerAdminAntigo = internalMutation({
|
||||
args: {},
|
||||
returns: v.object({
|
||||
sucesso: v.boolean(),
|
||||
mensagem: v.string(),
|
||||
}),
|
||||
handler: async (ctx) => {
|
||||
// Buscar todos os perfis "admin"
|
||||
const allAdmins = await ctx.db
|
||||
.query("roles")
|
||||
.filter((q) => q.eq(q.field("nome"), "admin"))
|
||||
.collect();
|
||||
|
||||
// Identificar admin antigo (nível 0)
|
||||
const adminAntigo = allAdmins.find((r) => r.nivel === 0);
|
||||
|
||||
if (!adminAntigo) {
|
||||
return {
|
||||
sucesso: false,
|
||||
mensagem: "Admin antigo (nível 0) não encontrado",
|
||||
};
|
||||
}
|
||||
|
||||
// Verificar se ainda há usuários usando
|
||||
const usuarios = await ctx.db
|
||||
.query("usuarios")
|
||||
.withIndex("by_role", (q) => q.eq("roleId", adminAntigo._id))
|
||||
.collect();
|
||||
|
||||
if (usuarios.length > 0) {
|
||||
return {
|
||||
sucesso: false,
|
||||
mensagem: `Ainda há ${usuarios.length} usuário(s) usando este perfil. Execute migrarUsuariosParaAdminNovo primeiro.`,
|
||||
};
|
||||
}
|
||||
|
||||
// Remover permissões associadas
|
||||
const permissoes = await ctx.db
|
||||
.query("rolePermissoes")
|
||||
.withIndex("by_role", (q) => q.eq("roleId", adminAntigo._id))
|
||||
.collect();
|
||||
for (const perm of permissoes) {
|
||||
await ctx.db.delete(perm._id);
|
||||
}
|
||||
|
||||
// Remover menu permissões associadas
|
||||
const menuPerms = await ctx.db
|
||||
.query("menuPermissoes")
|
||||
.withIndex("by_role", (q) => q.eq("roleId", adminAntigo._id))
|
||||
.collect();
|
||||
for (const menuPerm of menuPerms) {
|
||||
await ctx.db.delete(menuPerm._id);
|
||||
}
|
||||
|
||||
// Remover o perfil
|
||||
await ctx.db.delete(adminAntigo._id);
|
||||
|
||||
console.log(
|
||||
`🗑️ REMOVIDO: Admin antigo (nível 0) - ${adminAntigo._id}`
|
||||
);
|
||||
|
||||
return {
|
||||
sucesso: true,
|
||||
mensagem: "Admin antigo removido com sucesso",
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user