Skip to content

Commit

Permalink
Merge pull request #51 from ASparton/feat/35-delete-feed-route
Browse files Browse the repository at this point in the history
feat(delete-feed-route): delete feed by id route done
  • Loading branch information
ASparton authored Nov 23, 2023
2 parents 75398e8 + d8e10fd commit 760d122
Show file tree
Hide file tree
Showing 8 changed files with 92 additions and 13 deletions.
59 changes: 59 additions & 0 deletions back/__tests__/controllers/feeds.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,65 @@ describe('Feeds controller tests', () => {
await deleteAllUsers(database);
});
});

describe('DELETE feed by id', () => {
beforeAll(async () => {
await populateFeeds(database);
const res = await request(app).post('/api/users/register').send({
email: '[email protected]',
password: 'mySecretPassword',
username: 'Alexis',
});
authToken = res.body.token;
registeredUserId = res.body.user.id;
});

test('DELETE feed unauthenticated', async () => {
const res = await request(app).delete('/api/feeds/1');
expect(res.statusCode).toStrictEqual(HttpStatusCode.UNAUTHORIZED_401);
});

test('DELETE feed authenticated as non admin', async () => {
const res = await request(app)
.delete('/api/feeds/1')
.set('Authorization', `Bearer ${authToken}`);
expect(res.statusCode).toStrictEqual(HttpStatusCode.FORBIDDEN_403);
});

test('DELETE feed authenticated as admin', async () => {
await setRegisteredUserAdmin(registeredUserId);
const res = await request(app)
.delete('/api/feeds/1')
.set('Authorization', `Bearer ${authToken}`);
expect(res.statusCode).toStrictEqual(HttpStatusCode.OK_200);

const deleteFeed = await database.feed.findUnique({
where: {
id: 1,
},
});
expect(deleteFeed).toBeNull();
});

test('DELETE feed with non existing id', async () => {
const res = await request(app)
.delete('/api/feeds/0')
.set('Authorization', `Bearer ${authToken}`);
expect(res.statusCode).toStrictEqual(HttpStatusCode.NOT_FOUND_404);
});

test('DELETE feed with invalid id format', async () => {
const res = await request(app)
.delete('/api/feeds/nzendiezn')
.set('Authorization', `Bearer ${authToken}`);
expect(res.statusCode).toStrictEqual(HttpStatusCode.BAD_REQUEST_400);
});

afterAll(async () => {
await deleteAllFeeds(database);
await deleteAllUsers(database);
});
});
});

async function setRegisteredUserAdmin(userId: string) {
Expand Down
2 changes: 1 addition & 1 deletion back/insomnia.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"_type":"export","__export_format":4,"__export_date":"2023-11-21T16:11:15.725Z","__export_source":"insomnia.desktop.app:v8.4.2","resources":[{"_id":"req_48edfa91da4e4baf89e1c451940ca502","parentId":"fld_7dfe6474a7fe4c66a734b163ac9511cd","modified":1700574327677,"created":1699275753161,"url":"{{ _.url }}/users/login","name":"LOGIN","description":"","method":"POST","body":{"mimeType":"application/json","text":"{\n\t\"email\": \"[email protected]\",\n\t\"password\": \"mySecretPassword\"\n}"},"parameters":[],"headers":[{"name":"Content-Type","value":"application/json"},{"name":"User-Agent","value":"insomnia/8.3.0"}],"authentication":{},"metaSortKey":-1699277626516,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"fld_7dfe6474a7fe4c66a734b163ac9511cd","parentId":"fld_8572aff577dd4975b461bd785072416a","modified":1700558051699,"created":1699277617711,"name":"AUTH","description":"","environment":{},"environmentPropertyOrder":null,"metaSortKey":-1700557585613,"_type":"request_group"},{"_id":"fld_8572aff577dd4975b461bd785072416a","parentId":"wrk_scratchpad","modified":1700557577457,"created":1700557577457,"name":"USERS","description":"","environment":{},"environmentPropertyOrder":null,"metaSortKey":-1700557577457,"_type":"request_group"},{"_id":"wrk_scratchpad","parentId":null,"modified":1698054281901,"created":1698054281901,"name":"Scratch Pad","description":"","scope":"collection","_type":"workspace"},{"_id":"req_c9b6ded157db4820bbc5fe48279936bd","parentId":"fld_7dfe6474a7fe4c66a734b163ac9511cd","modified":1700577607674,"created":1698055032798,"url":"{{ _.url }}/users/register","name":"REGISTER","description":"","method":"POST","body":{"mimeType":"application/json","text":"{\n\t\"email\": \"[email protected]\",\n\t\"password\": \"mySecretPassword\",\n\t\"username\": \"Alexis\"\n}"},"parameters":[],"headers":[{"name":"Content-Type","value":"application/json"},{"name":"User-Agent","value":"insomnia/8.3.0"}],"authentication":{},"metaSortKey":-1699277626416,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_5d25b68ba33345878946e5296f24b304","parentId":"fld_7dfe6474a7fe4c66a734b163ac9511cd","modified":1700576649972,"created":1700558031049,"url":"{{ _.url }}/users/logout","name":"LOGOUT 🔒","description":"","method":"POST","body":{},"parameters":[],"headers":[{"name":"User-Agent","value":"insomnia/8.4.2"}],"authentication":{"type":"bearer","token":"{{ _.token }}","prefix":"Bearer"},"metaSortKey":-1699277626316,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_b21c2920ab4d48b3af187ecbc150318b","parentId":"fld_8572aff577dd4975b461bd785072416a","modified":1700576659458,"created":1700576596454,"url":"{{ _.url }}/users/profile","name":"PROFILE 🔒","description":"","method":"GET","body":{},"parameters":[],"headers":[{"name":"User-Agent","value":"insomnia/8.4.2"}],"authentication":{"type":"bearer","token":"{{ _.token }}","prefix":"Bearer"},"metaSortKey":-1699917606014.5,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_0aa5e8de7f3d41fe8cfb8be29424f2ef","parentId":"fld_8572aff577dd4975b461bd785072416a","modified":1700581264921,"created":1700580307718,"url":"{{ _.url }}/users/profile","name":"UPDATE 🔒","description":"","method":"PUT","body":{"mimeType":"application/json","text":"{\n\t\"username\": \"Alexis\",\n\t\"currency\": \"USD\",\n\t\"keywords\": [\n\t\t\"ethereum\"\n\t],\n\t\"cryptos\": [\n\t\t1\n\t]\n}"},"parameters":[],"headers":[{"name":"Content-Type","value":"application/json"},{"name":"User-Agent","value":"insomnia/8.4.2"}],"authentication":{"type":"bearer","token":"{{ _.token }}","prefix":"Bearer"},"metaSortKey":-1699597616265.25,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"env_99d30891da4bdcebc63947a8fc17f076de878684","parentId":"wrk_scratchpad","modified":1700580828379,"created":1698054913210,"name":"Base Environment","data":{"url":"localhost:4000/api","token":"mj7vunia97bxnr81c7pugt5ih4bamarge1k8exxn","userID":1},"dataPropertyOrder":{"&":["url","token","userID"]},"color":null,"isPrivate":false,"metaSortKey":1698054913210,"_type":"environment"},{"_id":"jar_99d30891da4bdcebc63947a8fc17f076de878684","parentId":"wrk_scratchpad","modified":1700557924945,"created":1698054913215,"name":"Default Jar","cookies":[],"_type":"cookie_jar"}]}
{"_type":"export","__export_format":4,"__export_date":"2023-11-21T22:34:37.995Z","__export_source":"insomnia.desktop.app:v8.4.2","resources":[{"_id":"req_accb7141a1c94119ac9bbe45524b417f","parentId":"fld_df03e117423f4903b236585bc67cc9d6","modified":1700605879774,"created":1700605512023,"url":"{{ _.url }}/feeds/1","name":"DELETE BY ID","description":"","method":"DELETE","body":{},"parameters":[],"headers":[{"name":"User-Agent","value":"insomnia/8.4.2"}],"authentication":{"type":"bearer","token":"02gvtn30flu8ousdk80ri4x31wtaa3m3drtm9day","prefix":"Bearer"},"metaSortKey":-1700605512023,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"fld_df03e117423f4903b236585bc67cc9d6","parentId":"wrk_47a49ef1618642b2ba8bf8089eb51a49","modified":1700601079368,"created":1700601079368,"name":"FEEDS","description":"","environment":{},"environmentPropertyOrder":null,"metaSortKey":-1700601079368,"_type":"request_group"},{"_id":"wrk_47a49ef1618642b2ba8bf8089eb51a49","parentId":null,"modified":1700593836329,"created":1700593821162,"name":"Count of Money API","description":"","scope":"collection","_type":"workspace"},{"_id":"req_d3b0d540afdb4f1d8eb26808caedd79c","parentId":"fld_df03e117423f4903b236585bc67cc9d6","modified":1700601236865,"created":1700601107315,"url":"{{ _.url }}/feeds","name":"ALL FEEDS 🅰️","description":"","method":"GET","body":{},"parameters":[],"headers":[{"name":"User-Agent","value":"insomnia/8.4.2"}],"authentication":{"type":"bearer","token":"ieg1zz4x75yln8jtn309ucmmn1hs6zgg3cjf117h","prefix":"Bearer"},"metaSortKey":-1700601113654,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_40f5f08d0ebc423ba0205a4dc0a2b3e3","parentId":"fld_0adeceae039d47caac5cb8d59d535a13","modified":1700595998689,"created":1700594400752,"url":"{{ _.url }}/articles","name":"Articles as anonymous","description":"","method":"GET","body":{},"parameters":[],"headers":[{"name":"User-Agent","value":"insomnia/8.4.2"}],"authentication":{},"metaSortKey":-1700594400752,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"fld_0adeceae039d47caac5cb8d59d535a13","parentId":"wrk_47a49ef1618642b2ba8bf8089eb51a49","modified":1700601099909,"created":1700593848098,"name":"ARTICLES","description":"","environment":{},"environmentPropertyOrder":null,"metaSortKey":-1700593848099,"_type":"request_group"},{"_id":"req_1561c2c8679c48369e9630b2d7aa6378","parentId":"fld_0adeceae039d47caac5cb8d59d535a13","modified":1700602481814,"created":1700593972741,"url":"{{ _.url }}/articles?keywords=bitcoin","name":"Articles by keywords 👤","description":"","method":"GET","body":{},"parameters":[],"headers":[{"name":"User-Agent","value":"insomnia/8.4.2"}],"authentication":{"type":"bearer","token":"av1f7s0y6qx8f3x8o4yw1rjz8pzo2celx2brhvmt","prefix":"Bearer"},"metaSortKey":-1700593972741,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_278c073318b1472583201e8c3f795495","parentId":"fld_0adeceae039d47caac5cb8d59d535a13","modified":1700596011147,"created":1700593853133,"url":"{{ _.url }}/articles/1","name":"One article by id","description":"","method":"GET","body":{},"parameters":[],"headers":[{"name":"User-Agent","value":"insomnia/8.4.2"}],"authentication":{},"metaSortKey":-1700593853133,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_7b5d4097d5304384a8be47a7e9e7105d","parentId":"fld_afa36486f6aa465a821ca115c050b467","modified":1700574327677,"created":1699275753161,"url":"{{ _.url }}/users/login","name":"LOGIN","description":"","method":"POST","body":{"mimeType":"application/json","text":"{\n\t\"email\": \"[email protected]\",\n\t\"password\": \"mySecretPassword\"\n}"},"parameters":[],"headers":[{"name":"Content-Type","value":"application/json"},{"name":"User-Agent","value":"insomnia/8.3.0"}],"authentication":{},"metaSortKey":-1699277626516,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"fld_afa36486f6aa465a821ca115c050b467","parentId":"fld_45c4f1bcbaa24df6a5948a8c30342512","modified":1700558051699,"created":1699277617711,"name":"AUTH","description":"","environment":{},"environmentPropertyOrder":null,"metaSortKey":-1700557585613,"_type":"request_group"},{"_id":"fld_45c4f1bcbaa24df6a5948a8c30342512","parentId":"wrk_47a49ef1618642b2ba8bf8089eb51a49","modified":1700557577457,"created":1700557577457,"name":"USERS","description":"","environment":{},"environmentPropertyOrder":null,"metaSortKey":-1700557577457,"_type":"request_group"},{"_id":"req_fb7934c4e0d743dbadead4312bc04ba3","parentId":"fld_afa36486f6aa465a821ca115c050b467","modified":1700605597566,"created":1698055032798,"url":"{{ _.url }}/users/register","name":"REGISTER","description":"","method":"POST","body":{"mimeType":"application/json","text":"{\n\t\"email\": \"[email protected]\",\n\t\"password\": \"mySecretPassword\",\n\t\"username\": \"Alexis\"\n}"},"parameters":[],"headers":[{"name":"Content-Type","value":"application/json"},{"name":"User-Agent","value":"insomnia/8.3.0"}],"authentication":{},"metaSortKey":-1699277626416,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_bc92fa6e9104494d92b4fa5a934a5608","parentId":"fld_afa36486f6aa465a821ca115c050b467","modified":1700601142192,"created":1700558031049,"url":"{{ _.url }}/users/logout","name":"LOGOUT 🔒","description":"","method":"POST","body":{},"parameters":[],"headers":[{"name":"User-Agent","value":"insomnia/8.4.2"}],"authentication":{"type":"bearer","token":"{{ _.token }}","prefix":"Bearer"},"metaSortKey":-1699277626316,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_698eec6ade06455fafbbb38c09da1024","parentId":"fld_45c4f1bcbaa24df6a5948a8c30342512","modified":1700576659458,"created":1700576596454,"url":"{{ _.url }}/users/profile","name":"PROFILE 🔒","description":"","method":"GET","body":{},"parameters":[],"headers":[{"name":"User-Agent","value":"insomnia/8.4.2"}],"authentication":{"type":"bearer","token":"{{ _.token }}","prefix":"Bearer"},"metaSortKey":-1699917606014.5,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"req_eb2611ad3eb64e569fa5f16f40d7949c","parentId":"fld_45c4f1bcbaa24df6a5948a8c30342512","modified":1700581264921,"created":1700580307718,"url":"{{ _.url }}/users/profile","name":"UPDATE 🔒","description":"","method":"PUT","body":{"mimeType":"application/json","text":"{\n\t\"username\": \"Alexis\",\n\t\"currency\": \"USD\",\n\t\"keywords\": [\n\t\t\"ethereum\"\n\t],\n\t\"cryptos\": [\n\t\t1\n\t]\n}"},"parameters":[],"headers":[{"name":"Content-Type","value":"application/json"},{"name":"User-Agent","value":"insomnia/8.4.2"}],"authentication":{"type":"bearer","token":"{{ _.token }}","prefix":"Bearer"},"metaSortKey":-1699597616265.25,"isPrivate":false,"settingStoreCookies":true,"settingSendCookies":true,"settingDisableRenderRequestBody":false,"settingEncodeUrl":true,"settingRebuildPath":true,"settingFollowRedirects":"global","_type":"request"},{"_id":"env_4501f8c1e77f499690a5b9d7fef2e5bb","parentId":"wrk_47a49ef1618642b2ba8bf8089eb51a49","modified":1700580828379,"created":1698054913210,"name":"Base Environment","data":{"url":"localhost:4000/api","token":"mj7vunia97bxnr81c7pugt5ih4bamarge1k8exxn","userID":1},"dataPropertyOrder":{"&":["url","token","userID"]},"color":null,"isPrivate":false,"metaSortKey":1698054913210,"_type":"environment"},{"_id":"jar_3898e942b6a24e5488e0060431cf476d","parentId":"wrk_47a49ef1618642b2ba8bf8089eb51a49","modified":1700557924945,"created":1698054913215,"name":"Default Jar","cookies":[],"_type":"cookie_jar"}]}
4 changes: 2 additions & 2 deletions back/src/controllers/articles.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import HttpStatusCode from '#types/HttpStatusCode';
import AllArticlesDTO from '#types/dto/articles/AllArticlesDTO';
import OneArticleDTO from '#types/dto/articles/OneArticleDTO';
import urlParamIdDTO from '#types/dto/urlParamIdDTO';
import { Article } from '@prisma/client';
import express from 'express';
import ApiErrors, { APIError } from '~apiErrors';
Expand Down Expand Up @@ -29,7 +29,7 @@ controller.get('/', isAuthenticated, async (req, res) => {
});

controller.get('/:id', async (req, res) => {
const urlParams = OneArticleDTO.parse(req.params);
const urlParams = urlParamIdDTO.parse(req.params);
const article = await findArticleById(urlParams.id);
if (article === null) throw new APIError(ApiErrors.RESOURCE_NOT_FOUND, 404);
return res.status(HttpStatusCode.OK_200).send(article);
Expand Down
10 changes: 9 additions & 1 deletion back/src/controllers/feeds.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
import express from 'express';
import HttpStatusCode from '#types/HttpStatusCode';
import { findAllFeeds } from '../database/feeds';
import { deleteFeedById, findAllFeeds } from '../database/feeds';
import urlParamIdDTO from '#types/dto/urlParamIdDTO';

const controller = express.Router();

controller.get('/', async (req, res) => {
return res.status(HttpStatusCode.OK_200).send(await findAllFeeds());
});

controller.delete('/:id', async (req, res) => {
const urlParams = urlParamIdDTO.parse(req.params);
return res
.status(HttpStatusCode.OK_200)
.send(await deleteFeedById(urlParams.id));
});

export default controller;
8 changes: 8 additions & 0 deletions back/src/database/feeds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,11 @@ import { database } from '~lucia';
export async function findAllFeeds(): Promise<Feed[]> {
return await database.feed.findMany();
}

export async function deleteFeedById(feedId: number): Promise<Feed> {
return await database.feed.delete({
where: {
id: feedId,
},
});
}
8 changes: 6 additions & 2 deletions back/src/middlewares.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { NextFunction, Request, Response } from 'express';
import { LuciaError } from 'lucia';

import ApiErrors, { APIError } from '~apiErrors';
import HttpStatusCode from '#types/HttpStatusCode';
import ApiErrors, { APIError } from '~apiErrors';

import { PrismaClientKnownRequestError } from '@prisma/client/runtime/library';
import { ZodError } from 'zod';
Expand Down Expand Up @@ -135,7 +135,11 @@ export function errorHandler<T>(
.status(HttpStatusCode.NOT_FOUND_404)
.send(ApiErrors.RESOURCE_NOT_FOUND);
break;

case 'P2025':
res
.status(HttpStatusCode.NOT_FOUND_404)
.send(ApiErrors.RESOURCE_NOT_FOUND);
break;
default:
res
.status(HttpStatusCode.INTERNAL_SERVER_ERROR_500)
Expand Down
7 changes: 0 additions & 7 deletions back/src/types/dto/articles/OneArticleDTO.ts

This file was deleted.

7 changes: 7 additions & 0 deletions back/src/types/dto/urlParamIdDTO.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { z } from 'zod';

const urlParamIdDTO = z.object({
id: z.coerce.number(),
});

export default urlParamIdDTO;

0 comments on commit 760d122

Please sign in to comment.