refactor: auth jwt
This commit is contained in:
@@ -1,5 +1,3 @@
|
||||
import jwtoken from 'jsonwebtoken'
|
||||
|
||||
import {
|
||||
CanActivate,
|
||||
ExecutionContext,
|
||||
@@ -7,8 +5,10 @@ import {
|
||||
UnauthorizedException,
|
||||
} from '@nestjs/common'
|
||||
|
||||
import { __secret, isTest } from '~/global/env.global'
|
||||
import { isTest } from '~/global/env.global'
|
||||
import { mockUser1 } from '~/mock/user.mock'
|
||||
import { ConfigsService } from '~/modules/configs/configs.service'
|
||||
import { JWTService } from '~/processors/helper/helper.jwt.service'
|
||||
import { getNestExecutionContextRequest } from '~/transformers/get-req.transformer'
|
||||
|
||||
/**
|
||||
@@ -17,13 +17,13 @@ import { getNestExecutionContextRequest } from '~/transformers/get-req.transform
|
||||
|
||||
@Injectable()
|
||||
export class AuthGuard implements CanActivate {
|
||||
constructor(
|
||||
protected readonly jwtService: JWTService,
|
||||
protected readonly configs: ConfigsService,
|
||||
) {}
|
||||
async canActivate(context: ExecutionContext): Promise<any> {
|
||||
const request = this.getRequest(context)
|
||||
|
||||
if (typeof request.user !== 'undefined') {
|
||||
return true
|
||||
}
|
||||
|
||||
/// for e2e-test mock user
|
||||
if (isTest) {
|
||||
request.user = { ...mockUser1 }
|
||||
@@ -31,18 +31,21 @@ export class AuthGuard implements CanActivate {
|
||||
}
|
||||
const query = request.query as any
|
||||
const headers = request.headers
|
||||
const Authorization =
|
||||
const Authorization: string =
|
||||
headers.authorization || headers.Authorization || query.token
|
||||
|
||||
if (!Authorization) {
|
||||
throw new UnauthorizedException()
|
||||
}
|
||||
const jwt = Authorization.replace('Bearer ', '')
|
||||
try {
|
||||
const payload = jwtoken.verify(jwt, __secret)
|
||||
} catch {
|
||||
const jwt = Authorization.replace(/[Bb]earer /, '')
|
||||
const ok = await this.jwtService.verify(jwt)
|
||||
if (!ok) {
|
||||
throw new UnauthorizedException()
|
||||
}
|
||||
|
||||
request.user = await this.configs.getMaster()
|
||||
request.token = jwt
|
||||
return true
|
||||
}
|
||||
|
||||
getRequest(context: ExecutionContext) {
|
||||
|
||||
@@ -1,49 +1,35 @@
|
||||
/*
|
||||
* @Author: Innei
|
||||
* @Date: 2020-11-24 16:20:37
|
||||
* @LastEditTime: 2021-03-21 18:13:17
|
||||
* @LastEditors: Innei
|
||||
* @FilePath: /server/apps/server/src/auth/roles.guard.ts
|
||||
* Mark: Coding with Love
|
||||
*/
|
||||
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'
|
||||
import { AuthGuard } from '@nestjs/passport'
|
||||
|
||||
import { isTest } from '~/global/env.global'
|
||||
import { AuthService } from '~/modules/auth/auth.service'
|
||||
import { ConfigsService } from '~/modules/configs/configs.service'
|
||||
import { JWTService } from '~/processors/helper/helper.jwt.service'
|
||||
import { getNestExecutionContextRequest } from '~/transformers/get-req.transformer'
|
||||
|
||||
import { AuthGuard } from './auth.guard'
|
||||
|
||||
/**
|
||||
* 区分游客和主人的守卫
|
||||
*/
|
||||
|
||||
@Injectable()
|
||||
export class RolesGuard extends AuthGuard('jwt') implements CanActivate {
|
||||
constructor(private readonly authService: AuthService) {
|
||||
super(authService)
|
||||
export class RolesGuard extends AuthGuard implements CanActivate {
|
||||
constructor(
|
||||
protected readonly jwtService: JWTService,
|
||||
protected readonly configs: ConfigsService,
|
||||
) {
|
||||
super(jwtService, configs)
|
||||
}
|
||||
async canActivate(context: ExecutionContext): Promise<boolean> {
|
||||
let isMaster = false
|
||||
const request = this.getRequest(context)
|
||||
const authorization = request.headers.authorization
|
||||
if (authorization) {
|
||||
let isMaster = false
|
||||
try {
|
||||
isMaster = (await super.canActivate(context)) as boolean
|
||||
} catch {}
|
||||
// FIXME test env
|
||||
if (!isMaster && !isTest) {
|
||||
const [isValidToken, userModel] =
|
||||
await this.authService.verifyCustomToken(authorization as string)
|
||||
if (isValidToken) {
|
||||
request.user = userModel!
|
||||
await super.canActivate(context)
|
||||
isMaster = true
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line no-empty
|
||||
} catch {}
|
||||
|
||||
request.isGuest = !isMaster
|
||||
request.isMaster = isMaster
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
@@ -1,32 +1,4 @@
|
||||
import cluster from 'cluster'
|
||||
import { machineIdSync } from 'node-machine-id'
|
||||
|
||||
import { CLUSTER, SECURITY } from '~/app.config'
|
||||
|
||||
export const isDev = process.env.NODE_ENV == 'development'
|
||||
|
||||
export const isTest = !!process.env.TEST
|
||||
export const cwd = process.cwd()
|
||||
|
||||
const getMachineId = () => {
|
||||
const id = machineIdSync()
|
||||
|
||||
if (isDev && cluster.isPrimary) {
|
||||
console.log(id)
|
||||
}
|
||||
return id
|
||||
}
|
||||
export const __secret: any =
|
||||
SECURITY.jwtSecret ||
|
||||
Buffer.from(getMachineId()).toString('base64').slice(0, 15) ||
|
||||
'asjhczxiucipoiopiqm2376'
|
||||
|
||||
if (isDev && cluster.isPrimary) {
|
||||
console.log(__secret)
|
||||
}
|
||||
if (!CLUSTER.enable || cluster.isPrimary) {
|
||||
console.log(
|
||||
'JWT Secret start with :',
|
||||
__secret.slice(0, 5) + '*'.repeat(__secret.length - 5),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ export const mockUser1: UserModel = {
|
||||
name: 'John Doe',
|
||||
mail: 'example@ee.com',
|
||||
password: '**********',
|
||||
authCode: '*****',
|
||||
|
||||
username: 'johndoe',
|
||||
created: new Date('2021/1/1 10:00:11'),
|
||||
}
|
||||
@@ -15,7 +15,7 @@ export const mockUser2: UserModel = {
|
||||
name: 'Shawn Carter',
|
||||
mail: 'example@ee.com',
|
||||
password: '**********',
|
||||
authCode: '*****',
|
||||
|
||||
username: 'shawn',
|
||||
created: new Date('2020/10/10 19:22:22'),
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
import { Controller, Delete, Get, HttpCode, Query, Scope } from '@nestjs/common'
|
||||
import { Controller, Delete, Get, HttpCode, Query } from '@nestjs/common'
|
||||
|
||||
import { Auth } from '~/common/decorator/auth.decorator'
|
||||
import { Paginator } from '~/common/decorator/http.decorator'
|
||||
@@ -14,7 +14,7 @@ import { getTodayEarly, getWeekStart } from '~/utils/time.util'
|
||||
import { AnalyzeDto } from './analyze.dto'
|
||||
import { AnalyzeService } from './analyze.service'
|
||||
|
||||
@Controller({ path: 'analyze', scope: Scope.REQUEST })
|
||||
@Controller({ path: 'analyze' })
|
||||
@ApiName
|
||||
@Auth()
|
||||
export class AnalyzeController {
|
||||
|
||||
@@ -15,7 +15,6 @@ import {
|
||||
NotFoundException,
|
||||
Post,
|
||||
Query,
|
||||
Scope,
|
||||
} from '@nestjs/common'
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter'
|
||||
import { ApiBearerAuth, ApiOperation } from '@nestjs/swagger'
|
||||
@@ -41,7 +40,6 @@ export class TokenDto {
|
||||
|
||||
@Controller({
|
||||
path: 'auth',
|
||||
scope: Scope.REQUEST,
|
||||
})
|
||||
@ApiName
|
||||
export class AuthController {
|
||||
@@ -66,7 +64,7 @@ export class AuthController {
|
||||
if (typeof token === 'string') {
|
||||
return await this.authService
|
||||
.verifyCustomToken(token)
|
||||
.then(([isValid, user]) => isValid)
|
||||
.then(([isValid]) => isValid)
|
||||
}
|
||||
if (id && typeof id === 'string' && isMongoId(id)) {
|
||||
return await this.authService.getTokenSecret(id)
|
||||
|
||||
@@ -3,50 +3,28 @@ import { isDate, omit } from 'lodash'
|
||||
import { customAlphabet } from 'nanoid/async'
|
||||
|
||||
import { Injectable } from '@nestjs/common'
|
||||
import { JwtService } from '@nestjs/jwt'
|
||||
import { ReturnModelType } from '@typegoose/typegoose'
|
||||
|
||||
import { MasterLostException } from '~/common/exceptions/master-lost.exception'
|
||||
import { alphabet } from '~/constants/other.constant'
|
||||
import {
|
||||
TokenModel,
|
||||
UserModel as User,
|
||||
UserDocument,
|
||||
UserModel,
|
||||
} from '~/modules/user/user.model'
|
||||
import { JWTService } from '~/processors/helper/helper.jwt.service'
|
||||
import { InjectModel } from '~/transformers/model.transformer'
|
||||
|
||||
import { TokenDto } from './auth.controller'
|
||||
import { JwtPayload } from './interfaces/jwt-payload.interface'
|
||||
|
||||
@Injectable()
|
||||
export class AuthService {
|
||||
constructor(
|
||||
@InjectModel(User) private readonly userModel: ReturnModelType<typeof User>,
|
||||
private readonly jwtService: JwtService,
|
||||
private readonly jwtService: JWTService,
|
||||
) {}
|
||||
|
||||
async signToken(_id: string) {
|
||||
const user = await this.userModel.findById(_id).select('authCode')
|
||||
if (!user) {
|
||||
throw new MasterLostException()
|
||||
}
|
||||
const authCode = user.authCode
|
||||
const payload = {
|
||||
_id,
|
||||
authCode,
|
||||
}
|
||||
|
||||
return this.jwtService.sign(payload)
|
||||
}
|
||||
async verifyPayload(payload: JwtPayload): Promise<UserDocument | null> {
|
||||
const user = await this.userModel.findById(payload._id).select('+authCode')
|
||||
|
||||
if (!user) {
|
||||
throw new MasterLostException()
|
||||
}
|
||||
|
||||
return user && user.authCode === payload.authCode ? user : null
|
||||
get jwtServicePublic() {
|
||||
return this.jwtService
|
||||
}
|
||||
|
||||
private async getAccessTokens() {
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
export interface JwtPayload {
|
||||
_id: string
|
||||
authCode: string
|
||||
}
|
||||
@@ -12,7 +12,6 @@ import {
|
||||
Post,
|
||||
Query,
|
||||
Req,
|
||||
Scope,
|
||||
UnprocessableEntityException,
|
||||
} from '@nestjs/common'
|
||||
import { ApiProperty, ApiResponseProperty } from '@nestjs/swagger'
|
||||
@@ -26,7 +25,7 @@ import { getMediumDateTime } from '~/utils'
|
||||
|
||||
import { BackupService } from './backup.service'
|
||||
|
||||
@Controller({ path: 'backups', scope: Scope.REQUEST })
|
||||
@Controller({ path: 'backups' })
|
||||
@ApiName
|
||||
@Auth()
|
||||
@BanInDemo
|
||||
|
||||
@@ -12,7 +12,6 @@ import {
|
||||
Post,
|
||||
Query,
|
||||
Res,
|
||||
Scope,
|
||||
UnprocessableEntityException,
|
||||
} from '@nestjs/common'
|
||||
import { Reflector } from '@nestjs/core'
|
||||
@@ -34,7 +33,6 @@ import { LogQueryDto, LogTypeDto } from './health.dto'
|
||||
|
||||
@Controller({
|
||||
path: 'health',
|
||||
scope: Scope.REQUEST,
|
||||
})
|
||||
@Auth()
|
||||
@ApiName
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Controller, Get, Scope } from '@nestjs/common'
|
||||
import { Controller, Get } from '@nestjs/common'
|
||||
|
||||
import { Auth } from '~/common/decorator/auth.decorator'
|
||||
import { ApiName } from '~/common/decorator/openapi.decorator'
|
||||
@@ -7,7 +7,7 @@ import { PTYService } from './pty.service'
|
||||
|
||||
@ApiName
|
||||
@Auth()
|
||||
@Controller({ path: 'pty', scope: Scope.REQUEST })
|
||||
@Controller({ path: 'pty' })
|
||||
export class PTYController {
|
||||
constructor(private readonly service: PTYService) {}
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ import { nanoid } from 'nanoid'
|
||||
import { IPty, spawn } from 'node-pty'
|
||||
import { Socket } from 'socket.io'
|
||||
|
||||
import { JwtService } from '@nestjs/jwt'
|
||||
import {
|
||||
GatewayMetadata,
|
||||
OnGatewayConnection,
|
||||
@@ -20,6 +19,7 @@ import { AuthService } from '~/modules/auth/auth.service'
|
||||
import { ConfigsService } from '~/modules/configs/configs.service'
|
||||
import { CacheService } from '~/processors/cache/cache.service'
|
||||
import { createAuthGateway } from '~/processors/gateway/shared/auth.gateway'
|
||||
import { JWTService } from '~/processors/helper/helper.jwt.service'
|
||||
import { getIp, getRedisKey } from '~/utils'
|
||||
|
||||
const AuthGateway = createAuthGateway({ namespace: 'pty', authway: 'jwt' })
|
||||
@@ -29,7 +29,7 @@ export class PTYGateway
|
||||
implements OnGatewayConnection, OnGatewayDisconnect
|
||||
{
|
||||
constructor(
|
||||
protected readonly jwtService: JwtService,
|
||||
protected readonly jwtService: JWTService,
|
||||
protected readonly authService: AuthService,
|
||||
protected readonly cacheService: CacheService,
|
||||
protected readonly configService: ConfigsService,
|
||||
|
||||
@@ -4,6 +4,7 @@ import { ApiOperation } from '@nestjs/swagger'
|
||||
import { Auth } from '~/common/decorator/auth.decorator'
|
||||
import { HttpCache } from '~/common/decorator/cache.decorator'
|
||||
import { CurrentUser } from '~/common/decorator/current-user.decorator'
|
||||
import { BanInDemo } from '~/common/decorator/demo.decorator'
|
||||
import { IpLocation, IpRecord } from '~/common/decorator/ip.decorator'
|
||||
import { ApiName } from '~/common/decorator/openapi.decorator'
|
||||
import { IsMaster } from '~/common/decorator/role.decorator'
|
||||
@@ -46,7 +47,7 @@ export class UserController {
|
||||
const avatar = user.avatar ?? getAvatar(mail)
|
||||
|
||||
return {
|
||||
token: await this.authService.signToken(user._id),
|
||||
token: this.authService.jwtServicePublic.sign(user._id),
|
||||
...footstep,
|
||||
name,
|
||||
username,
|
||||
@@ -71,6 +72,7 @@ export class UserController {
|
||||
@ApiOperation({ summary: '修改主人的信息' })
|
||||
@Auth()
|
||||
@HttpCache.disable
|
||||
@BanInDemo
|
||||
async patchMasterData(
|
||||
@Body() body: UserPatchDto,
|
||||
@CurrentUser() user: UserDocument,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
||||
import { compareSync } from 'bcrypt'
|
||||
import { nanoid } from 'nanoid'
|
||||
|
||||
import {
|
||||
BadRequestException,
|
||||
@@ -15,7 +14,7 @@ import { MasterLostException } from '~/common/exceptions/master-lost.exception'
|
||||
import { RedisKeys } from '~/constants/cache.constant'
|
||||
import { CacheService } from '~/processors/cache/cache.service'
|
||||
import { InjectModel } from '~/transformers/model.transformer'
|
||||
import { banInDemo, getAvatar, sleep } from '~/utils'
|
||||
import { getAvatar, sleep } from '~/utils'
|
||||
import { getRedisKey } from '~/utils/redis.util'
|
||||
|
||||
import { AuthService } from '../auth/auth.service'
|
||||
@@ -82,7 +81,7 @@ export class UserService {
|
||||
|
||||
// @ts-ignore
|
||||
const res = await this.userModel.create({ ...model })
|
||||
const token = await this.authService.signToken(res._id)
|
||||
const token = await this.authService.jwtServicePublic.sign(res._id)
|
||||
return { token, username: res.username }
|
||||
}
|
||||
|
||||
@@ -94,7 +93,6 @@ export class UserService {
|
||||
* @param {Partial} data - 部分修改数据
|
||||
*/
|
||||
async patchUserData(user: UserDocument, data: Partial<UserModel>) {
|
||||
banInDemo()
|
||||
const { password } = data
|
||||
const doc = { ...data }
|
||||
if (password !== undefined) {
|
||||
@@ -113,9 +111,8 @@ export class UserService {
|
||||
throw new UnprocessableEntityException('密码可不能和原来的一样哦')
|
||||
}
|
||||
|
||||
// 2. 认证码重新生成
|
||||
const newCode = nanoid(10)
|
||||
doc.authCode = newCode
|
||||
// 2. 撤销所有 token
|
||||
await this.authService.jwtServicePublic.invokeAll()
|
||||
}
|
||||
return await this.userModel.updateOne({ _id: user._id }, doc)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { resolve } from 'path'
|
||||
import SocketIO, { Socket } from 'socket.io'
|
||||
|
||||
import { JwtService } from '@nestjs/jwt'
|
||||
import {
|
||||
GatewayMetadata,
|
||||
OnGatewayConnection,
|
||||
@@ -12,6 +11,7 @@ import {
|
||||
|
||||
import { LOG_DIR } from '~/constants/path.constant'
|
||||
import { CacheService } from '~/processors/cache/cache.service'
|
||||
import { JWTService } from '~/processors/helper/helper.jwt.service'
|
||||
|
||||
import { BusinessEvents } from '../../../constants/business-event.constant'
|
||||
import { AuthService } from '../../../modules/auth/auth.service'
|
||||
@@ -24,7 +24,7 @@ export class AdminEventsGateway
|
||||
implements OnGatewayConnection, OnGatewayDisconnect
|
||||
{
|
||||
constructor(
|
||||
protected readonly jwtService: JwtService,
|
||||
protected readonly jwtService: JWTService,
|
||||
protected readonly authService: AuthService,
|
||||
private readonly cacheService: CacheService,
|
||||
) {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Namespace, Socket } from 'socket.io'
|
||||
|
||||
import { OnEvent } from '@nestjs/event-emitter'
|
||||
import { JwtService } from '@nestjs/jwt'
|
||||
import {
|
||||
OnGatewayConnection,
|
||||
OnGatewayDisconnect,
|
||||
@@ -12,6 +11,7 @@ import { Emitter } from '@socket.io/redis-emitter'
|
||||
import { EventBusEvents } from '~/constants/event-bus.constant'
|
||||
import { AuthService } from '~/modules/auth/auth.service'
|
||||
import { CacheService } from '~/processors/cache/cache.service'
|
||||
import { JWTService } from '~/processors/helper/helper.jwt.service'
|
||||
|
||||
import { BusinessEvents } from '../../../constants/business-event.constant'
|
||||
import { BoardcastBaseGateway } from '../base.gateway'
|
||||
@@ -33,7 +33,7 @@ export const createAuthGateway = (
|
||||
const { namespace, authway = 'all' } = options
|
||||
class AuthGateway extends BoardcastBaseGateway implements IAuthGateway {
|
||||
constructor(
|
||||
protected readonly jwtService: JwtService,
|
||||
protected readonly jwtService: JWTService,
|
||||
protected readonly authService: AuthService,
|
||||
private readonly cacheService: CacheService,
|
||||
) {
|
||||
@@ -66,9 +66,9 @@ export const createAuthGateway = (
|
||||
|
||||
const validJwt = async () => {
|
||||
try {
|
||||
const payload = this.jwtService.verify(token)
|
||||
const user = await this.authService.verifyPayload(payload)
|
||||
if (!user) {
|
||||
const ok = await this.jwtService.verify(token)
|
||||
|
||||
if (!ok) {
|
||||
return false
|
||||
}
|
||||
} catch {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { JwtService } from '@nestjs/jwt'
|
||||
import {
|
||||
GatewayMetadata,
|
||||
OnGatewayConnection,
|
||||
@@ -7,6 +6,7 @@ import {
|
||||
} from '@nestjs/websockets'
|
||||
|
||||
import { CacheService } from '~/processors/cache/cache.service'
|
||||
import { JWTService } from '~/processors/helper/helper.jwt.service'
|
||||
|
||||
import { AuthService } from '../../../modules/auth/auth.service'
|
||||
import { createAuthGateway } from '../shared/auth.gateway'
|
||||
@@ -22,7 +22,7 @@ export class SystemEventsGateway
|
||||
implements OnGatewayConnection, OnGatewayDisconnect
|
||||
{
|
||||
constructor(
|
||||
protected readonly jwtService: JwtService,
|
||||
protected readonly jwtService: JWTService,
|
||||
protected readonly authService: AuthService,
|
||||
private readonly cacheService: CacheService,
|
||||
) {
|
||||
|
||||
@@ -10,51 +10,61 @@ import { getRedisKey, md5 } from '~/utils'
|
||||
|
||||
import { CacheService } from '../cache/cache.service'
|
||||
|
||||
@Injectable()
|
||||
export class JWTService {
|
||||
private secret: string
|
||||
constructor(private readonly cacheService: CacheService) {
|
||||
this.init()
|
||||
}
|
||||
|
||||
private init() {
|
||||
const getMachineId = () => {
|
||||
const getMachineId = () => {
|
||||
const id = machineIdSync()
|
||||
|
||||
if (isDev && cluster.isPrimary) {
|
||||
console.log(id)
|
||||
}
|
||||
return id
|
||||
}
|
||||
this.secret =
|
||||
}
|
||||
const secret =
|
||||
SECURITY.jwtSecret ||
|
||||
Buffer.from(getMachineId()).toString('base64').slice(0, 15) ||
|
||||
'asjhczxiucipoiopiqm2376'
|
||||
|
||||
if (isDev && cluster.isPrimary) {
|
||||
console.log(this.secret)
|
||||
}
|
||||
if (!CLUSTER.enable || cluster.isPrimary) {
|
||||
if (isDev && cluster.isPrimary) {
|
||||
console.log(secret)
|
||||
}
|
||||
if (!CLUSTER.enable || cluster.isPrimary) {
|
||||
console.log(
|
||||
'JWT Secret start with :',
|
||||
this.secret.slice(0, 5) + '*'.repeat(this.secret.length - 5),
|
||||
secret.slice(0, 5) + '*'.repeat(secret.length - 5),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class JWTService {
|
||||
constructor(private readonly cacheService: CacheService) {}
|
||||
|
||||
async verify(token: string) {
|
||||
try {
|
||||
verify(token, this.secret)
|
||||
verify(token, secret)
|
||||
return await this.isTokenInRedis(token)
|
||||
} catch {
|
||||
} catch (er) {
|
||||
console.debug(er, token)
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
async isTokenInRedis(id: string) {
|
||||
async isTokenInRedis(token: string) {
|
||||
const redis = this.cacheService.getClient()
|
||||
const key = getRedisKey(RedisKeys.JWTStore)
|
||||
const token = await redis.sismember(key, md5(id))
|
||||
return !!token
|
||||
const has = await redis.sismember(key, md5(token))
|
||||
return !!has
|
||||
}
|
||||
|
||||
async invokeToken(token: string) {
|
||||
const redis = this.cacheService.getClient()
|
||||
const key = getRedisKey(RedisKeys.JWTStore)
|
||||
await redis.srem(key, md5(token))
|
||||
}
|
||||
|
||||
async invokeAll() {
|
||||
const redis = this.cacheService.getClient()
|
||||
const key = getRedisKey(RedisKeys.JWTStore)
|
||||
await redis.del(key)
|
||||
}
|
||||
|
||||
async storeTokenInRedis(token: string) {
|
||||
@@ -62,8 +72,8 @@ export class JWTService {
|
||||
await redis.sadd(getRedisKey(RedisKeys.JWTStore), md5(token))
|
||||
}
|
||||
|
||||
sign(id: string, options: SignOptions = { expiresIn: '7d' }): string {
|
||||
const token = sign({ id }, this.secret, options)
|
||||
sign(id: string, options: SignOptions = { expiresIn: '7d' }) {
|
||||
const token = sign({ id }, secret, options)
|
||||
this.storeTokenInRedis(token)
|
||||
return token
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import { EmailService } from './helper.email.service'
|
||||
import { EventManagerService } from './helper.event.service'
|
||||
import { HttpService } from './helper.http.service'
|
||||
import { ImageService } from './helper.image.service'
|
||||
import { JWTService } from './helper.jwt.service'
|
||||
import { TextMacroService } from './helper.macro.service'
|
||||
import { TaskQueueService } from './helper.tq.service'
|
||||
import { UploadService } from './helper.upload.service'
|
||||
@@ -30,6 +31,7 @@ const providers: Provider<any>[] = [
|
||||
EmailService,
|
||||
EventManagerService,
|
||||
HttpService,
|
||||
JWTService,
|
||||
ImageService,
|
||||
TaskQueueService,
|
||||
TextMacroService,
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
import { JwtModule } from '@nestjs/jwt'
|
||||
import { PassportModule } from '@nestjs/passport'
|
||||
import { Test } from '@nestjs/testing'
|
||||
import { getModelToken } from '~/transformers/model.transformer'
|
||||
import { SECURITY } from '~/app.config'
|
||||
|
||||
import { AuthService } from '~/modules/auth/auth.service'
|
||||
import { JwtStrategy } from '~/modules/auth/jwt.strategy'
|
||||
import { UserModel } from '~/modules/user/user.model'
|
||||
import { getModelToken } from '~/transformers/model.transformer'
|
||||
|
||||
describe('Test AuthService', () => {
|
||||
let service: AuthService
|
||||
@@ -18,24 +15,8 @@ describe('Test AuthService', () => {
|
||||
authCode: 'authCode',
|
||||
}
|
||||
beforeAll(async () => {
|
||||
const __secret: any = SECURITY.jwtSecret || 'asjhczxiucipoiopiqm2376'
|
||||
|
||||
const jwtModule = JwtModule.registerAsync({
|
||||
useFactory() {
|
||||
return {
|
||||
secret: __secret,
|
||||
signOptions: {
|
||||
expiresIn: SECURITY.jwtExpire,
|
||||
algorithm: 'HS256',
|
||||
},
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
const moduleRef = Test.createTestingModule({
|
||||
imports: [jwtModule, PassportModule],
|
||||
providers: [
|
||||
JwtStrategy,
|
||||
AuthService,
|
||||
{
|
||||
provide: getModelToken(UserModel.name),
|
||||
@@ -55,17 +36,8 @@ describe('Test AuthService', () => {
|
||||
service = app.get(AuthService)
|
||||
})
|
||||
|
||||
it('should sign token', async () => {
|
||||
const _token = await service.signToken('1')
|
||||
it('should sign token', () => {
|
||||
const _token = service.jwtServicePublic.sign('1')
|
||||
expect(_token).toBeDefined()
|
||||
})
|
||||
|
||||
it('should verifyied', async () => {
|
||||
const user = await service.verifyPayload({
|
||||
_id: '1',
|
||||
authCode: 'authCode',
|
||||
})
|
||||
expect(user).toBeDefined()
|
||||
expect(user).toEqual(mockUser)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user