Koa2 获取并存储用户操作日志

  有时候我们需要记录用户进行了哪些操作,比如删除、更新和添加。这部分是要呈献给用户的,所以一定不能直接把系统日志的一大坨给他们。
  系统后台采用了Koa2,数据库是mongo,借助mongoose操作数据库。

Model设计

  设计Log结构

const mongoose = require('../tool/db-util').mongoose
const Schema = mongoose.Schema

const logSchema = new Schema({
  index: Number,
  nickname: String,
  userId: String,
  date: {type: Date, default: Date.now},

  // request
  method: String,
  host: String,
  url: String,

  // response
  status: Number,

  desc: String
})
const LogModel = mongoose.model('log', logSchema)

module.exports = {
  LogModel
}

中间件

  这里参考了土豆zmb写的中间件,我根据自己应用的实际情况作了点修改。因为用户请求时携带着token,所以我在中间件里面获取到了用户的基本信息。

const jwt = require('jsonwebtoken')
const config = require('../config')
const logController = require('../controllers/log')

module.exports = async (ctx, next) => {
  if (ctx.method === 'GET') {
    // 不记录get请求
    await next()
  } else {
    let token = ctx.request.header.authorization
    if (token) {
      const secret = config.System.token_secret
      let payload = null
      try {
        payload = await jwt.verify(token.split(' ')[1], secret, {expiresIn: '1h'})
      } catch (e) {
        payload = {}
      }
      global.log = {
        nickname: payload.nickname,
        userId: payload._id,
        method: ctx.request.method,
        host: ctx.request.header.host,
        url: ctx.request.url,
        status: null,
        desc: null
      }

      await next()

      // 保存
      if (global.log.desc) {
        global.log.status = ctx.response.status
        logController.add(global.log)
      }
    }
  }
}

控制层LogController

const logService = require('../services/log')

class LogController {
  static async add (content) {
    await logService.add(content)
  }

  static async all (ctx) {
    let opt = ctx.request.query
    let {page = 1, size = 10, ...condition} = opt

    let content = await logService.all(condition, Number(page), Number(size))
    ctx.success({content})
  }
}

module.exports = LogController

服务层LogService

  查询时将几个需要展示的字段查出来,这里用了分页查询和降序。

const LogModel = require('../models/log').LogModel

class LogService {
  static async add (content) {
    let log = new LogModel(content)
    await log.save()
  }

  static async all (condition, page, size) {
    let logs = await LogModel.find(condition, '_id nickname date host status desc').skip((page - 1) * size).sort({_id: -1}).limit(size)
    let count = await LogModel.count(condition)
    return {logs, page: {page, size, count}}
  }
}

module.exports = LogService

应用

  在需要记录的地方,设置global.log.desc的值就可以了。如果不设置的话,记录到数据库中的内容为空。用户操作记录,只需要在控制层记录就可以了。如果需要留下更详细的记录,那就再服务层设置了。
  这里以用户的一个登录操作为例:

class UserController {
  static async signIn (ctx) {
    let opt = ctx.request.body
    let user = await userService.signIn(opt)
    const secret = config.System.token_secret

    if (user) {
      const token = jwt.sign(user.toJSON(), secret, {expiresIn: '1h'}) // token签名 有效期为1小时

      ctx.success({content: {user, token}})
      global.log.desc = `${user.nickname}登录`
    } else {
      ctx.error({status: 200, error: '登录失败'})
    }
  }

mongo数据库中存放的记录

前台展示

猜你喜欢

转载自blog.csdn.net/dahongdahong/article/details/80084521