mirror of
https://github.com/melgarafael/DeskcommCRM.git
synced 2026-10-02 09:34:46 +08:00
fix(admin): extensão removida deixa de aparecer como instalada
Remoção de extensão é soft delete: `extension_installations.removed_at` ganha data e a linha fica. A tela de `/admin/extensoes` lia a tabela inteira, então uma extensão já removida continuava listada como instalada, com a contagem de empresas dela junto. A irmã de produção (`lib/extensions/service.ts`) filtra no banco; esta passa a filtrar igual. É a única leitora de `extension_installations` fora do service. O filtro vira cerca: o caso novo em `tests/unit/extensoes-da-instalacao-conta-sem-nomear.test.ts` recorta a consulta das instaladas e exige o `removed_at`. Sabotado nesta branch: sem a linha, `Tests 1 failed | 2 passed`; com ela, `Tests 3 passed`. Resgatado de 0e2abb08e (wt-1380), que ficou fora do merge do #1380. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N9fyW7pXJCsyDPtu5PoQpN
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
5b3186aa36
commit
db5dfc57fd
@@ -0,0 +1,7 @@
|
||||
---
|
||||
impacto: nada_mudou
|
||||
secao: corrigido
|
||||
titulo: Extensão removida deixa de aparecer como instalada no painel do dono do servidor
|
||||
---
|
||||
|
||||
Remover uma extensão marca a instalação como removida, mas a linha continua no banco. A tela `/admin/extensoes` lia todas as linhas, então uma extensão já removida seguia listada como instalada, junto com a contagem de empresas dela. Agora a tela ignora as instalações removidas, do mesmo jeito que o restante do sistema de extensões já fazia.
|
||||
@@ -52,9 +52,14 @@ export default async function Page() {
|
||||
const db = createAdminClient();
|
||||
const [catalogos, instalacoes, vinculos] = await Promise.all([
|
||||
db.from("extension_catalogs").select("id,origin,revision,digest,admitted_at").order("admitted_at", { ascending: false }),
|
||||
// Remoção aqui é soft delete: a linha fica, com `removed_at` preenchido. Sem
|
||||
// este filtro a tela chamaria de "instalada" uma extensão que o operador já
|
||||
// removeu — e contaria os vínculos dela junto. A irmã de produção
|
||||
// (`lib/extensions/service.ts`) filtra no banco pelo mesmo motivo.
|
||||
db
|
||||
.from("extension_installations")
|
||||
.select("id,publisher,name,version,installed_at")
|
||||
.is("removed_at", null)
|
||||
.order("installed_at", { ascending: false }),
|
||||
db.from("organization_extensions").select("installation_id,enabled"),
|
||||
]);
|
||||
|
||||
@@ -39,6 +39,20 @@ describe("a tela de extensões da instalação", () => {
|
||||
).toEqual(["installation_id", "enabled"]);
|
||||
});
|
||||
|
||||
it("não chama de instalada a extensão que o operador já removeu", () => {
|
||||
// Remoção é soft delete (`extension_installations.removed_at`), então a linha
|
||||
// continua lá. Uma tela que não filtra mostra a removida como instalada e conta
|
||||
// os vínculos dela — e o erro é invisível justamente para quem removeu.
|
||||
const inicio = semProsa.indexOf('from("extension_installations")');
|
||||
expect(inicio, `nenhuma leitura de extension_installations em ${TELA}`).toBeGreaterThan(-1);
|
||||
const proxima = semProsa.indexOf('.from("', inicio + 1);
|
||||
const consulta = semProsa.slice(inicio, proxima === -1 ? undefined : proxima);
|
||||
expect(
|
||||
consulta,
|
||||
"a consulta das instaladas não filtra `removed_at`. Ver o cabeçalho deste caso.",
|
||||
).toContain('.is("removed_at", null)');
|
||||
});
|
||||
|
||||
it("a varredura ENCONTRA o select — um regex quebrado passaria por vacuidade", () => {
|
||||
// Sem este caso, renomear a tabela ou trocar as aspas deixaria o caso acima
|
||||
// verde sobre um conjunto vazio, que é o modo silencioso de uma cerca morrer.
|
||||
|
||||
Reference in New Issue
Block a user