From 04b4f75f3eb546759987a925c9ef139ea5db552f Mon Sep 17 00:00:00 2001 From: mthmcalixto <121470728+mthmcalixto@users.noreply.github.com> Date: Tue, 9 Jan 2024 20:26:23 -0300 Subject: [PATCH] feat(/api/v1/contents): add return results for comments add with_children and with_root query params to filter content between posts and comments. --- pages/api/v1/contents/index.public.js | 16 +- tests/integration/api/v1/contents/get.test.js | 428 ++++++++++++++++++ 2 files changed, 442 insertions(+), 2 deletions(-) diff --git a/pages/api/v1/contents/index.public.js b/pages/api/v1/contents/index.public.js index cf5eae3f0..8a94b50b9 100644 --- a/pages/api/v1/contents/index.public.js +++ b/pages/api/v1/contents/index.public.js @@ -10,6 +10,7 @@ import controller from 'models/controller.js'; import event from 'models/event.js'; import firewall from 'models/firewall.js'; import notification from 'models/notification.js'; +import removeMarkdown from 'models/remove-markdown'; import user from 'models/user.js'; import validator from 'models/validator.js'; @@ -35,6 +36,8 @@ function getValidationHandler(request, response, next) { page: 'optional', per_page: 'optional', strategy: 'optional', + with_root: 'optional', + with_children: 'optional', }); request.query = cleanValues; @@ -48,11 +51,12 @@ async function getHandler(request, response) { const results = await content.findWithStrategy({ strategy: request.query.strategy, where: { - parent_id: null, + parent_id: request.query.with_children ? undefined : null, status: 'published', + $not_null: request.query.with_root === false ? ['parent_id'] : undefined, }, attributes: { - exclude: ['body'], + exclude: request.query.with_children ? undefined : ['body'], }, page: request.query.page, per_page: request.query.per_page, @@ -62,6 +66,14 @@ async function getHandler(request, response) { const secureOutputValues = authorization.filterOutput(userTryingToList, 'read:content:list', contentList); + for (const content of secureOutputValues) { + if (content.parent_id) { + content.body = removeMarkdown(content.body, { maxLength: 255 }); + } else { + delete content.body; + } + } + controller.injectPaginationHeaders(results.pagination, '/api/v1/contents', response); return response.status(200).json(secureOutputValues); diff --git a/tests/integration/api/v1/contents/get.test.js b/tests/integration/api/v1/contents/get.test.js index 9bf99b2e5..4ec65109e 100644 --- a/tests/integration/api/v1/contents/get.test.js +++ b/tests/integration/api/v1/contents/get.test.js @@ -1246,5 +1246,433 @@ describe('GET /api/v1/contents', () => { expect(uuidVersion(responseBody.error_id)).toEqual(4); expect(uuidVersion(responseBody.request_id)).toEqual(4); }); + + describe('Content type query params', () => { + test('1 post and 2 comments without children', async () => { + const firstUser = await orchestrator.createUser(); + const secondUser = await orchestrator.createUser(); + const thirdUser = await orchestrator.createUser(); + + const firstRootContent = await orchestrator.createContent({ + owner_id: firstUser.id, + title: 'Primeiro conteúdo criado', + status: 'published', + }); + + await orchestrator.createContent({ + owner_id: secondUser.id, + body: 'Comment #1', + status: 'published', + parent_id: firstRootContent.id, + }); + + await orchestrator.createContent({ + owner_id: thirdUser.id, + body: 'Comment #2', + status: 'published', + parent_id: firstRootContent.id, + }); + + const response = await fetch(`${orchestrator.webserverUrl}/api/v1/contents?strategy=new`); + const responseBody = await response.json(); + + expect(response.status).toEqual(200); + + expect(responseBody).toStrictEqual([ + { + id: firstRootContent.id, + owner_id: firstUser.id, + parent_id: null, + slug: 'primeiro-conteudo-criado', + title: 'Primeiro conteúdo criado', + status: 'published', + source_url: null, + created_at: firstRootContent.created_at.toISOString(), + updated_at: firstRootContent.updated_at.toISOString(), + published_at: firstRootContent.published_at.toISOString(), + deleted_at: null, + owner_username: firstUser.username, + tabcoins: 1, + children_deep_count: 2, + }, + ]); + }); + + test('3 posts, and 2 comments with_children = "false"', async () => { + const firstUser = await orchestrator.createUser(); + const secondUser = await orchestrator.createUser(); + const thirdUser = await orchestrator.createUser(); + + const firstRootContent = await orchestrator.createContent({ + owner_id: firstUser.id, + title: 'Primeiro conteúdo criado', + status: 'published', + }); + + const secondRootContent = await orchestrator.createContent({ + owner_id: secondUser.id, + title: 'Segundo conteúdo criado', + status: 'published', + }); + + const thirdRootContent = await orchestrator.createContent({ + owner_id: thirdUser.id, + title: 'Terceiro conteúdo criado', + status: 'published', + }); + + await orchestrator.createContent({ + owner_id: firstUser.id, + body: 'Comment #1', + status: 'published', + parent_id: thirdRootContent.id, + }); + + await orchestrator.createContent({ + owner_id: thirdUser.id, + body: 'Comment #2', + status: 'published', + parent_id: secondRootContent.id, + }); + + const response = await fetch(`${orchestrator.webserverUrl}/api/v1/contents?strategy=new&with_children=false`); + const responseBody = await response.json(); + + expect(response.status).toEqual(200); + + expect(responseBody).toStrictEqual([ + { + id: thirdRootContent.id, + owner_id: thirdUser.id, + parent_id: null, + slug: 'terceiro-conteudo-criado', + title: 'Terceiro conteúdo criado', + status: 'published', + source_url: null, + created_at: thirdRootContent.created_at.toISOString(), + updated_at: thirdRootContent.updated_at.toISOString(), + published_at: thirdRootContent.published_at.toISOString(), + deleted_at: null, + owner_username: thirdUser.username, + tabcoins: 1, + children_deep_count: 1, + }, + { + id: secondRootContent.id, + owner_id: secondUser.id, + parent_id: null, + slug: 'segundo-conteudo-criado', + title: 'Segundo conteúdo criado', + status: 'published', + source_url: null, + created_at: secondRootContent.created_at.toISOString(), + updated_at: secondRootContent.updated_at.toISOString(), + published_at: secondRootContent.published_at.toISOString(), + deleted_at: null, + owner_username: secondUser.username, + tabcoins: 1, + children_deep_count: 1, + }, + { + id: firstRootContent.id, + owner_id: firstUser.id, + parent_id: null, + slug: 'primeiro-conteudo-criado', + title: 'Primeiro conteúdo criado', + status: 'published', + source_url: null, + created_at: firstRootContent.created_at.toISOString(), + updated_at: firstRootContent.updated_at.toISOString(), + published_at: firstRootContent.published_at.toISOString(), + deleted_at: null, + owner_username: firstUser.username, + tabcoins: 1, + children_deep_count: 0, + }, + ]); + }); + + test('3 posts, and 2 comments with_children = "true"', async () => { + const firstUser = await orchestrator.createUser(); + const secondUser = await orchestrator.createUser(); + const thirdUser = await orchestrator.createUser(); + + const firstRootContent = await orchestrator.createContent({ + owner_id: firstUser.id, + title: 'Primeiro conteúdo criado', + status: 'published', + }); + + const secondRootContent = await orchestrator.createContent({ + owner_id: secondUser.id, + title: 'Segundo conteúdo criado', + status: 'published', + }); + + const thirdRootContent = await orchestrator.createContent({ + owner_id: thirdUser.id, + title: 'Terceiro conteúdo criado', + status: 'published', + }); + + const firstComment = await orchestrator.createContent({ + owner_id: firstUser.id, + body: 'Comment #1', + status: 'published', + parent_id: thirdRootContent.id, + }); + + const secondComment = await orchestrator.createContent({ + owner_id: thirdUser.id, + body: 'Comment #2', + status: 'published', + parent_id: secondRootContent.id, + }); + + const response = await fetch(`${orchestrator.webserverUrl}/api/v1/contents?strategy=new&with_children=true`); + const responseBody = await response.json(); + + expect(response.status).toEqual(200); + + expect(responseBody).toStrictEqual([ + { + id: secondComment.id, + owner_id: thirdUser.id, + parent_id: secondRootContent.id, + slug: secondComment.slug, + title: null, + body: 'Comment #2', + status: 'published', + source_url: null, + created_at: secondComment.created_at.toISOString(), + updated_at: secondComment.updated_at.toISOString(), + published_at: secondComment.published_at.toISOString(), + deleted_at: null, + owner_username: thirdUser.username, + tabcoins: 0, + children_deep_count: 0, + }, + { + id: firstComment.id, + owner_id: firstUser.id, + parent_id: thirdRootContent.id, + slug: firstComment.slug, + title: null, + body: 'Comment #1', + status: 'published', + source_url: null, + created_at: firstComment.created_at.toISOString(), + updated_at: firstComment.updated_at.toISOString(), + published_at: firstComment.published_at.toISOString(), + deleted_at: null, + owner_username: firstUser.username, + tabcoins: 0, + children_deep_count: 0, + }, + { + id: thirdRootContent.id, + owner_id: thirdUser.id, + parent_id: null, + slug: 'terceiro-conteudo-criado', + title: 'Terceiro conteúdo criado', + status: 'published', + source_url: null, + created_at: thirdRootContent.created_at.toISOString(), + updated_at: thirdRootContent.updated_at.toISOString(), + published_at: thirdRootContent.published_at.toISOString(), + deleted_at: null, + owner_username: thirdUser.username, + tabcoins: 1, + children_deep_count: 1, + }, + { + id: secondRootContent.id, + owner_id: secondUser.id, + parent_id: null, + slug: 'segundo-conteudo-criado', + title: 'Segundo conteúdo criado', + status: 'published', + source_url: null, + created_at: secondRootContent.created_at.toISOString(), + updated_at: secondRootContent.updated_at.toISOString(), + published_at: secondRootContent.published_at.toISOString(), + deleted_at: null, + owner_username: secondUser.username, + tabcoins: 1, + children_deep_count: 1, + }, + { + id: firstRootContent.id, + owner_id: firstUser.id, + parent_id: null, + slug: 'primeiro-conteudo-criado', + title: 'Primeiro conteúdo criado', + status: 'published', + source_url: null, + created_at: firstRootContent.created_at.toISOString(), + updated_at: firstRootContent.updated_at.toISOString(), + published_at: firstRootContent.published_at.toISOString(), + deleted_at: null, + owner_username: firstUser.username, + tabcoins: 1, + children_deep_count: 0, + }, + ]); + }); + + test('2 posts and 2 comments with_children = "true" and with_root = "false"', async () => { + const firstUser = await orchestrator.createUser(); + const secondUser = await orchestrator.createUser(); + const thirdUser = await orchestrator.createUser(); + + const firstRootContent = await orchestrator.createContent({ + owner_id: secondUser.id, + title: 'Primeiro conteúdo criado', + status: 'published', + }); + + const secondRootContent = await orchestrator.createContent({ + owner_id: thirdUser.id, + title: 'Segundo conteúdo criado', + status: 'published', + }); + + const firstComment = await orchestrator.createContent({ + owner_id: firstUser.id, + body: 'Comment #1', + status: 'published', + parent_id: firstRootContent.id, + }); + + const secondComment = await orchestrator.createContent({ + owner_id: thirdUser.id, + body: 'Comment #2', + status: 'published', + parent_id: secondRootContent.id, + }); + + const response = await fetch( + `${orchestrator.webserverUrl}/api/v1/contents?strategy=new&with_children=true&with_root=false` + ); + const responseBody = await response.json(); + + expect(response.status).toEqual(200); + + expect(responseBody).toStrictEqual([ + { + id: secondComment.id, + owner_id: thirdUser.id, + parent_id: secondRootContent.id, + slug: secondComment.slug, + title: null, + body: 'Comment #2', + status: 'published', + source_url: null, + created_at: secondComment.created_at.toISOString(), + updated_at: secondComment.updated_at.toISOString(), + published_at: secondComment.published_at.toISOString(), + deleted_at: null, + owner_username: thirdUser.username, + tabcoins: 0, + children_deep_count: 0, + }, + { + id: firstComment.id, + owner_id: firstUser.id, + parent_id: firstRootContent.id, + slug: firstComment.slug, + title: null, + body: 'Comment #1', + status: 'published', + source_url: null, + created_at: firstComment.created_at.toISOString(), + updated_at: firstComment.updated_at.toISOString(), + published_at: firstComment.published_at.toISOString(), + deleted_at: null, + owner_username: firstUser.username, + tabcoins: 0, + children_deep_count: 0, + }, + ]); + }); + + test('2 published posts, 1 draft post, and 2 published comments with_root = "true"', async () => { + const firstUser = await orchestrator.createUser(); + const secondUser = await orchestrator.createUser(); + const thirdUser = await orchestrator.createUser(); + + await orchestrator.createContent({ + owner_id: firstUser.id, + title: 'Primeiro conteúdo criado', + status: 'draft', + }); + + const secondRootContent = await orchestrator.createContent({ + owner_id: secondUser.id, + title: 'Segundo conteúdo criado', + status: 'published', + }); + + const thirdRootContent = await orchestrator.createContent({ + owner_id: thirdUser.id, + title: 'Terceiro conteúdo criado', + status: 'published', + }); + + await orchestrator.createContent({ + owner_id: firstUser.id, + body: 'Comment #1', + status: 'published', + parent_id: thirdRootContent.id, + }); + + await orchestrator.createContent({ + owner_id: thirdUser.id, + body: 'Comment #2', + status: 'published', + parent_id: secondRootContent.id, + }); + + const response = await fetch(`${orchestrator.webserverUrl}/api/v1/contents?strategy=new&with_root=true`); + const responseBody = await response.json(); + + expect(response.status).toEqual(200); + + expect(responseBody).toStrictEqual([ + { + id: thirdRootContent.id, + owner_id: thirdUser.id, + parent_id: null, + slug: 'terceiro-conteudo-criado', + title: 'Terceiro conteúdo criado', + status: 'published', + source_url: null, + created_at: thirdRootContent.created_at.toISOString(), + updated_at: thirdRootContent.updated_at.toISOString(), + published_at: thirdRootContent.published_at.toISOString(), + deleted_at: null, + owner_username: thirdUser.username, + tabcoins: 1, + children_deep_count: 1, + }, + { + id: secondRootContent.id, + owner_id: secondUser.id, + parent_id: null, + slug: 'segundo-conteudo-criado', + title: 'Segundo conteúdo criado', + status: 'published', + source_url: null, + created_at: secondRootContent.created_at.toISOString(), + updated_at: secondRootContent.updated_at.toISOString(), + published_at: secondRootContent.published_at.toISOString(), + deleted_at: null, + owner_username: secondUser.username, + tabcoins: 1, + children_deep_count: 1, + }, + ]); + }); + }); }); });