Skip to content

Commit

Permalink
Merge pull request #50 from ASparton/feat/33-get-feeds-route
Browse files Browse the repository at this point in the history
feat(getAllFeeds): get all feeds route done with only access admin
  • Loading branch information
ASparton authored Nov 21, 2023
2 parents ca49f1a + 4aa73f5 commit 75398e8
Show file tree
Hide file tree
Showing 11 changed files with 124 additions and 5 deletions.
4 changes: 3 additions & 1 deletion back/__tests__/controllers/articles.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ import app from '../../src/app';

let authToken = '';

describe('Articles router tests', () => {
describe('Articles controller tests', () => {
beforeAll(async () => {
await deleteAllUsers(database);
await deleteAllFeeds(database);
});

describe('GET all articles', () => {
Expand Down Expand Up @@ -126,6 +127,7 @@ describe('Articles router tests', () => {

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

Expand Down
67 changes: 67 additions & 0 deletions back/__tests__/controllers/feeds.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import HttpStatusCode from '#types/HttpStatusCode';
import {
deleteAllFeeds,
deleteAllUsers,
exampleFeeds,
populateFeeds,
} from 'prisma/seedingOperatons';
import { database } from 'src/lucia';
import request from 'supertest';
import app from '../../src/app';

let authToken = '';
let registeredUserId = '';

describe('Feeds controller tests', () => {
describe('GET all feeds', () => {
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('GET all feeds unauthenticated', async () => {
const res = await request(app).get('/api/feeds');
expect(res.statusCode).toStrictEqual(HttpStatusCode.UNAUTHORIZED_401);
});

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

test('GET all feeds authenticated as admin', async () => {
await setRegisteredUserAdmin(registeredUserId);
const res = await request(app)
.get('/api/feeds')
.set('Authorization', `Bearer ${authToken}`);
expect(res.statusCode).toStrictEqual(HttpStatusCode.OK_200);
expect(JSON.parse(JSON.stringify(res.body))).toStrictEqual(
JSON.parse(JSON.stringify(exampleFeeds))
);
});

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

async function setRegisteredUserAdmin(userId: string) {
await database.user.update({
where: {
id: userId,
},
data: {
is_admin: true,
},
});
}
2 changes: 1 addition & 1 deletion back/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"license": "MIT",
"scripts": {
"dev": "tsx watch src/index.ts",
"test": "NODE_OPTIONS=--experimental-vm-modules npx jest --colors --coverage",
"test": "NODE_OPTIONS=--experimental-vm-modules npx jest --colors --coverage --runInBand",
"lint": "biome lint src/",
"format": "biome format --write src/"
},
Expand Down
1 change: 1 addition & 0 deletions back/prisma/seed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const prismaClient = new PrismaClient();

async function main() {
console.log(`Start seeding ...`);
// TODO: Real user population working with lucia
await populateUser(prismaClient);
await populateFeeds(prismaClient);
await populateArticles(prismaClient);
Expand Down
2 changes: 1 addition & 1 deletion back/prisma/seedingOperatons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const exampleUsers: User[] = [
},
];

const exampleFeeds: Feed[] = [
export const exampleFeeds: Feed[] = [
{
id: 1,
url: 'https://cointelegraph.com/rss/tag/bitcoin',
Expand Down
5 changes: 5 additions & 0 deletions back/src/apiErrors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ enum ApiErrors {
*/
UNAUTHORIZED = 'UNAUTHORIZED',

/**
* Raised when the user is not admin and the endpoint reached need admin rights
*/
FORBIDDEN = 'FORBIDDEN',

/**
* Raised when the resource at the given id was not found by prisma.
*/
Expand Down
9 changes: 8 additions & 1 deletion back/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,15 @@ import cors from 'cors';

import articles from '@controllers/articles';
import auth from '@controllers/auth';
import feeds from '@controllers/feeds';
import users from '@controllers/users';

import { authenticationRequired, errorHandler, logger } from '~middlewares';
import {
adminRoleRequired,
authenticationRequired,
errorHandler,
logger,
} from '~middlewares';

const app = express();

Expand All @@ -18,6 +24,7 @@ app.use(logger);

app.use('/api/users/', auth, authenticationRequired, users);
app.use('/api/articles', articles);
app.use('/api/feeds', authenticationRequired, adminRoleRequired, feeds);

app.use(errorHandler);

Expand Down
2 changes: 1 addition & 1 deletion back/src/controllers/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ controller.post('/register', async (req, res) => {
},
attributes: {
email: body.email,
username: body.email,
username: body.username,
currency: body.currency as string,
is_admin: false,
},
Expand Down
11 changes: 11 additions & 0 deletions back/src/controllers/feeds.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import express from 'express';
import HttpStatusCode from '#types/HttpStatusCode';
import { findAllFeeds } from '../database/feeds';

const controller = express.Router();

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

export default controller;
6 changes: 6 additions & 0 deletions back/src/database/feeds.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { Feed } from '@prisma/client';
import { database } from '~lucia';

export async function findAllFeeds(): Promise<Feed[]> {
return await database.feed.findMany();
}
20 changes: 20 additions & 0 deletions back/src/middlewares.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,26 @@ export function logger(req: Request, _: Response, next: NextFunction) {
next();
}

/**
* Only pass to the next middleware if the request is authenticated.
*/
export async function adminRoleRequired(
req: Request,
res: Response,
next: NextFunction,
) {
console.log('[AUTH] admin endpoint middleware');

if (!req.lucia || !req.lucia.user || !req.lucia.sessionId)
return res
.status(HttpStatusCode.UNAUTHORIZED_401)
.send(ApiErrors.UNAUTHORIZED);
if (!req.lucia.user.is_admin)
return res.status(HttpStatusCode.FORBIDDEN_403).send(ApiErrors.FORBIDDEN);

next();
}

/**
* Only pass to the next middleware if the request is authenticated.
*/
Expand Down

0 comments on commit 75398e8

Please sign in to comment.