feat: add admin db query
This commit is contained in:
@@ -119,6 +119,7 @@
|
|||||||
"passport": "0.5.2",
|
"passport": "0.5.2",
|
||||||
"passport-jwt": "4.0.0",
|
"passport-jwt": "4.0.0",
|
||||||
"pluralize": "*",
|
"pluralize": "*",
|
||||||
|
"qs": "6.10.3",
|
||||||
"reflect-metadata": "0.1.13",
|
"reflect-metadata": "0.1.13",
|
||||||
"rxjs": "7.5.4",
|
"rxjs": "7.5.4",
|
||||||
"snakecase-keys": "5.1.2",
|
"snakecase-keys": "5.1.2",
|
||||||
@@ -148,12 +149,14 @@
|
|||||||
"@types/node": "16.11.26",
|
"@types/node": "16.11.26",
|
||||||
"@types/nodemailer": "6.4.4",
|
"@types/nodemailer": "6.4.4",
|
||||||
"@types/passport-jwt": "3.0.6",
|
"@types/passport-jwt": "3.0.6",
|
||||||
|
"@types/qs": "6.9.7",
|
||||||
"@types/ua-parser-js": "0.7.36",
|
"@types/ua-parser-js": "0.7.36",
|
||||||
"@vercel/ncc": "0.33.3",
|
"@vercel/ncc": "0.33.3",
|
||||||
"cron": "*",
|
"cron": "*",
|
||||||
"cross-env": "7.0.3",
|
"cross-env": "7.0.3",
|
||||||
"eslint": "*",
|
"eslint": "*",
|
||||||
"husky": "7.0.4",
|
"husky": "7.0.4",
|
||||||
|
"i": "0.3.7",
|
||||||
"ioredis": "4.28.5",
|
"ioredis": "4.28.5",
|
||||||
"jest": "27.5.1",
|
"jest": "27.5.1",
|
||||||
"lint-staged": "12.3.5",
|
"lint-staged": "12.3.5",
|
||||||
|
|||||||
18
pnpm-lock.yaml
generated
18
pnpm-lock.yaml
generated
@@ -44,6 +44,7 @@ specifiers:
|
|||||||
'@types/node': 16.11.26
|
'@types/node': 16.11.26
|
||||||
'@types/nodemailer': 6.4.4
|
'@types/nodemailer': 6.4.4
|
||||||
'@types/passport-jwt': 3.0.6
|
'@types/passport-jwt': 3.0.6
|
||||||
|
'@types/qs': 6.9.7
|
||||||
'@types/ua-parser-js': 0.7.36
|
'@types/ua-parser-js': 0.7.36
|
||||||
'@vercel/ncc': 0.33.3
|
'@vercel/ncc': 0.33.3
|
||||||
algoliasearch: 4.12.2
|
algoliasearch: 4.12.2
|
||||||
@@ -68,6 +69,7 @@ specifiers:
|
|||||||
get-image-colors: 4.0.1
|
get-image-colors: 4.0.1
|
||||||
html-minifier: 4.0.0
|
html-minifier: 4.0.0
|
||||||
husky: 7.0.4
|
husky: 7.0.4
|
||||||
|
i: 0.3.7
|
||||||
image-size: 1.0.1
|
image-size: 1.0.1
|
||||||
inquirer: '*'
|
inquirer: '*'
|
||||||
ioredis: 4.28.5
|
ioredis: 4.28.5
|
||||||
@@ -94,6 +96,7 @@ specifiers:
|
|||||||
passport-jwt: 4.0.0
|
passport-jwt: 4.0.0
|
||||||
pluralize: '*'
|
pluralize: '*'
|
||||||
prettier: 2.5.1
|
prettier: 2.5.1
|
||||||
|
qs: 6.10.3
|
||||||
redis-memory-server: 0.5.0
|
redis-memory-server: 0.5.0
|
||||||
reflect-metadata: 0.1.13
|
reflect-metadata: 0.1.13
|
||||||
rimraf: 3.0.2
|
rimraf: 3.0.2
|
||||||
@@ -169,6 +172,7 @@ dependencies:
|
|||||||
passport: 0.5.2
|
passport: 0.5.2
|
||||||
passport-jwt: 4.0.0
|
passport-jwt: 4.0.0
|
||||||
pluralize: 8.0.0
|
pluralize: 8.0.0
|
||||||
|
qs: 6.10.3
|
||||||
reflect-metadata: 0.1.13
|
reflect-metadata: 0.1.13
|
||||||
rxjs: 7.5.4
|
rxjs: 7.5.4
|
||||||
snakecase-keys: 5.1.2
|
snakecase-keys: 5.1.2
|
||||||
@@ -202,12 +206,14 @@ devDependencies:
|
|||||||
'@types/node': 16.11.26
|
'@types/node': 16.11.26
|
||||||
'@types/nodemailer': 6.4.4
|
'@types/nodemailer': 6.4.4
|
||||||
'@types/passport-jwt': 3.0.6
|
'@types/passport-jwt': 3.0.6
|
||||||
|
'@types/qs': 6.9.7
|
||||||
'@types/ua-parser-js': 0.7.36
|
'@types/ua-parser-js': 0.7.36
|
||||||
'@vercel/ncc': 0.33.3
|
'@vercel/ncc': 0.33.3
|
||||||
cron: 1.7.2
|
cron: 1.7.2
|
||||||
cross-env: 7.0.3
|
cross-env: 7.0.3
|
||||||
eslint: 8.10.0
|
eslint: 8.10.0
|
||||||
husky: 7.0.4
|
husky: 7.0.4
|
||||||
|
i: 0.3.7
|
||||||
ioredis: 4.28.5
|
ioredis: 4.28.5
|
||||||
jest: 27.5.1_ts-node@10.6.0
|
jest: 27.5.1_ts-node@10.6.0
|
||||||
lint-staged: 12.3.5
|
lint-staged: 12.3.5
|
||||||
@@ -4701,6 +4707,11 @@ packages:
|
|||||||
hasBin: true
|
hasBin: true
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/i/0.3.7:
|
||||||
|
resolution: {integrity: sha512-FYz4wlXgkQwIPqhzC5TdNMLSE5+GS1IIDJZY/1ZiEPCT2S3COUVZeT5OW4BmW4r5LHLQuOosSwsvnroG9GR59Q==}
|
||||||
|
engines: {node: '>=0.4'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/iconv-lite/0.4.24:
|
/iconv-lite/0.4.24:
|
||||||
resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==}
|
resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@@ -6985,6 +6996,13 @@ packages:
|
|||||||
resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==}
|
resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
|
||||||
|
/qs/6.10.3:
|
||||||
|
resolution: {integrity: sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==}
|
||||||
|
engines: {node: '>=0.6'}
|
||||||
|
dependencies:
|
||||||
|
side-channel: 1.0.4
|
||||||
|
dev: false
|
||||||
|
|
||||||
/qs/6.5.2:
|
/qs/6.5.2:
|
||||||
resolution: {integrity: sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==}
|
resolution: {integrity: sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==}
|
||||||
engines: {node: '>=0.6'}
|
engines: {node: '>=0.6'}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { AnalyzeInterceptor } from './common/interceptors/analyze.interceptor'
|
|||||||
import { HttpCacheInterceptor } from './common/interceptors/cache.interceptor'
|
import { HttpCacheInterceptor } from './common/interceptors/cache.interceptor'
|
||||||
import { CountingInterceptor } from './common/interceptors/counting.interceptor'
|
import { CountingInterceptor } from './common/interceptors/counting.interceptor'
|
||||||
import { JSONSerializeInterceptor } from './common/interceptors/json-serialize.interceptor'
|
import { JSONSerializeInterceptor } from './common/interceptors/json-serialize.interceptor'
|
||||||
|
import { QueryInterceptor } from './common/interceptors/query.interceptor'
|
||||||
import { ResponseInterceptor } from './common/interceptors/response.interceptor'
|
import { ResponseInterceptor } from './common/interceptors/response.interceptor'
|
||||||
import { AttachHeaderTokenMiddleware } from './common/middlewares/attach-auth.middleware'
|
import { AttachHeaderTokenMiddleware } from './common/middlewares/attach-auth.middleware'
|
||||||
import { AggregateModule } from './modules/aggregate/aggregate.module'
|
import { AggregateModule } from './modules/aggregate/aggregate.module'
|
||||||
@@ -85,7 +86,12 @@ import { LoggerModule } from './processors/logger/logger.module'
|
|||||||
providers: [
|
providers: [
|
||||||
{
|
{
|
||||||
provide: APP_INTERCEPTOR,
|
provide: APP_INTERCEPTOR,
|
||||||
useClass: HttpCacheInterceptor,
|
useClass: QueryInterceptor,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
provide: APP_INTERCEPTOR,
|
||||||
|
useClass: HttpCacheInterceptor, // 4
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
provide: APP_INTERCEPTOR,
|
provide: APP_INTERCEPTOR,
|
||||||
@@ -93,15 +99,15 @@ import { LoggerModule } from './processors/logger/logger.module'
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
provide: APP_INTERCEPTOR,
|
provide: APP_INTERCEPTOR,
|
||||||
useClass: CountingInterceptor,
|
useClass: CountingInterceptor, // 3
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
provide: APP_INTERCEPTOR,
|
provide: APP_INTERCEPTOR,
|
||||||
useClass: JSONSerializeInterceptor,
|
useClass: JSONSerializeInterceptor, // 2
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
provide: APP_INTERCEPTOR,
|
provide: APP_INTERCEPTOR,
|
||||||
useClass: ResponseInterceptor,
|
useClass: ResponseInterceptor, // 1
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import {
|
|||||||
NestInterceptor,
|
NestInterceptor,
|
||||||
} from '@nestjs/common'
|
} from '@nestjs/common'
|
||||||
import { ReturnModelType } from '@typegoose/typegoose'
|
import { ReturnModelType } from '@typegoose/typegoose'
|
||||||
import { FastifyRequest } from 'fastify'
|
|
||||||
import isbot from 'isbot'
|
import isbot from 'isbot'
|
||||||
import { InjectModel } from 'nestjs-typegoose'
|
import { InjectModel } from 'nestjs-typegoose'
|
||||||
import { Observable } from 'rxjs'
|
import { Observable } from 'rxjs'
|
||||||
@@ -21,6 +20,7 @@ import { RedisKeys } from '~/constants/cache.constant'
|
|||||||
import { AnalyzeModel } from '~/modules/analyze/analyze.model'
|
import { AnalyzeModel } from '~/modules/analyze/analyze.model'
|
||||||
import { OptionModel } from '~/modules/configs/configs.model'
|
import { OptionModel } from '~/modules/configs/configs.model'
|
||||||
import { CacheService } from '~/processors/cache/cache.service'
|
import { CacheService } from '~/processors/cache/cache.service'
|
||||||
|
import { getNestExecutionContextRequest } from '~/utils'
|
||||||
import { getIp } from '~/utils/ip.util'
|
import { getIp } from '~/utils/ip.util'
|
||||||
import { getRedisKey } from '~/utils/redis.util'
|
import { getRedisKey } from '~/utils/redis.util'
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ export class AnalyzeInterceptor implements NestInterceptor {
|
|||||||
next: CallHandler<any>,
|
next: CallHandler<any>,
|
||||||
): Promise<Observable<any>> {
|
): Promise<Observable<any>> {
|
||||||
const call$ = next.handle()
|
const call$ = next.handle()
|
||||||
const request = this.getRequest(context)
|
const request = getNestExecutionContextRequest(context)
|
||||||
if (!request) {
|
if (!request) {
|
||||||
return call$
|
return call$
|
||||||
}
|
}
|
||||||
@@ -130,12 +130,4 @@ export class AnalyzeInterceptor implements NestInterceptor {
|
|||||||
|
|
||||||
return call$
|
return call$
|
||||||
}
|
}
|
||||||
|
|
||||||
getRequest(context: ExecutionContext) {
|
|
||||||
const req = context.switchToHttp().getRequest<KV>()
|
|
||||||
if (req) {
|
|
||||||
return req as FastifyRequest & { user?: any }
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
35
src/common/interceptors/query.interceptor.ts
Normal file
35
src/common/interceptors/query.interceptor.ts
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import {
|
||||||
|
CallHandler,
|
||||||
|
ExecutionContext,
|
||||||
|
Injectable,
|
||||||
|
NestInterceptor,
|
||||||
|
} from '@nestjs/common'
|
||||||
|
import qs from 'qs'
|
||||||
|
import { Observable } from 'rxjs'
|
||||||
|
import { getNestExecutionContextRequest } from '~/utils'
|
||||||
|
/** 此拦截器用于转换 req.query.query -> js object,用于直接数据库查询,需要鉴权 */
|
||||||
|
@Injectable()
|
||||||
|
export class QueryInterceptor implements NestInterceptor {
|
||||||
|
intercept(
|
||||||
|
context: ExecutionContext,
|
||||||
|
next: CallHandler<any>,
|
||||||
|
): Observable<any> | Promise<Observable<any>> {
|
||||||
|
const request = getNestExecutionContextRequest(context)
|
||||||
|
const query = request.query as any
|
||||||
|
|
||||||
|
if (!query) {
|
||||||
|
return next.handle()
|
||||||
|
}
|
||||||
|
|
||||||
|
const queryObj = query.db_query
|
||||||
|
|
||||||
|
if (request.user) {
|
||||||
|
;(request.query as any).db_query =
|
||||||
|
typeof queryObj === 'string' ? qs.parse(queryObj) : queryObj
|
||||||
|
} else {
|
||||||
|
delete (request.query as any).db_query
|
||||||
|
}
|
||||||
|
|
||||||
|
return next.handle()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
import { Body, Controller, Post, Query } from '@nestjs/common'
|
import { Body, Controller, Get, Post, Query } from '@nestjs/common'
|
||||||
import { AdminEventsGateway } from '~/processors/gateway/admin/events.gateway'
|
import { AdminEventsGateway } from '~/processors/gateway/admin/events.gateway'
|
||||||
import { EventTypes } from '~/processors/gateway/events.types'
|
import { EventTypes } from '~/processors/gateway/events.types'
|
||||||
import { WebEventsGateway } from '~/processors/gateway/web/events.gateway'
|
import { WebEventsGateway } from '~/processors/gateway/web/events.gateway'
|
||||||
|
import { PagerDto } from '~/shared/dto/pager.dto'
|
||||||
|
|
||||||
@Controller('debug')
|
@Controller('debug')
|
||||||
export class DebugController {
|
export class DebugController {
|
||||||
@@ -9,6 +10,10 @@ export class DebugController {
|
|||||||
private readonly webEvent: WebEventsGateway,
|
private readonly webEvent: WebEventsGateway,
|
||||||
private readonly adminEvent: AdminEventsGateway,
|
private readonly adminEvent: AdminEventsGateway,
|
||||||
) {}
|
) {}
|
||||||
|
@Get('qs')
|
||||||
|
async qs(@Query() query: PagerDto) {
|
||||||
|
return query
|
||||||
|
}
|
||||||
|
|
||||||
@Post('/events')
|
@Post('/events')
|
||||||
async sendEvent(
|
async sendEvent(
|
||||||
|
|||||||
@@ -61,12 +61,12 @@ export class NoteController {
|
|||||||
@Paginator
|
@Paginator
|
||||||
@ApiOperation({ summary: '获取记录带分页器' })
|
@ApiOperation({ summary: '获取记录带分页器' })
|
||||||
async getNotes(@IsMaster() isMaster: boolean, @Query() query: NoteQueryDto) {
|
async getNotes(@IsMaster() isMaster: boolean, @Query() query: NoteQueryDto) {
|
||||||
const { size, select, page, sortBy, sortOrder, year } = query
|
const { size, select, page, sortBy, sortOrder, year, db_query } = query
|
||||||
const condition = {
|
const condition = {
|
||||||
...addHidePasswordAndHideCondition(isMaster),
|
...addHidePasswordAndHideCondition(isMaster),
|
||||||
...addYearCondition(year),
|
...addYearCondition(year),
|
||||||
}
|
}
|
||||||
return await this.noteService.model.paginate(condition, {
|
return await this.noteService.model.paginate(db_query ?? condition, {
|
||||||
limit: size,
|
limit: size,
|
||||||
page,
|
page,
|
||||||
select: isMaster
|
select: isMaster
|
||||||
|
|||||||
@@ -11,7 +11,11 @@ import {
|
|||||||
ValidateIf,
|
ValidateIf,
|
||||||
} from 'class-validator'
|
} from 'class-validator'
|
||||||
|
|
||||||
export class PagerDto {
|
class DbQueryDto {
|
||||||
|
@IsOptional()
|
||||||
|
db_query?: any
|
||||||
|
}
|
||||||
|
export class PagerDto extends DbQueryDto {
|
||||||
@Min(1)
|
@Min(1)
|
||||||
@Max(50)
|
@Max(50)
|
||||||
@IsInt()
|
@IsInt()
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import { ExecutionContext } from '@nestjs/common'
|
import { ExecutionContext } from '@nestjs/common'
|
||||||
import type { FastifyRequest } from 'fastify'
|
import type { FastifyRequest } from 'fastify'
|
||||||
|
import type { UserModel } from '~/modules/user/user.model'
|
||||||
export function getNestExecutionContextRequest(
|
export function getNestExecutionContextRequest(
|
||||||
context: ExecutionContext,
|
context: ExecutionContext,
|
||||||
): FastifyRequest & KV {
|
): FastifyRequest & { user?: UserModel } & KV {
|
||||||
return context.switchToHttp().getRequest<FastifyRequest>()
|
return context.switchToHttp().getRequest<FastifyRequest>()
|
||||||
// if (req) {
|
// if (req) {
|
||||||
// return req
|
// return req
|
||||||
|
|||||||
Reference in New Issue
Block a user