美文网首页
Koa2 获取并存储用户操作日志

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

作者: 大洪 | 来源:发表于2018-04-25 19:43 被阅读309次

      有时候我们需要记录用户进行了哪些操作,比如删除、更新和添加。这部分是要呈献给用户的,所以一定不能直接把系统日志的一大坨给他们。
      系统后台采用了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数据库中存放的记录 前台展示

    相关文章

      网友评论

          本文标题:Koa2 获取并存储用户操作日志

          本文链接:https://www.haomeiwen.com/subject/kraylftx.html