Browse Source

✨ feat: 增加日志记录

Pchen. 8 months ago
parent
commit
58ce1c0ed8
3 changed files with 147 additions and 11 deletions
  1. 135 0
      apis/User/Admin/GetReqLog.js
  2. 2 1
      lib/API.js
  3. 10 10
      lib/requestLog.js

+ 135 - 0
apis/User/Admin/GetReqLog.js

@@ -0,0 +1,135 @@
+const API = require("../../../lib/API")
+const db = require("../../../plugin/DataBase/db")
+const AccessControl = require("../../../lib/AccessControl")
+const { BaseStdResponse } = require("../../../BaseStdResponse")
+
+class GetReqLog extends API {
+    constructor() {
+        super();
+
+        this.setPath('/Admin/User/GetReqLog')
+        this.setMethod('post')
+    }
+
+    async onRequest(req, res) {
+        let { uuid, session, create_user, begin_time, end_time,  pagesize, current } = req.body
+
+        if ([uuid, session, pagesize, current].some(value => value === '' || value === null || value === undefined))
+            return res.json({
+                ...BaseStdResponse.MISSING_PARAMETER
+            })
+
+        // 校验分页参数
+        if (isNaN(pagesize) || pagesize <= 0 || pagesize > 50) {
+            return res.json({
+                ...BaseStdResponse.ERR,
+                msg: '参数错误'
+            })
+        }
+
+        if (isNaN(current) || current <= 0) {
+            return res.json({
+                ...BaseStdResponse.ERR,
+                msg: '参数错误'
+            })
+        }
+
+        // 检查 session
+        if (!await AccessControl.checkSession(uuid, session))
+            return res.status(401).json({
+                ...BaseStdResponse.ACCESS_DENIED
+            })
+
+        // 检查权限
+        let permission = await AccessControl.getPermission(uuid)
+        if (!permission.includes("admin"))
+            return res.json({
+                ...BaseStdResponse.PERMISSION_DENIED
+            })
+
+        // 计算分页的 offset
+        const offset = (current - 1) * pagesize
+
+       let sql = `
+                SELECT 
+                    l.*,
+                    u.username,
+                    u.avatar
+                FROM 
+                    requestLog l
+                JOIN 
+                    users u
+                ON 
+                    l.create_user = u.uuid
+                WHERE 
+                    1 = 1
+            `
+
+        let countSql = `
+            SELECT COUNT(*) AS total
+            FROM 
+                requestLog l
+            JOIN 
+                users u
+            ON 
+                l.create_user = u.uuid
+            WHERE 1 = 1
+        `
+
+        let params = []
+        let countParams = []
+
+        if (create_user) {
+            sql += ` AND l.create_user = ?`
+            countSql += ` AND l.create_user = ?`
+            params.push(create_user)
+            countParams.push(create_user)
+        }
+
+        if (begin_time) {
+            sql += ` AND l.create_time > ?`
+            countSql += ` AND l.create_time = ?`
+            params.push(begin_time)
+            countParams.push(begin_time)
+        }
+
+        if (end_time) {
+            sql += ` AND l.create_time < ?`
+            countSql += ` AND l.create_time < ?`
+            params.push(end_time)
+            countParams.push(end_time)
+        }
+
+        sql += `
+            ORDER BY l.id DESC
+            LIMIT ? OFFSET ?;
+        `
+        params.push(String(pagesize), String(offset))
+
+        // 临时调大缓存
+        await db.query("SET SESSION sort_buffer_size = 4*1024*1024;")
+
+        let rows = await db.query(sql, params)
+        let countResult = await db.query(countSql, countParams)
+
+        if (!rows || !countResult)
+            return res.json({
+                ...BaseStdResponse.MISSING_FILE,
+                msg: '获取日志数据失败!'
+            })
+
+        let total = countResult[0].total
+
+        res.json({
+            ...BaseStdResponse.OK,
+            data: rows,
+            pagination: {
+                current,
+                pagesize,
+                total
+            }
+        })
+    }
+}
+
+module.exports.GetReqLog = GetReqLog

+ 2 - 1
lib/API.js

@@ -120,12 +120,13 @@ class API {
             // 拦截返回值统一加密
             // 拦截返回值统一加密
             const originalJson = res.json.bind(res)
             const originalJson = res.json.bind(res)
             res.json = (data) => {
             res.json = (data) => {
+                this.requestLog.insertLog(req, JSON.parse(JSON.stringify(data)), this.namespace, this.method, this.path)
+
                 if(this.encrypt && data.data) {
                 if(this.encrypt && data.data) {
                     data.b = this.aesEncrypt(data.data, req)
                     data.b = this.aesEncrypt(data.data, req)
                     delete data.data
                     delete data.data
                 }
                 }
 
 
-                this.requestLog.insertLog(req, data, this.namespace, this.method, this.path)
                 return originalJson(data)
                 return originalJson(data)
             }
             }
 
 

+ 10 - 10
lib/requestLog.js

@@ -9,7 +9,7 @@ class RequestLog {
         this.searcher = ipSearcher.newWithFileOnly(path.join(__dirname, '../plugin/ip2region/ip2region.xdb'))
         this.searcher = ipSearcher.newWithFileOnly(path.join(__dirname, '../plugin/ip2region/ip2region.xdb'))
     }
     }
 
 
-    async insertLog(req, res, namespace, method, path) {
+    async insertLog(req, resData, namespace, method, path) {
         try {
         try {
             const time = new Date().getTime()
             const time = new Date().getTime()
             const ip = this.getClientIp(req)
             const ip = this.getClientIp(req)
@@ -26,8 +26,8 @@ class RequestLog {
                 reqData = req.body
                 reqData = req.body
             }
             }
 
 
-            let sql = 'INSERT INTO requestLog (create_user, create_time, method, reqData, code, ip, ua, deviceType, apiName, location, url) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'
-            let r = await db.query(sql, [reqData.uuid ?? '', time, method, reqData, res.code, ip, userAgent, deviceType, namespace ?? '未知', ipData ?? '未知', path])
+            let sql = 'INSERT INTO requestLog (create_user, create_time, method, reqData, resData, code, ip, ua, deviceType, apiName, location, url) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)'
+            let r = await db.query(sql, [reqData.uuid ?? '', time, method, reqData, resData, resData.code, ip, userAgent, deviceType, namespace ?? '未知', ipData ?? '未知', path])
             if (!r || r.affectedRows !== 1)
             if (!r || r.affectedRows !== 1)
                 this.logger.error(`插入日志信息失败!数据库错误`)
                 this.logger.error(`插入日志信息失败!数据库错误`)
         } catch (error) {
         } catch (error) {
@@ -36,28 +36,28 @@ class RequestLog {
     }
     }
 
 
     getClientIp(req) {
     getClientIp(req) {
-        let ip = null;
+        let ip = null
 
 
         if (req.headers['x-forwarded-for']) {
         if (req.headers['x-forwarded-for']) {
             ip = req.headers['x-forwarded-for'].split(',')[0].trim();
             ip = req.headers['x-forwarded-for'].split(',')[0].trim();
         } else if (req.headers['x-real-ip']) {
         } else if (req.headers['x-real-ip']) {
             ip = req.headers['x-real-ip'];
             ip = req.headers['x-real-ip'];
         } else {
         } else {
-            ip = req.connection.remoteAddress || '';
+            ip = req.connection.remoteAddress || ''
         }
         }
 
 
         // 如果是 IPv6 映射的 IPv4 (::ffff:x.x.x.x),提取后面的 IPv4
         // 如果是 IPv6 映射的 IPv4 (::ffff:x.x.x.x),提取后面的 IPv4
         if (ip.startsWith("::ffff:")) {
         if (ip.startsWith("::ffff:")) {
-            ip = ip.replace("::ffff:", "");
+            ip = ip.replace("::ffff:", "")
         }
         }
 
 
-        // 如果是 [::1] 或其他 IPv6,可以按需过滤掉
-        const ipv4Regex = /^(\d{1,3}\.){3}\d{1,3}$/;
+        // 如果是 [::1] 或其他 IPv6
+        const ipv4Regex = /^(\d{1,3}\.){3}\d{1,3}$/
         if (!ipv4Regex.test(ip)) {
         if (!ipv4Regex.test(ip)) {
-            return null; // 非 IPv4 返回 null 或者你可以保留原值
+            return '0.0.0.0'; // 非 IPv4
         }
         }
 
 
-        return ip;
+        return ip ?? '0.0.0.0';
     }
     }
 
 
 }
 }