Skip to content

Commit

Permalink
Verify role (#13)
Browse files Browse the repository at this point in the history
* Add verifyRoles middleware

* Verfiy roles

* remove test code
  • Loading branch information
likui628 authored Sep 28, 2024
1 parent 111f093 commit 0fb5fb2
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 9 deletions.
2 changes: 1 addition & 1 deletion prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ model User {
email String @unique
name String?
password String
role Role[]
role Role? @default(USER)
isVerified Boolean
}

Expand Down
File renamed without changes.
4 changes: 2 additions & 2 deletions src/config/passport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import {
StrategyOptions,
} from 'passport-jwt'
import { prisma } from '../utils'
import config from './config'
import env from './env'

const options: StrategyOptions = {
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: config.ACCESS_TOKEN_SECRET,
secretOrKey: env.ACCESS_TOKEN_SECRET,
}

export const jwtStrategy = new JwtStrategy(
Expand Down
12 changes: 12 additions & 0 deletions src/config/roles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Role } from '@prisma/client'

const allRoles: Record<Role, string[]> = {
[Role.USER]: [],
[Role.ADMIN]: ['manageUsers'],
}

export const roles = Object.keys(allRoles) as Role[]

export const roleRights = new Map<Role, string[]>(
Object.entries(allRoles) as [Role, string[]][],
)
4 changes: 2 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import app from './app'
import config from './config/config'
import env from './config/env'

const port = config.PORT || 5000
const port = env.PORT || 5000
app.listen(port, () => {
/* eslint-disable no-console */
console.log(`Listening: http://localhost:${port}`)
Expand Down
32 changes: 32 additions & 0 deletions src/middlewares/verify-roles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { NextFunction, Request, Response } from 'express'
import { Role } from '@prisma/client'
import { errorResponse } from '../utils'
import { roleRights } from '../config/roles'

declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace Express {
interface User {
role?: Role
}
}
}

export const verifyRoles = (...requiredRights: string[]) => {
return (req: Request, res: Response, next: NextFunction) => {
if (requiredRights.length) {
const userRole = req.user?.role
if (!userRole) {
return errorResponse(res, null, 403, 'Forbidden')
}
const userRights = roleRights.get(userRole) || []
const hasRequiredRights = requiredRights.every((r) =>
userRights.includes(r),
)
if (!hasRequiredRights) {
return errorResponse(res, null, 403, 'Forbidden')
}
}
next()
}
}
8 changes: 4 additions & 4 deletions src/services/token.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { User } from '@prisma/client'
import jwt from 'jsonwebtoken'
import config from '../config/config'
import env from '../config/env'

export const generateAuthTokens = (user: User) => {
const payload = { id: user.id, username: user.name }
const token = jwt.sign(payload, config.ACCESS_TOKEN_SECRET, {
const payload = { id: user.id, username: user.name, role: user.role }
const token = jwt.sign(payload, env.ACCESS_TOKEN_SECRET, {
expiresIn: '1h',
})

const refreshToken = jwt.sign(payload, config.REFRESH_TOKEN_SECRET, {
const refreshToken = jwt.sign(payload, env.REFRESH_TOKEN_SECRET, {
expiresIn: '7d',
})
return { token, refreshToken }
Expand Down

0 comments on commit 0fb5fb2

Please sign in to comment.