Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reverter ganhos de TabCoins em conteúdos pegos pelo firewall interno e outros ajustes #1638

Open
wants to merge 9 commits into
base: main
Choose a base branch
from

Conversation

Rafatcb
Copy link
Collaborator

@Rafatcb Rafatcb commented Feb 26, 2024

Mudanças realizadas

Mudança nas mensagens de erro

As mensagens de erro passaram a informar que algumas ações podem ter sido desfeitas.

Antes Depois
Você está tentando criar muitos usuários. Você está tentando criar muitos usuários, então usuários criados recentemente podem ter sido desabilitados.
Você está tentando criar muitos conteúdos na raiz do site. Você está tentando criar muitas publicações, então publicações criadas recentemente podem ter sido removidas.
Você está tentando criar muitas respostas. Você está tentando criar muitos comentários, então comentários criados recentemente podem ter sido removidos.

Mudança no status dos conteúdos (firewall ao invés de draft)

Conforme mencionado em #1638 (comment), foi criado um novo status chamado firewall para representar um conteúdo que foi afetado pelo firewall, mesmo que o conteúdo estivesse com o status deleted. Assim, é possível analisar pelos endpoints quais ações o usuário realizou que fizeram com que o firewall fosse ativado. O evento do firewall poderá ser analisado para confirmar (confirm) ou reverter (undo) o efeito, então o status do conteúdo seria respectivamente deleted ou o status anterior.

Reversão de ganhos de TabCoins

A função creditOrDebitTabCoins foi chamada para reverter possíveis ganhos de TabCoins que o usuário teve com os conteúdos publicados que foram pegos pelo firewall interno.

Endpoints

  • GET /api/v1/events/firewall/[id]: obter dados sobre o evento do firewall e quais foram os conteúdos e usuários afetados.
  • POST /api/v1/moderations/review_firewall/[id]: confirmar ou desfazer um evento específico de firewall. A confirmação (confirm) adiciona a feature nuked ao usuário ou o status deleted aos conteúdos envolvidos. A reversão (undo) retorna os TabCoins removidos, restaura o status dos conteúdos e features dos usuários, a depender do tipo de firewall. Este endpoint retornará os dados atualizados contendo o evento original do firewall, o novo evento criado ao desfazer o firewall, os dados dos conteúdos e usuários afetados.

Resolve #1463

Tipo de mudança

  • Melhorias no firewall interno
  • Nova funcionalidade

Checklist:

  • As modificações não geram novos logs de erro ou aviso (warning).
  • Eu adicionei testes que provam que a correção ou novo recurso funciona conforme esperado.
  • Tanto os novos testes quanto os antigos estão passando localmente.

@Rafatcb Rafatcb added back Envolve modificações no backend segurança Melhoria de segurança labels Feb 26, 2024
Copy link

vercel bot commented Feb 26, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
tabnews ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jun 4, 2024 0:18am

Copy link
Collaborator

@aprendendofelipe aprendendofelipe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Importante contribuição, @Rafatcb! 💪💪💪

Com a adição de undoContentsTabcoins, talvez seja melhor executar tudo dentro de uma transação, mas é preciso pensar melhor se isso faz sentido, pois, se der algum erro, não seria interessante reverter toda a transação.

Fiz comentários no código

models/firewall.js Outdated Show resolved Hide resolved
models/firewall.js Outdated Show resolved Hide resolved
models/firewall.js Outdated Show resolved Hide resolved
models/firewall.js Outdated Show resolved Hide resolved
@Rafatcb
Copy link
Collaborator Author

Rafatcb commented Feb 26, 2024

Com a adição de undoContentsTabcoins, talvez seja melhor executar tudo dentro de uma transação, mas é preciso pensar melhor se isso faz sentido, pois, se der algum erro, não seria interessante reverter toda a transação.

Acho que criar uma transação para cada iteração do for pode fazer sentido, assim garantimos que toda a atualização do saldo referente ao conteúdo X foi feita corretamente, sem impactar a atualização do saldo dos outros conteúdos ou a atualização do status. O que acha?

Edit: Vendo melhor, a condição em que entrará na função creditOrDebitTabCoins só tem uma query que modifica o banco, então a transação não teria impacto, apenas um try / catch que poderia prevenir algo, mas não sei se tem necessidade ali. Vou subir as alterações sem try / catch e sem transaction.

@aprendendofelipe
Copy link
Collaborator

@Rafatcb, aquele owner_id: context.user.id deixou visível que falta um teste que garanta que os conteúdos serão despublicados mesmo sendo de diferentes usuários. Já faltava um teste desse antes do PR.


E a questão de diferentes usuários me fez pensar na possível situação de usuários legítimos que publicarem algo pela mesma rede pública, ao mesmo tempo, e somente o terceiro saberá que alguma coisa errada aconteceu. Os dois primeiros não saberão o que aconteceu com suas publicações. Será que é interessante verificar se alguma das publicações é de um usuário diferente do terceiro e enviar uma notificação por email?


Um efeito colateral da implementação é que ficou mais complicado de reverter o efeito do firewall em casos de falso positivo. Antes, apesar de ter que fazer diretamente no banco, era só voltar as publicações de draft para published, mas agora seria necessário também desfazer o efeito de creditOrDebitTabCoins. Só que falta uma definição de como seria isso de forma a não causar inconsistências.

@Rafatcb
Copy link
Collaborator Author

Rafatcb commented Feb 27, 2024

aquele owner_id: context.user.id deixou visível que falta um teste que garanta que os conteúdos serão despublicados mesmo sendo de diferentes usuários. Já faltava um teste desse antes do PR.

Criarei o teste 👍

E a questão de diferentes usuários me fez pensar na possível situação de usuários legítimos que publicarem algo pela mesma rede pública, ao mesmo tempo, e somente o terceiro saberá que alguma coisa errada aconteceu. Os dois primeiros não saberão o que aconteceu com suas publicações. Será que é interessante verificar se alguma das publicações é de um usuário diferente do terceiro e enviar uma notificação por email?

Acho que isso pode ser interessante sim.

Um efeito colateral da implementação é que ficou mais complicado de reverter o efeito do firewall em casos de falso positivo. Antes, apesar de ter que fazer diretamente no banco, era só voltar as publicações de draft para published, mas agora seria necessário também desfazer o efeito de creditOrDebitTabCoins. Só que falta uma definição de como seria isso de forma a não causar inconsistências.

Ainda não pensei na melhor forma em fazer isso. Você já tem alguma ideia? Se seria criando uma função SQL ou uma feature e um endpoint para desfazer os efeitos de um evento do firewall específico?

@aprendendofelipe
Copy link
Collaborator

Ainda não pensei na melhor forma em fazer isso. Você já tem alguma ideia? Se seria criando uma função SQL ou uma feature e um endpoint para desfazer os efeitos de um evento do firewall específico?

Também não pensei. Acho que o ponto mais importante é como ficaria no banco de dados, já que não podemos excluir os balanços criados pelo evento de firewall. Provavelmente teria que criar novos balanços revertendo os do evento de reversão 😅

Talvez uma undoAllFirewallSideEffect parecida com a undoAllRatingOperations.

@Rafatcb Rafatcb added the pendente Aguardando ação do autor do Pull Request label Feb 28, 2024
@Rafatcb
Copy link
Collaborator Author

Rafatcb commented Mar 4, 2024

Firewall

Percebi que a alteração que fiz removia o conteúdo, mas não atualizava o deleted_at, então aproveitei para corrigir isso. Também passei a atualizar o updated_at nas três procedures do firewall.

Email

A parte do e-mail acabou ficando bem "personalizada" de acordo com singular/plural e publicação/comentário. Para as publicações, consegui enviar o título, mas para os comentários não sei o que seria melhor para quem receber o e-mail ter uma noção, então passei apenas os IDs. Se você ter alguma sugestão de melhoria, pode falar.

Não sei se o texto "Identificamos que você está tentando..." é adequado, se deveria mencionar "Identificamos muitas novas publicações no seu IP" ou algo parecido.

Desfazer o efeito do firewall

Modifiquei o user.addFeatures e o balance.undo, e criei o content.undoDeleted para conseguir atualizar os dados de uma forma mais adequada para essa situação específica.

Algumas dúvidas:

  1. Essa é uma ação sobre o "firewall", então criei o endpoint DELETE /api/v1/firewall/[event_id], mas na verdade a ação é orientada pela tabela events, tanto que recebe o event.id como parâmetro. O endpoint deveria ser DELETE /api/v1/events/[id]?
  2. É mais adequado realizar o event.findOne e a validação no controller e passar o objeto foundEvent para o model (e nesse caso o model precisaria confiar que o objeto foundEvent está correto) ou deixar o findOne e as validações no model mesmo?
  3. Acha que faz mais sentido o endpoint retornar algo específico, retornar {} ou null?

@Rafatcb Rafatcb removed the pendente Aguardando ação do autor do Pull Request label Mar 4, 2024
Copy link
Collaborator

@aprendendofelipe aprendendofelipe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Rafatcb, está muito bom, mas como ainda não consegui ver tudo, já vou deixar alguns comentários.

Sobre a refatoração em models/transacional, aprovo todas as mudanças. Até por isso acho que talvez compense separar em um PR prévio a esse e já matar essa etapa.

Sobre a parte de email dentro de models/firewall, será que não são coisas que deveriam estar no models/notification?

Tem mais comentários no código 👍

models/transactional/components/code.js Outdated Show resolved Hide resolved
models/validator.js Outdated Show resolved Hide resolved
pages/api/v1/firewall/[event_id]/index.public.js Outdated Show resolved Hide resolved
pages/api/v1/firewall/[event_id]/index.public.js Outdated Show resolved Hide resolved
@Rafatcb
Copy link
Collaborator Author

Rafatcb commented Mar 9, 2024

Sobre a refatoração em models/transacional, aprovo todas as mudanças. Até por isso acho que talvez compense separar em um PR prévio a esse e já matar essa etapa.

Ok, vou fazer isso. Eu fiz aqui porque estava precisando copiar os estilos e percebi a repetição.

Sobre a parte de email dentro de models/firewall, será que não são coisas que deveriam estar no models/notification?

Eu havia começado a fazer no models/notification, mas depois de inspecionar o código tinha ficado em dúvida se esse era o "padrão do projeto". Vou organizar e passar para o models/notification.

@Rafatcb Rafatcb added the pendente Aguardando ação do autor do Pull Request label Mar 9, 2024
@Rafatcb Rafatcb mentioned this pull request Mar 9, 2024
3 tasks
@Rafatcb Rafatcb marked this pull request as draft March 12, 2024 01:11
@Rafatcb

This comment was marked as outdated.

Copy link
Collaborator Author

@Rafatcb Rafatcb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Enquanto estou criando o endpoint GET, percebi algo que acho que está errado (filterOutput no model), então decidi aproveitar para comentar também outros pontos que poderiam ser diferentes.

models/firewall.js Outdated Show resolved Hide resolved
models/firewall.js Outdated Show resolved Hide resolved
models/firewall.js Outdated Show resolved Hide resolved
@Rafatcb Rafatcb removed the pendente Aguardando ação do autor do Pull Request label Mar 16, 2024
@Rafatcb
Copy link
Collaborator Author

Rafatcb commented Mar 16, 2024

Fiz o GET. Abaixo estão alguns pontos que refleti e fiquei indeciso sobre como proceder. O PR está funcional mas acredito que esses pontos (além dos já comentados) mereçam atenção antes de realizar o merge:

  1. Não sei se a interface de retorno está ideal:

    {
      affected: {
        contents?,
        users?
      },
      event,
      status: 'active' | 'reversed'
    }

    Eu escolhi adicionar um atributo affected (que pode ter outro nome) para não correr o risco de eventualmente retornarmos mais coisas e ficar incompatível com a interface atual (imagine que vamos retornar um event afetado, por exemplo). E a interface do affected está compatível com o retorno do endpoint do undo.

  2. Não consegui entender como modificar o schemas no validator para conseguir usar no filteredOutputValues do GET. Comecei experimentando validar apenas o retorno de event, mas o schema está esperando que o objeto seja o event, e não que tenha uma tributo event, então já não soube como lidar com esses casos de "atributos com o mesmo nome". Outro exemplo é o status, que não deveria ter a mesma validação do status do content.

    Além disso, precisei modificar o schemas.id para aceitar um Array para conseguir passar um array no where.id do content.findAll. Não me parece ser a solução ideal.

@Rafatcb Rafatcb marked this pull request as ready for review March 16, 2024 01:03
models/firewall/find.js Outdated Show resolved Hide resolved
@Rafatcb
Copy link
Collaborator Author

Rafatcb commented May 15, 2024

Realizei as alterações propostas. Separei o models/firewall em diferentes arquivos e acho que ficou bem organizado. Intencionalmente, não estou exportando o event-types pelo firewall/index.js pois não vi a necessidade de usá-lo fora dos modelos do firewall.

Copy link
Collaborator

@aprendendofelipe aprendendofelipe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fiz sugestões no código, e para facilitar eu já enviei um commit com as mudanças que sugeri. Se acatar, pode reorganizar os commits do PR antes do merge, se achar necessário.

Estando tudo certo, me avise para rodarmos as migrations e fazermos os testes finais em homologação 🤝

models/firewall/rules.js Outdated Show resolved Hide resolved
models/firewall/find.js Outdated Show resolved Hide resolved
models/firewall/review.js Outdated Show resolved Hide resolved
models/firewall/review.js Outdated Show resolved Hide resolved
@Rafatcb
Copy link
Collaborator Author

Rafatcb commented May 15, 2024

Podemos deixar os commits assim 👍

Parece tudo certo, pode rodar as migrações.

@aprendendofelipe
Copy link
Collaborator

Precisei alterar a migration para remover a versão antiga das funções antes de criar as novas, pois não foi possível atualizar as funções alterando o tipo de retorno delas.

Agora foi tudo normalmente e já podemos testar em homologação. Inclusive já adicionei as features para os moderadores 👍

@Rafatcb
Copy link
Collaborator Author

Rafatcb commented May 16, 2024

Criei alguns comentários em homologação, caí no rate limit duas vezes, mas nenhuma no firewall.

Então, fui tentar criar contas, e consegui cair no firewall. Só não consegui continuar o teste porque não temos um GET /api/v1/events/firewall para listar os erros e pegar o id 😅

@Rafatcb
Copy link
Collaborator Author

Rafatcb commented May 16, 2024

Vi aqui que se alguém é pego pelo firewall e continua realizando a ação, novos eventos do firewall são criados. Eventos com ids diferentes, mas tendo todas as outras informações iguais. Isso faz com que o teste abaixo passe:

test('With two "firewall:block_users" events from the same IP', async () => {
  const usersRequestBuilder = new RequestBuilder('/api/v1/users');
  const firewallRequestBuilder = new RequestBuilder(`/api/v1/events/firewall`);
  await firewallRequestBuilder.buildUser({ with: ['read:firewall'] });

  // Create users
  const { responseBody: user1 } = await usersRequestBuilder.post({
    username: 'firstUser',
    email: '[email protected]',
    password: 'password',
  });
  const { responseBody: user2 } = await usersRequestBuilder.post({
    username: 'secondUser',
    email: '[email protected]',
    password: 'password',
  });
  const { response: user3Response } = await usersRequestBuilder.post({
    username: 'thirdUser',
    email: '[email protected]',
    password: 'password',
  });

  expect(user3Response.status).toEqual(429);

  let allEvents = await event.findAll();
  const firstFirewallEvent = allEvents.at(-1);

  const { response: user4Response } = await usersRequestBuilder.post({
    username: 'fourthUser',
    email: '[email protected]',
    password: 'password',
  });

  expect(user4Response.status).toEqual(429);

  allEvents = await event.findAll();
  const secondFirewallEvent = allEvents.at(-1);

  expect(firstFirewallEvent.id).not.toEqual(secondFirewallEvent.id);

  // Get firewall side-effects
  const { response: firstFirewallResponse, responseBody: firstFirewallResponseBody } =
    await firewallRequestBuilder.get(`/${firstFirewallEvent.id}`);
  const { response: secondFirewallResponse, responseBody: secondFirewallResponseBody } =
    await firewallRequestBuilder.get(`/${secondFirewallEvent.id}`);

  expect(firstFirewallResponse.status).toEqual(200);
  expect(secondFirewallResponse.status).toEqual(200);

  await usersRequestBuilder.setUser(user1);
  const { responseBody: user1AfterFirewall } = await usersRequestBuilder.get(`/${user1.username}`);

  await usersRequestBuilder.setUser(user2);
  const { responseBody: user2AfterFirewall } = await usersRequestBuilder.get(`/${user2.username}`);

  expect(firstFirewallResponseBody).toEqual({
    affected: {
      users: [user1AfterFirewall, user2AfterFirewall],
    },
    events: [
      {
        created_at: firstFirewallResponseBody.events[0].created_at,
        id: firstFirewallEvent.id,
        metadata: {
          from_rule: 'create:user',
          users: [user1AfterFirewall.id, user2AfterFirewall.id],
        },
        originator_user_id: null,
        type: 'firewall:block_users',
      },
    ],
  });

  expect(Date.parse(firstFirewallResponseBody.events[0].created_at)).not.toEqual(NaN);

  expect(secondFirewallResponseBody).toEqual({
    affected: {
      users: [user1AfterFirewall, user2AfterFirewall],
    },
    events: [
      {
        created_at: secondFirewallResponseBody.events[0].created_at,
        id: secondFirewallEvent.id,
        metadata: {
          from_rule: 'create:user',
          users: [user1AfterFirewall.id, user2AfterFirewall.id],
        },
        originator_user_id: null,
        type: 'firewall:block_users',
      },
    ],
  });

  expect(Date.parse(secondFirewallResponseBody.events[0].created_at)).not.toEqual(NaN);
});

Esse não me parece o comportamento ideal, já que na hora de confirmar ou desfazer o evento, após um deles ser analisado, o outro não terá mais impacto.

Faz sentido mudar as funções create...RuleSideEffect para, antes de criar um novo evento, procurar se o evento já existe e enviá-lo pela notificação?

@aprendendofelipe
Copy link
Collaborator

Faz sentido mudar as funções create...RuleSideEffect para, antes de criar um novo evento, procurar se o evento já existe e enviá-lo pela notificação?

Pode ser que eu não tenha entendido sua dúvida, mas acredito que não faça sentido procurar outros eventos no momento que alguém cair no firewall. Mas na ação de desfazer ou confirmar o evento de firewall, aí sim, acho que é necessário buscar todos. Quando eu sugeri de não colocar o limite de 2 eventos no validador, foi justamente pensando nisso. 👍


function buildWhereClause(where, nextArgumentIndex = 1) {
const columnMap = {
types: 'type',
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Não temos um padrão para isso, e acho que fui eu quem começou a adicionar o nome da propriedade no plural nos models para permitir buscar passando um array, mas como tanto aqui quanto no models/user eu faço a verificação Array.isArray(value), pensei em tirar a possibilidade de passar o nome da propriedade no plural nesses dois models. Faz sentido?

Se sim, posso realizar essa modificação junto de outras (se surgirem na revisão).

Isso também pode ser tratado posteriormente no contents, já que ele não está relacionado à este PR.

@Rafatcb
Copy link
Collaborator Author

Rafatcb commented May 18, 2024

Criei a função findAllRelatedEvents para conseguir obter todos os eventos relacionados numa única ida ao banco. Não sei se dá para deixar a query melhor, imagino que ela ficará lenta num banco com muitos eventos. O lado positivo é que esses endpoints serão pouco utilizados, já que é exclusivo para os moderadores.

INNER JOIN
searched_event ON true
WHERE
events.metadata @> searched_event.metadata
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do jeito que está testando, também passaria se fizesse a comparação simplesmente com =:

WHERE
  events.metadata = searched_event.metadata

Mas acredito que a intenção seja lidar com os casos em que nem todos os afetados serão os mesmos, por exemplo quando um conteúdo (ou usuário) for pego no primeiro evento, mas, por já ser mais antigo, não for pego pelo segundo. Nesse caso, para obter o mesmo resultado independentemente de qual dos eventos enviar na requisição, a comparação precisa ser com algo assim:

WHERE
  events.metadata @> searched_event.metadata OR
  events.metadata <@ searched_event.metadata

Obs.: Tem outras formas de comparar, mas teria que ter algo específico para conteúdos e outra comparação para usuários.

Acho que, para testar isso corretamente, teria que ser possível criar os eventos com data retroativa. Uma alternativa é modificar a query de criação do evento para usar a data e hora da lambda ao invés do banco de dados (como no published_at) e usar vi.useFakeTimers no teste.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fiquei em dúvida se vale a pena tantas alterações para testar isso. Veja o que fui percebendo:

  1. Ao passar um new Date() no INSERT do models/event, não será possível testar com o RequestBuilder porque o Next e o Vitest são processos diferentes, então mesmo modificando o tempo no teste, o registro usará o horário do computador.
  2. Então eu poderia usar o orchestrator para criar os conteúdos, já que ele cria também o evento. Nessa situação, o horário salvo é o modificado no teste com useFakeTimers(), mas o canRequest não é chamado.
  3. Seguindo, eu precisaria modificar o orchestrator.createContent para simular a chamada à regra adequada do firewall.
  4. Por fim (imagino), precisaria modificar a função firewall_create_content_text_child e relacionadas para aceitar o createdAt, que seria usado para a comparação no lugar de AND created_at > NOW() - INTERVAL '5 seconds'.

Faz sentido? Compliquei alguma parte que não precisaria?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Ao passar um new Date() no INSERT do models/event, não será possível testar com o RequestBuilder porque o Next e o Vitest são processos diferentes, então mesmo modificando o tempo no teste, o registro usará o horário do computador.
  2. Então eu poderia usar o orchestrator para criar os conteúdos, já que ele cria também o evento. Nessa situação, o horário salvo é o modificado no teste com useFakeTimers(), mas o canRequest não é chamado.

Para usar tempos falsos, de fato precisa criar o conteúdo pelo orchestrator.createContent, mas só precisa falsificar a hora do primeiro (ou dos primeiros) evento(s). A requisição que vai cair no firewall deve ser direto pela API, onde pode ser usado o RequestBuilder.

  1. Seguindo, eu precisaria modificar o orchestrator.createContent para simular a chamada à regra adequada do firewall.

Acho que não precisa (nem deveria fazer isso), mas entendo que isso seria para a criação do primeiro evento de firewall do teste. Deve ser suficiente adicionar um orchestrator.createFirewallEvent para permitir criar um evento qualquer diretamente por ele. Com isso será possível simular um evento de firewall com mais (e com menos) conteúdos (ou usuários) do que o evento de firewall que será criado pela API, e daí é esperado que esse evento criado manualmente seja incluído nos eventos de firewall relacionados que são retornados. Acho que compensa fazer isso, pois a alternativa seria criar os dois eventos pela API, mas adicionando um intervalo de tempo entre as duas chamadas, o que aos poucos vai atrasando a execução da bateria de testes

Sobre o orchestrator.createFirewallEvent, ele pode chamar um firewall.createEvent, que pode ser criado para ser usado dentro de firewall/rules, o que também parece ser uma refatoração simples.

  1. Por fim (imagino), precisaria modificar a função firewall_create_content_text_child e relacionadas para aceitar o createdAt, que seria usado para a comparação no lugar de AND created_at > NOW() - INTERVAL '5 seconds'.

Pensando rapidamente, acho que não precisa modificar essas funções.

Faz sentido? Compliquei alguma parte que não precisaria?

Talvez tenha complicado ao pensar em usar apenas o orchestrator.createContent ou apenas o RequestBuilder, mas usando os dois, cada um no momento adequado, acho que é uma mudança bem simples. No Triple A dos testes (Arrange, Act, Assert), o orchestrator.createContent e orchestrator.createFirewallEvent seriam usados no Arrange e o RequestBuilder no Act.

No código atual em produção seria uma mudança apenas na query de event.create, por exemplo adicionando created_at, $5 e new Date() assim:

  const query = {
    text: `INSERT INTO events (type, originator_user_id, originator_ip, metadata, created_at)
               VALUES($1, $2, $3, $4, $5) RETURNING *;`,
    values: [
      cleanObject.type,
      cleanObject.originator_user_id,
      cleanObject.originator_ip,
      cleanObject.metadata,
      new Date(),
    ],
  };

Não testei o que estou sugerindo, então posso estar deixando escapar algo. Se preferir, posso implementar para descobrir se é tão simples como pensei. 🤝

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aprendendofelipe Eu estava tentando implementar mas comecei a ficar confuso sobre o que você realmente propôs, então se puder implementar, agradeço.

A alteração que subi agora foi apenas para definir o status: published de alguns testes que criavam publicações pelo orchestrator.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pode deixar que amanhã eu implemento 🤝

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As alterações que subi agora foram apenas um rebase.

Rafatcb and others added 9 commits June 3, 2024 21:11
Improves firewall error message; changes the content status to `deleted` instead of `draft`;
reverses the user's TabCoins earnings from content that was caught by the firewall; only updates
content that has the status `published`.
Send an email explaining what happened to each affected user that did not trigger the event. If it
is the root content firewall, the titles are sent in the body of the email, and if it is the
comments firewall, the IDs are sent.
Returns the firewall `events` objects, along with the data affected by the event (`contents` and/or
`users`)
…rewall

Instead of saving the `status` of content affected by the firewall as `deleted`, save it as
`firewall`. When undoing, returns the contents to their original status (not necessarily
`published`).
If the firewall catches some suspicious activity from an IP address and that IP address continues to
perform the same action, new events are created for the same firewall side-effect.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
back Envolve modificações no backend novo recurso Nova funcionalidade/recurso segurança Melhoria de segurança
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Ajustes necessários no firewall interno (limite de usuários e publicações por IP)
2 participants