Skip to content

Commit 7650d23

Browse files
committed
updated
1 parent b385e43 commit 7650d23

File tree

10 files changed

+180
-10
lines changed

10 files changed

+180
-10
lines changed

config/default.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ export default {
22
redisCacheExpiresIn: 60,
33
refreshTokenExpiresIn: 60,
44
accessTokenExpiresIn: 15,
5+
origin: 'http://localhost:3000',
56
};

package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,12 @@
1010
"devDependencies": {
1111
"@types/bcryptjs": "^2.4.2",
1212
"@types/config": "^0.0.41",
13+
"@types/cookie-parser": "^1.4.3",
14+
"@types/cors": "^2.8.12",
1315
"@types/express": "^4.17.13",
1416
"@types/jsonwebtoken": "^8.5.8",
1517
"@types/lodash": "^4.14.182",
18+
"@types/morgan": "^1.9.3",
1619
"@types/node": "^17.0.31",
1720
"prisma": "^3.13.0",
1821
"typescript": "^4.6.4"
@@ -21,11 +24,14 @@
2124
"@prisma/client": "^3.13.0",
2225
"bcryptjs": "^2.4.3",
2326
"config": "^3.3.7",
27+
"cookie-parser": "^1.4.6",
28+
"cors": "^2.8.5",
2429
"dotenv": "^16.0.0",
2530
"envalid": "^7.3.1",
2631
"express": "^4.18.1",
2732
"jsonwebtoken": "^8.5.1",
2833
"lodash": "^4.17.21",
34+
"morgan": "^1.10.0",
2935
"redis": "^4.1.0",
3036
"ts-node-dev": "^1.1.8",
3137
"zod": "^3.15.1"

src/app.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
require('dotenv').config();
22
import express, { NextFunction, Request, Response, response } from 'express';
33
import config from 'config';
4+
import cors from 'cors';
5+
import morgan from 'morgan';
6+
import cookieParser from 'cookie-parser';
47
import validateEnv from './utils/validateEnv';
58
import { PrismaClient } from '@prisma/client';
69
import authRouter from './routes/auth.routes';
10+
import userRouter from './routes/user.routes';
711
import AppError from './utils/appError';
812

913
validateEnv();
@@ -13,10 +17,27 @@ const app = express();
1317

1418
async function bootstrap() {
1519
// MIDDLEWARE
20+
21+
// 1.Body Parser
1622
app.use(express.json({ limit: '10kb' }));
1723

24+
// 2. Cookie Parser
25+
app.use(cookieParser());
26+
27+
// 2. Cors
28+
app.use(
29+
cors({
30+
origin: [config.get<string>('origin')],
31+
credentials: true,
32+
})
33+
);
34+
35+
// 3. Logger
36+
if (process.env.NODE_ENV === 'development') app.use(morgan('dev'));
37+
1838
// ROUTES
1939
app.use('/api/auth', authRouter);
40+
app.use('/api/users', userRouter);
2041

2142
// UNHANDLED ROUTES
2243
app.all('*', (req: Request, res: Response, next: NextFunction) => {

src/controllers/auth.controller.ts

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@ import bcrypt from 'bcryptjs';
33
import { LoginUserInput, RegisterUserInput } from '../schemas/user.schema';
44
import {
55
createUser,
6-
findUserByEmail,
6+
findUniqueUser,
77
signTokens,
88
} from '../services/user.service';
99
import { Prisma } from '@prisma/client';
1010
import config from 'config';
1111
import AppError from '../utils/appError';
12+
import redisClient from '../utils/connectRedis';
1213

1314
const cookiesOptions: CookieOptions = {
1415
httpOnly: true,
@@ -74,7 +75,7 @@ export const loginUserHandler = async (
7475
try {
7576
const { email, password } = req.body;
7677

77-
const user = await findUserByEmail({ email });
78+
const user = await findUniqueUser({ email });
7879

7980
if (!user || !(await bcrypt.compare(password, user.password))) {
8081
return next(new AppError(400, 'Invalid email or password'));
@@ -97,3 +98,26 @@ export const loginUserHandler = async (
9798
next(err);
9899
}
99100
};
101+
102+
function logout(res: Response) {
103+
res.cookie('access_token', '', { maxAge: 1 });
104+
res.cookie('refresh_token', '', { maxAge: 1 });
105+
res.cookie('logged_in', '', { maxAge: 1 });
106+
}
107+
108+
export const logoutUserHandler = async (
109+
req: Request,
110+
res: Response,
111+
next: NextFunction
112+
) => {
113+
try {
114+
await redisClient.del(res.locals.user.id);
115+
logout(res);
116+
117+
res.status(200).json({
118+
status: 'success',
119+
});
120+
} catch (err: any) {
121+
next(err);
122+
}
123+
};

src/controllers/user.controller.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { NextFunction, Request, Response } from 'express';
2+
3+
export const getMeHandler = async (
4+
req: Request,
5+
res: Response,
6+
next: NextFunction
7+
) => {
8+
try {
9+
const user = res.locals.user;
10+
11+
res.status(200).status(200).json({
12+
status: 'success',
13+
data: {
14+
user,
15+
},
16+
});
17+
} catch (err: any) {
18+
next(err);
19+
}
20+
};

src/middleware/deserializeUser.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { NextFunction, Request, Response } from 'express';
22
import { omit } from 'lodash';
3-
import { findUserById } from '../services/user.service';
3+
import { excludedFields, findUniqueUser } from '../services/user.service';
44
import AppError from '../utils/appError';
55
import redisClient from '../utils/connectRedis';
66
import { verifyJwt } from '../utils/jwt';
@@ -44,17 +44,18 @@ export const deserializeUser = async (
4444
}
4545

4646
// Check if the user still exist
47-
const user = await findUserById(JSON.parse(session).id);
47+
const user = await findUniqueUser({ id: JSON.parse(session).id });
4848

4949
if (!user) {
5050
return next(new AppError(401, `Invalid token or session has expired`));
5151
}
5252

5353
// Add user to res.locals
54-
res.locals.user = user;
54+
res.locals.user = omit(user, excludedFields);
5555

5656
next();
5757
} catch (err: any) {
58+
console.log(err);
5859
next(err);
5960
}
6061
};

src/routes/auth.routes.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import express from 'express';
22
import {
33
loginUserHandler,
4+
logoutUserHandler,
45
registerUserHandler,
56
} from '../controllers/auth.controller';
7+
import { deserializeUser } from '../middleware/deserializeUser';
8+
import { requireUser } from '../middleware/requireUser';
69
import { validate } from '../middleware/validate';
710
import { loginUserSchema, registerUserSchema } from '../schemas/user.schema';
811

@@ -12,4 +15,6 @@ router.post('/register', validate(registerUserSchema), registerUserHandler);
1215

1316
router.post('/login', validate(loginUserSchema), loginUserHandler);
1417

18+
router.get('/logout', deserializeUser, requireUser, logoutUserHandler);
19+
1520
export default router;

src/routes/user.routes.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import express from 'express';
2+
import { getMeHandler } from '../controllers/user.controller';
3+
import { deserializeUser } from '../middleware/deserializeUser';
4+
import { requireUser } from '../middleware/requireUser';
5+
6+
const router = express.Router();
7+
8+
router.use(deserializeUser, requireUser);
9+
10+
router.get('/me', getMeHandler);
11+
12+
export default router;

src/services/user.service.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import config from 'config';
44
import redisClient from '../utils/connectRedis';
55
import { signJwt } from '../utils/jwt';
66

7-
export const excludedFields = ['password', 'verified'];
7+
export const excludedFields = ['password', 'verified', 'verificationCode'];
88

99
const prisma = new PrismaClient();
1010

@@ -16,7 +16,7 @@ export const createUser = async (input: Prisma.UserCreateInput) => {
1616
return omit(user, excludedFields);
1717
};
1818

19-
export const findUserByEmail = async (where: Prisma.UserWhereUniqueInput) => {
19+
export const findUniqueUser = async (where: Prisma.UserWhereUniqueInput) => {
2020
return await prisma.user.findUnique({
2121
where,
2222
});

yarn.lock

Lines changed: 83 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,18 @@
7878
dependencies:
7979
"@types/node" "*"
8080

81+
"@types/cookie-parser@^1.4.3":
82+
version "1.4.3"
83+
resolved "https://registry.yarnpkg.com/@types/cookie-parser/-/cookie-parser-1.4.3.tgz#3a01df117c5705cf89a84c876b50c5a1fd427a21"
84+
integrity sha512-CqSKwFwefj4PzZ5n/iwad/bow2hTCh0FlNAeWLtQM3JA/NX/iYagIpWG2cf1bQKQ2c9gU2log5VUCrn7LDOs0w==
85+
dependencies:
86+
"@types/express" "*"
87+
88+
"@types/cors@^2.8.12":
89+
version "2.8.12"
90+
resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.12.tgz#6b2c510a7ad7039e98e7b8d3d6598f4359e5c080"
91+
integrity sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==
92+
8193
"@types/express-serve-static-core@^4.17.18":
8294
version "4.17.28"
8395
resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz#c47def9f34ec81dc6328d0b1b5303d1ec98d86b8"
@@ -87,7 +99,7 @@
8799
"@types/qs" "*"
88100
"@types/range-parser" "*"
89101

90-
"@types/express@^4.17.13":
102+
"@types/express@*", "@types/express@^4.17.13":
91103
version "4.17.13"
92104
resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.13.tgz#a76e2995728999bab51a33fabce1d705a3709034"
93105
integrity sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==
@@ -114,6 +126,13 @@
114126
resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a"
115127
integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==
116128

129+
"@types/morgan@^1.9.3":
130+
version "1.9.3"
131+
resolved "https://registry.yarnpkg.com/@types/morgan/-/morgan-1.9.3.tgz#ae04180dff02c437312bc0cfb1e2960086b2f540"
132+
integrity sha512-BiLcfVqGBZCyNCnCH3F4o2GmDLrpy0HeBVnNlyZG4fo88ZiE9SoiBe3C+2ezuwbjlEyT+PDZ17//TAlRxAn75Q==
133+
dependencies:
134+
"@types/node" "*"
135+
117136
"@types/node@*", "@types/node@^17.0.31":
118137
version "17.0.31"
119138
resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.31.tgz#a5bb84ecfa27eec5e1c802c6bbf8139bdb163a5d"
@@ -178,6 +197,13 @@ balanced-match@^1.0.0:
178197
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
179198
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
180199

200+
basic-auth@~2.0.1:
201+
version "2.0.1"
202+
resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-2.0.1.tgz#b998279bf47ce38344b4f3cf916d4679bbf51e3a"
203+
integrity sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==
204+
dependencies:
205+
safe-buffer "5.1.2"
206+
181207
bcryptjs@^2.4.3:
182208
version "2.4.3"
183209
resolved "https://registry.yarnpkg.com/bcryptjs/-/bcryptjs-2.4.3.tgz#9ab5627b93e60621ff7cdac5da9733027df1d0cb"
@@ -288,16 +314,37 @@ content-type@~1.0.4:
288314
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
289315
integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
290316

317+
cookie-parser@^1.4.6:
318+
version "1.4.6"
319+
resolved "https://registry.yarnpkg.com/cookie-parser/-/cookie-parser-1.4.6.tgz#3ac3a7d35a7a03bbc7e365073a26074824214594"
320+
integrity sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==
321+
dependencies:
322+
cookie "0.4.1"
323+
cookie-signature "1.0.6"
324+
291325
cookie-signature@1.0.6:
292326
version "1.0.6"
293327
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
294328
integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw=
295329

330+
cookie@0.4.1:
331+
version "0.4.1"
332+
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1"
333+
integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==
334+
296335
cookie@0.5.0:
297336
version "0.5.0"
298337
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b"
299338
integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==
300339

340+
cors@^2.8.5:
341+
version "2.8.5"
342+
resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29"
343+
integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==
344+
dependencies:
345+
object-assign "^4"
346+
vary "^1"
347+
301348
create-require@^1.1.0:
302349
version "1.1.1"
303350
resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333"
@@ -310,7 +357,7 @@ debug@2.6.9:
310357
dependencies:
311358
ms "2.0.0"
312359

313-
depd@2.0.0:
360+
depd@2.0.0, depd@~2.0.0:
314361
version "2.0.0"
315362
resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
316363
integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==
@@ -697,6 +744,17 @@ mkdirp@^1.0.4:
697744
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
698745
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
699746

747+
morgan@^1.10.0:
748+
version "1.10.0"
749+
resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.10.0.tgz#091778abc1fc47cd3509824653dae1faab6b17d7"
750+
integrity sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==
751+
dependencies:
752+
basic-auth "~2.0.1"
753+
debug "2.6.9"
754+
depd "~2.0.0"
755+
on-finished "~2.3.0"
756+
on-headers "~1.0.2"
757+
700758
ms@2.0.0:
701759
version "2.0.0"
702760
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
@@ -717,6 +775,11 @@ normalize-path@^3.0.0, normalize-path@~3.0.0:
717775
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
718776
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
719777

778+
object-assign@^4:
779+
version "4.1.1"
780+
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
781+
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
782+
720783
object-inspect@^1.9.0:
721784
version "1.12.0"
722785
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.0.tgz#6e2c120e868fd1fd18cb4f18c31741d0d6e776f0"
@@ -729,6 +792,18 @@ on-finished@2.4.1:
729792
dependencies:
730793
ee-first "1.1.1"
731794

795+
on-finished@~2.3.0:
796+
version "2.3.0"
797+
resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
798+
integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=
799+
dependencies:
800+
ee-first "1.1.1"
801+
802+
on-headers@~1.0.2:
803+
version "1.0.2"
804+
resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f"
805+
integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==
806+
732807
once@^1.3.0:
733808
version "1.4.0"
734809
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
@@ -834,6 +909,11 @@ rimraf@^2.6.1:
834909
dependencies:
835910
glob "^7.1.3"
836911

912+
safe-buffer@5.1.2:
913+
version "5.1.2"
914+
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
915+
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
916+
837917
safe-buffer@5.2.1, safe-buffer@^5.0.1:
838918
version "5.2.1"
839919
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
@@ -1013,7 +1093,7 @@ utils-merge@1.0.1:
10131093
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
10141094
integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
10151095

1016-
vary@~1.1.2:
1096+
vary@^1, vary@~1.1.2:
10171097
version "1.1.2"
10181098
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
10191099
integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=

0 commit comments

Comments
 (0)