增加重要日志的记录
This commit is contained in:
parent
403f37ac12
commit
3034702f3f
@ -1,4 +1,4 @@
|
||||
import { permission, role, router } from 'decorators/router'
|
||||
import { role, router } from 'decorators/router'
|
||||
import BaseController, { ROLE_ANON } from 'common/base.controller'
|
||||
import { ZError } from 'common/ZError'
|
||||
import { NonceRecord } from 'models/NonceRecord'
|
||||
@ -9,7 +9,7 @@ import { User } from 'models/User'
|
||||
const LOGIN_TIP = 'This signature is just to verify your identity'
|
||||
export default class AccountController extends BaseController {
|
||||
@role(ROLE_ANON)
|
||||
@router('get /api/wallet/wallet_nonce')
|
||||
@router('get /api/user/login')
|
||||
async walletNonce(req, res) {
|
||||
let record = new NonceRecord()
|
||||
await record.save()
|
||||
@ -17,49 +17,65 @@ export default class AccountController extends BaseController {
|
||||
}
|
||||
// wallet login
|
||||
@role(ROLE_ANON)
|
||||
@router('post /api/wallet/wallet_login')
|
||||
@router('post /api/user/login')
|
||||
async loginWallet(req, res) {
|
||||
const { nonce, signature, account } = req.params
|
||||
logger.info(`wallet login::account:${account} nonce:${nonce} signature:${signature}`)
|
||||
if (!nonce || !signature || !account) {
|
||||
const { nonce, signature, address } = req.params
|
||||
logger.db('login', req)
|
||||
logger.info(`wallet login::address:${address} nonce:${nonce} signature:${signature}`)
|
||||
if (!nonce || !signature || !address) {
|
||||
throw new ZError(10, 'params mismatch')
|
||||
}
|
||||
let record = await NonceRecord.findById(nonce)
|
||||
if (!record || record.status !== 0) {
|
||||
throw new ZError(11, 'nonce invalid')
|
||||
}
|
||||
if (record.expired < Date.now()) {
|
||||
throw new ZError(12, 'nonce expired')
|
||||
}
|
||||
record.status = 1
|
||||
await record.save()
|
||||
const signObj = buildLoginSignMsg(nonce, LOGIN_TIP)
|
||||
const recover = recoverTypedSignatureV4(signObj, signature)
|
||||
if (recover !== account) {
|
||||
if (recover !== address) {
|
||||
throw new ZError(20, 'address mismatch')
|
||||
}
|
||||
let accountData = await User.findByAddress(account)
|
||||
let accountData = await User.insertOrUpdate({ address }, {})
|
||||
if (!accountData) {
|
||||
throw new ZError(11, 'user not found')
|
||||
}
|
||||
if (accountData.locked) {
|
||||
throw new ZError(12, 'user locked')
|
||||
}
|
||||
accountData.lastLogin = Date.now()
|
||||
await accountData.save()
|
||||
|
||||
const token = await res.jwtSign({ id: accountData.id })
|
||||
setImmediate(() => {
|
||||
NonceRecord.removeExpired()
|
||||
})
|
||||
return { token }
|
||||
}
|
||||
|
||||
@router('post /api/wallet/logout')
|
||||
async logout(req, res) {
|
||||
return {}
|
||||
}
|
||||
|
||||
@router('get /api/user/:uid/info')
|
||||
@router('get /api/user/status')
|
||||
async info(req) {
|
||||
let uid = req.params.uid
|
||||
const account = await User.findById(uid)
|
||||
return { account: account, user: req.user }
|
||||
let user = req.user
|
||||
return {}
|
||||
}
|
||||
|
||||
@router('post /api/user/claim')
|
||||
async claim(req, res) {
|
||||
return {}
|
||||
let user = req.user
|
||||
logger.db('claim', req)
|
||||
const {} = req.params
|
||||
const taskId = ''
|
||||
return { taskId }
|
||||
}
|
||||
|
||||
@router('get /api/user/claim/:taskId')
|
||||
async claimStatus(req, res) {
|
||||
const { taskId } = req.params
|
||||
const txHashList = []
|
||||
let status = 0
|
||||
return { status, txHashList }
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,9 @@
|
||||
import { LoggerQueue } from 'queue/logger.queue'
|
||||
|
||||
const level = process.env.NODE_ENV === 'production' ? 'info' : 'log'
|
||||
const logger = require('tracer').colorConsole({ dateformat: 'yyyy-mm-dd HH:MM:ss.L', level })
|
||||
logger.db = function (name: string, req: any, logObj?: any) {
|
||||
logObj = logObj || {}
|
||||
new LoggerQueue().addLog(name, req, logObj)
|
||||
}
|
||||
export default logger
|
||||
|
@ -2,11 +2,19 @@ import { getModelForClass, index, modelOptions, pre, prop } from '@typegoose/typ
|
||||
import { dbconn } from 'decorators/dbconn'
|
||||
import { BaseModule } from './Base'
|
||||
|
||||
const DEFAULT_EXPIRED = 1000 * 60 * 5
|
||||
@dbconn()
|
||||
@modelOptions({ schemaOptions: { collection: 'nonce_record', timestamps: true } })
|
||||
class NonceRecordClass extends BaseModule {
|
||||
@prop({ required: true, default: 0 })
|
||||
public status: number
|
||||
|
||||
@prop({ default: Date.now() + DEFAULT_EXPIRED })
|
||||
public expired: number
|
||||
|
||||
public static async removeExpired() {
|
||||
await NonceRecord.deleteMany({ expired: { $lt: Date.now() } })
|
||||
}
|
||||
}
|
||||
|
||||
export const NonceRecord = getModelForClass(NonceRecordClass, { existingConnection: NonceRecordClass['db'] })
|
||||
|
31
src/models/UserLog.ts
Normal file
31
src/models/UserLog.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import { dbconn } from 'decorators/dbconn'
|
||||
import { getModelForClass, index, modelOptions, mongoose, prop } from '@typegoose/typegoose'
|
||||
import { Severity } from '@typegoose/typegoose/lib/internal/constants'
|
||||
import { BaseModule } from './Base'
|
||||
|
||||
/**
|
||||
* 管理员操作记录
|
||||
*/
|
||||
@dbconn()
|
||||
@index({ user: 1 }, { unique: false })
|
||||
@index({ name: 1 }, { unique: false })
|
||||
@modelOptions({ schemaOptions: { collection: 'user_log', timestamps: true }, options: { allowMixed: Severity.ALLOW } })
|
||||
class UserLogClass extends BaseModule {
|
||||
@prop()
|
||||
public user: string
|
||||
@prop()
|
||||
public name: string
|
||||
@prop()
|
||||
public method: string
|
||||
@prop()
|
||||
public path: string
|
||||
@prop()
|
||||
public referer: string
|
||||
@prop()
|
||||
public user_agent: string
|
||||
@prop()
|
||||
public ip: string
|
||||
@prop({ type: mongoose.Schema.Types.Mixed })
|
||||
public params: any
|
||||
}
|
||||
export const UserLog = getModelForClass(UserLogClass, { existingConnection: UserLogClass['db'] })
|
39
src/queue/logger.queue.ts
Normal file
39
src/queue/logger.queue.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import { AsyncQueue, createAsyncQueue } from 'common/AsyncQueue'
|
||||
import { singleton } from 'decorators/singleton'
|
||||
import logger from 'logger/logger'
|
||||
import { UserLog } from 'models/UserLog'
|
||||
|
||||
@singleton
|
||||
export class LoggerQueue {
|
||||
private queue: AsyncQueue
|
||||
|
||||
constructor() {
|
||||
this.queue = createAsyncQueue()
|
||||
}
|
||||
|
||||
public addLog(name, req, logObj) {
|
||||
this.queue.push(async () => {
|
||||
const user = req.user
|
||||
const ip = req.headers['x-forwarded-for'] || req.ip
|
||||
const path = req.url
|
||||
const params = req.method === 'GET' ? req.query : req.body
|
||||
const dataObj = JSON.stringify(logObj) === '{}' ? params : logObj
|
||||
try {
|
||||
const history = new UserLog({
|
||||
user: user ? user.id : '',
|
||||
path: path,
|
||||
method: req.method,
|
||||
params: dataObj,
|
||||
referer: req.headers['referer'],
|
||||
user_agent: req.headers['user-agent'],
|
||||
ip,
|
||||
name,
|
||||
})
|
||||
await history.save()
|
||||
} catch (err) {
|
||||
logger.error('error add user log: ')
|
||||
logger.error(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user