From 7d1fa2e40cfc16fa65a19f5f6d39be9366cb2b01 Mon Sep 17 00:00:00 2001 From: Faruk AYDIN Date: Tue, 26 Mar 2024 13:14:33 +0100 Subject: [PATCH] feat: Implement create access token API endpoint --- .../v1/access-tokens/create-access-token.js | 13 +++++++ .../access-tokens/create-access-token.test.js | 39 +++++++++++++++++++ .../src/routes/api/v1/access-tokens.js | 9 +++++ packages/backend/src/routes/index.js | 2 + 4 files changed, 63 insertions(+) create mode 100644 packages/backend/src/controllers/api/v1/access-tokens/create-access-token.js create mode 100644 packages/backend/src/controllers/api/v1/access-tokens/create-access-token.test.js create mode 100644 packages/backend/src/routes/api/v1/access-tokens.js diff --git a/packages/backend/src/controllers/api/v1/access-tokens/create-access-token.js b/packages/backend/src/controllers/api/v1/access-tokens/create-access-token.js new file mode 100644 index 00000000..5fe162a9 --- /dev/null +++ b/packages/backend/src/controllers/api/v1/access-tokens/create-access-token.js @@ -0,0 +1,13 @@ +import User from '../../../../models/user.js'; +import { renderObject, renderError } from '../../../../helpers/renderer.js'; + +export default async (request, response) => { + const { email, password } = request.body; + const token = await User.authenticate(email, password); + + if (token) { + return renderObject(response, { token }); + } + + renderError(response, [{ general: ['Incorrect email or password.'] }]); +}; diff --git a/packages/backend/src/controllers/api/v1/access-tokens/create-access-token.test.js b/packages/backend/src/controllers/api/v1/access-tokens/create-access-token.test.js new file mode 100644 index 00000000..cc54b094 --- /dev/null +++ b/packages/backend/src/controllers/api/v1/access-tokens/create-access-token.test.js @@ -0,0 +1,39 @@ +import { describe, it, expect, beforeEach } from 'vitest'; +import request from 'supertest'; +import app from '../../../../app.js'; +import { createUser } from '../../../../../test/factories/user'; + +describe('POST /api/v1/access-tokens', () => { + beforeEach(async () => { + await createUser({ + email: 'user@automatisch.io', + password: 'password', + }); + }); + + it('should return the token data with correct credentials', async () => { + const response = await request(app) + .post('/api/v1/access-tokens') + .send({ + email: 'user@automatisch.io', + password: 'password', + }) + .expect(200); + + expect(response.body.data.token.length).toBeGreaterThan(0); + }); + + it('should return error with incorrect credentials', async () => { + const response = await request(app) + .post('/api/v1/access-tokens') + .send({ + email: 'incorrect@email.com', + password: 'incorrectpassword', + }) + .expect(422); + + expect(response.body.errors.general).toEqual([ + 'Incorrect email or password.', + ]); + }); +}); diff --git a/packages/backend/src/routes/api/v1/access-tokens.js b/packages/backend/src/routes/api/v1/access-tokens.js new file mode 100644 index 00000000..8d7ed14c --- /dev/null +++ b/packages/backend/src/routes/api/v1/access-tokens.js @@ -0,0 +1,9 @@ +import { Router } from 'express'; +import asyncHandler from 'express-async-handler'; +import createAccessTokenAction from '../../../controllers/api/v1/access-tokens/create-access-token.js'; + +const router = Router(); + +router.post('/', asyncHandler(createAccessTokenAction)); + +export default router; diff --git a/packages/backend/src/routes/index.js b/packages/backend/src/routes/index.js index 6a6a5e21..cb141691 100644 --- a/packages/backend/src/routes/index.js +++ b/packages/backend/src/routes/index.js @@ -4,6 +4,7 @@ import webhooksRouter from './webhooks.js'; import paddleRouter from './paddle.ee.js'; import healthcheckRouter from './healthcheck.js'; import automatischRouter from './api/v1/automatisch.js'; +import accessTokensRouter from './api/v1/access-tokens.js'; import usersRouter from './api/v1/users.js'; import paymentRouter from './api/v1/payment.ee.js'; import appAuthClientsRouter from './api/v1/app-auth-clients.js'; @@ -26,6 +27,7 @@ router.use('/webhooks', webhooksRouter); router.use('/paddle', paddleRouter); router.use('/healthcheck', healthcheckRouter); router.use('/api/v1/automatisch', automatischRouter); +router.use('/api/v1/access-tokens', accessTokensRouter); router.use('/api/v1/users', usersRouter); router.use('/api/v1/payment', paymentRouter); router.use('/api/v1/app-auth-clients', appAuthClientsRouter);