mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-07-22 07:31:05 +08:00
Go: add audit log framework (#17129)
### Summary Prepare for audit log --------- Signed-off-by: Jin Hai <haijin.chn@gmail.com>
This commit is contained in:
@@ -20,16 +20,18 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"ragflow/internal/common"
|
||||
"ragflow/internal/engine/clickhouse"
|
||||
"ragflow/internal/engine/redis"
|
||||
"ragflow/internal/server"
|
||||
"ragflow/internal/server/local"
|
||||
"ragflow/internal/utility"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"ragflow/internal/service"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gin-gonic/gin/binding"
|
||||
|
||||
"ragflow/internal/service"
|
||||
)
|
||||
|
||||
// UserHandler user handler
|
||||
@@ -102,27 +104,60 @@ func (h *UserHandler) Register(c *gin.Context) {
|
||||
// @Success 200 {object} map[string]interface{}
|
||||
// @Router /api/v1/users/login [post]
|
||||
func (h *UserHandler) Login(c *gin.Context) {
|
||||
startAt := time.Now()
|
||||
operationLog := &common.OperationLog{
|
||||
EventTime: startAt,
|
||||
Operation: "login",
|
||||
APIPath: c.FullPath(),
|
||||
HTTPMethod: c.Request.Method,
|
||||
IPAddress: c.ClientIP(),
|
||||
}
|
||||
defer func() {
|
||||
operationLog.DurationMS = time.Since(startAt).Milliseconds()
|
||||
clickhouseDriver := clickhouse.GetDriver()
|
||||
err := clickhouseDriver.SaveOperationLog(operationLog)
|
||||
if err != nil {
|
||||
common.ResponseWithCodeData(c, common.CodeServerError, false, err.Error())
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
var req service.LoginRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
common.ResponseWithCodeData(c, common.CodeBadRequest, false, err.Error())
|
||||
operationLog.ErrorCode = uint16(common.CodeBadRequest)
|
||||
operationLog.Message = err.Error()
|
||||
operationLog.DurationMS = time.Since(startAt).Milliseconds()
|
||||
return
|
||||
}
|
||||
operationLog.ResourceName = req.Username
|
||||
|
||||
user, code, err := h.userService.Login(&req)
|
||||
if err != nil {
|
||||
common.ResponseWithCodeData(c, code, false, err.Error())
|
||||
operationLog.ErrorCode = uint16(code)
|
||||
operationLog.Message = err.Error()
|
||||
operationLog.DurationMS = time.Since(startAt).Milliseconds()
|
||||
return
|
||||
}
|
||||
operationLog.UserID = user.ID
|
||||
|
||||
// Sign the access_token using itsdangerous (compatible with Python)
|
||||
secretKey, err := server.GetSecretKey(redis.Get())
|
||||
if err != nil {
|
||||
common.ResponseWithCodeData(c, common.CodeServerError, false, fmt.Sprintf("Failed to get secret key: %s", err.Error()))
|
||||
errMessage := fmt.Sprintf("Failed to get secret key: %s", err.Error())
|
||||
common.ResponseWithCodeData(c, common.CodeServerError, false, errMessage)
|
||||
operationLog.ErrorCode = uint16(common.CodeServerError)
|
||||
operationLog.Message = errMessage
|
||||
operationLog.DurationMS = time.Since(startAt).Milliseconds()
|
||||
return
|
||||
}
|
||||
authToken, err := utility.DumpAccessToken(*user.AccessToken, secretKey)
|
||||
if err != nil {
|
||||
common.ResponseWithCodeData(c, common.CodeServerError, false, "Failed to generate auth token")
|
||||
operationLog.ErrorCode = uint16(common.CodeServerError)
|
||||
operationLog.Message = "Failed to generate auth token"
|
||||
operationLog.DurationMS = time.Since(startAt).Milliseconds()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -149,32 +184,68 @@ func (h *UserHandler) Login(c *gin.Context) {
|
||||
// @Success 200 {object} map[string]interface{}
|
||||
// @Router /v1/user/login [post]
|
||||
func (h *UserHandler) LoginByEmail(c *gin.Context) {
|
||||
startAt := time.Now()
|
||||
operationLog := &common.OperationLog{
|
||||
EventTime: startAt,
|
||||
Operation: "login",
|
||||
APIPath: c.FullPath(),
|
||||
HTTPMethod: c.Request.Method,
|
||||
IPAddress: c.ClientIP(),
|
||||
}
|
||||
defer func() {
|
||||
operationLog.DurationMS = time.Since(startAt).Milliseconds()
|
||||
clickhouseDriver := clickhouse.GetDriver()
|
||||
err := clickhouseDriver.SaveOperationLog(operationLog)
|
||||
if err != nil {
|
||||
common.ResponseWithCodeData(c, common.CodeServerError, false, err.Error())
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
var req service.EmailLoginRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
common.ResponseWithCodeData(c, common.CodeBadRequest, false, err.Error())
|
||||
operationLog.ErrorCode = uint16(common.CodeBadRequest)
|
||||
operationLog.Message = err.Error()
|
||||
operationLog.DurationMS = time.Since(startAt).Milliseconds()
|
||||
return
|
||||
}
|
||||
operationLog.ResourceName = req.Email
|
||||
|
||||
if !local.IsAdminAvailable() {
|
||||
license := local.GetAdminStatus()
|
||||
common.ResponseWithCodeData(c, common.CodeAuthenticationError, "No", license.Reason)
|
||||
operationLog.ErrorCode = uint16(common.CodeAuthenticationError)
|
||||
operationLog.Message = license.Reason
|
||||
operationLog.DurationMS = time.Since(startAt).Milliseconds()
|
||||
return
|
||||
}
|
||||
|
||||
user, code, err := h.userService.LoginByEmail(&req)
|
||||
if err != nil {
|
||||
common.ResponseWithCodeData(c, code, false, err.Error())
|
||||
operationLog.ErrorCode = uint16(code)
|
||||
operationLog.Message = err.Error()
|
||||
operationLog.DurationMS = time.Since(startAt).Milliseconds()
|
||||
return
|
||||
}
|
||||
operationLog.UserID = user.ID
|
||||
|
||||
secretKey, err := server.GetSecretKey(redis.Get())
|
||||
if err != nil {
|
||||
common.ResponseWithCodeData(c, common.CodeServerError, false, fmt.Sprintf("Failed to get secret key: %s", err.Error()))
|
||||
errorMessage := fmt.Sprintf("Failed to get secret key: %s", err.Error())
|
||||
common.ResponseWithCodeData(c, common.CodeServerError, false, errorMessage)
|
||||
operationLog.ErrorCode = uint16(common.CodeServerError)
|
||||
operationLog.Message = errorMessage
|
||||
operationLog.DurationMS = time.Since(startAt).Milliseconds()
|
||||
return
|
||||
}
|
||||
authToken, err := utility.DumpAccessToken(*user.AccessToken, secretKey)
|
||||
if err != nil {
|
||||
common.ResponseWithCodeData(c, common.CodeServerError, false, "Failed to generate auth token")
|
||||
operationLog.ErrorCode = uint16(common.CodeServerError)
|
||||
operationLog.Message = "Failed to generate auth token"
|
||||
operationLog.DurationMS = time.Since(startAt).Milliseconds()
|
||||
return
|
||||
}
|
||||
setOAuthAuthCookie(c, authToken)
|
||||
@@ -224,6 +295,24 @@ func (h *UserHandler) GetUserByID(c *gin.Context) {
|
||||
// @Success 200 {object} map[string]interface{}
|
||||
// @Router /v1/user/logout [post]
|
||||
func (h *UserHandler) Logout(c *gin.Context) {
|
||||
startAt := time.Now()
|
||||
operationLog := &common.OperationLog{
|
||||
EventTime: startAt,
|
||||
Operation: "logout",
|
||||
APIPath: c.FullPath(),
|
||||
HTTPMethod: c.Request.Method,
|
||||
IPAddress: c.ClientIP(),
|
||||
}
|
||||
defer func() {
|
||||
operationLog.DurationMS = time.Since(startAt).Milliseconds()
|
||||
clickhouseDriver := clickhouse.GetDriver()
|
||||
err := clickhouseDriver.SaveOperationLog(operationLog)
|
||||
if err != nil {
|
||||
common.ResponseWithCodeData(c, common.CodeServerError, false, err.Error())
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
http.SetCookie(c.Writer, &http.Cookie{
|
||||
Name: oauthAuthCookie,
|
||||
Value: "",
|
||||
@@ -237,8 +326,11 @@ func (h *UserHandler) Logout(c *gin.Context) {
|
||||
// Same as AuthMiddleware@auth.go
|
||||
token := c.GetHeader("Authorization")
|
||||
if token == "" {
|
||||
common.ResponseWithHttpCodeData(c, http.StatusUnauthorized, 401, nil, "Missing Authorization header")
|
||||
common.ResponseWithHttpCodeData(c, http.StatusUnauthorized, common.CodeUnauthorized, nil, "Missing Authorization header")
|
||||
c.Abort()
|
||||
operationLog.ErrorCode = uint16(common.CodeUnauthorized)
|
||||
operationLog.Message = "Missing Authorization header"
|
||||
operationLog.DurationMS = time.Since(startAt).Milliseconds()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -247,13 +339,20 @@ func (h *UserHandler) Logout(c *gin.Context) {
|
||||
if err != nil {
|
||||
common.ResponseWithHttpCodeData(c, http.StatusUnauthorized, code, nil, "Invalid access token")
|
||||
c.Abort()
|
||||
operationLog.ErrorCode = uint16(code)
|
||||
operationLog.Message = "Invalid access token"
|
||||
operationLog.DurationMS = time.Since(startAt).Milliseconds()
|
||||
return
|
||||
}
|
||||
operationLog.UserID = user.ID
|
||||
|
||||
// Logout user
|
||||
code, err = h.userService.Logout(user)
|
||||
if err != nil {
|
||||
common.ResponseWithCodeData(c, code, false, err.Error())
|
||||
operationLog.ErrorCode = uint16(code)
|
||||
operationLog.Message = err.Error()
|
||||
operationLog.DurationMS = time.Since(startAt).Milliseconds()
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user