| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 |
- package dbdata
- import (
- "net/url"
- "regexp"
- "strings"
- "github.com/bjdgyc/anylink/base"
- "github.com/ivpusic/grpool"
- "github.com/spf13/cast"
- "xorm.io/xorm"
- )
- const (
- UserAuthFail = 0 // 认证失败
- UserAuthSuccess = 1 // 认证成功
- UserConnected = 2 // 连线成功
- UserLogout = 3 // 用户登出
- UserLogoutLose = 0 // 用户掉线
- UserLogoutBanner = 1 // 用户banner弹窗取消
- UserLogoutClient = 2 // 用户主动登出
- UserLogoutTimeout = 3 // 用户超时登出
- UserLogoutAdmin = 4 // 账号被管理员踢下线
- UserLogoutExpire = 5 // 账号过期被踢下线
- )
- type UserActLogProcess struct {
- Pool *grpool.Pool
- StatusOps []string
- OsOps []string
- ClientOps []string
- InfoOps []string
- }
- var (
- UserActLogIns = &UserActLogProcess{
- Pool: grpool.NewPool(1, 100),
- StatusOps: []string{ // 操作类型
- UserAuthFail: "认证失败",
- UserAuthSuccess: "认证成功",
- UserConnected: "连接成功",
- UserLogout: "用户登出",
- },
- OsOps: []string{ // 操作系统
- 0: "Unknown",
- 1: "Windows",
- 2: "macOS",
- 3: "Linux",
- 4: "Android",
- 5: "iOS",
- },
- ClientOps: []string{ // 客户端
- 0: "Unknown",
- 1: "AnyConnect",
- 2: "OpenConnect",
- 3: "AnyLink",
- },
- InfoOps: []string{ // 信息
- UserLogoutLose: "用户掉线",
- UserLogoutBanner: "用户取消弹窗/客户端发起的logout",
- UserLogoutClient: "用户/客户端主动断开",
- UserLogoutTimeout: "Session过期被踢下线",
- UserLogoutAdmin: "账号被管理员踢下线",
- UserLogoutExpire: "账号过期被踢下线",
- },
- }
- )
- // 异步写入用户操作日志
- func (ua *UserActLogProcess) Add(u UserActLog, userAgent string) {
- // os, client, ver
- os_idx, client_idx, ver := ua.ParseUserAgent(userAgent)
- u.Os = os_idx
- u.Client = client_idx
- u.Version = ver
- u.RemoteAddr = strings.Split(u.RemoteAddr, ":")[0]
- // remove extra characters
- infoSlice := strings.Split(u.Info, " ")
- infoLen := len(infoSlice)
- if infoLen > 1 {
- if u.Username == infoSlice[0] {
- u.Info = strings.Join(infoSlice[1:], " ")
- }
- // delete - char
- if infoLen > 2 && infoSlice[1] == "-" {
- u.Info = u.Info[2:]
- }
- }
- // limit the max length of char
- u.Version = substr(u.Version, 0, 15)
- u.DeviceType = substr(u.DeviceType, 0, 128)
- u.PlatformVersion = substr(u.PlatformVersion, 0, 128)
- u.Info = substr(u.Info, 0, 255)
- UserActLogIns.Pool.JobQueue <- func() {
- err := Add(u)
- if err != nil {
- base.Error("Add UserActLog error: ", err)
- }
- }
- }
- // 转义操作类型, 方便vue显示
- func (ua *UserActLogProcess) GetStatusOpsWithTag() interface{} {
- type StatusTag struct {
- Key int `json:"key"`
- Value string `json:"value"`
- Tag string `json:"tag"`
- }
- var res []StatusTag
- for k, v := range ua.StatusOps {
- tag := "info"
- switch k {
- case UserAuthFail:
- tag = "danger"
- case UserAuthSuccess:
- tag = "success"
- case UserConnected:
- tag = ""
- }
- res = append(res, StatusTag{k, v, tag})
- }
- return res
- }
- func (ua *UserActLogProcess) GetInfoOpsById(id uint8) string {
- return ua.InfoOps[id]
- }
- // 解析user agent
- func (ua *UserActLogProcess) ParseUserAgent(userAgent string) (os_idx, client_idx uint8, ver string) {
- // Unknown
- if len(userAgent) == 0 {
- return 0, 0, ""
- }
- // OS
- os_idx = 0
- if strings.Contains(userAgent, "windows") {
- os_idx = 1
- } else if strings.Contains(userAgent, "mac os") || strings.Contains(userAgent, "darwin_i386") {
- os_idx = 2
- } else if strings.Contains(userAgent, "darwin_arm") || strings.Contains(userAgent, "apple") {
- os_idx = 5
- } else if strings.Contains(userAgent, "android") {
- os_idx = 4
- } else if strings.Contains(userAgent, "linux") {
- os_idx = 3
- }
- // Client
- client_idx = 0
- if strings.Contains(userAgent, "anyconnect") {
- client_idx = 1
- } else if strings.Contains(userAgent, "openconnect") {
- client_idx = 2
- } else if strings.Contains(userAgent, "anylink") {
- client_idx = 3
- }
- // Version
- uaSlice := strings.Split(userAgent, " ")
- ver = uaSlice[len(uaSlice)-1]
- if ver[0] == 'v' {
- ver = ver[1:]
- }
- if !regexp.MustCompile(`^(\d+\.?)+$`).MatchString(ver) {
- ver = ""
- }
- return
- }
- // 清除用户操作日志
- func (ua *UserActLogProcess) ClearUserActLog(ts string) (int64, error) {
- affected, err := xdb.Where("created_at < '" + ts + "'").Delete(&UserActLog{})
- return affected, err
- }
- // 后台筛选用户操作日志
- func (ua *UserActLogProcess) GetSession(values url.Values) *xorm.Session {
- session := xdb.Where("1=1")
- if values.Get("username") != "" {
- session.And("username = ?", values.Get("username"))
- }
- if values.Get("sdate") != "" {
- session.And("created_at >= ?", values.Get("sdate")+" 00:00:00'")
- }
- if values.Get("edate") != "" {
- session.And("created_at <= ?", values.Get("edate")+" 23:59:59'")
- }
- if values.Get("status") != "" {
- session.And("status = ?", cast.ToUint8(values.Get("status"))-1)
- }
- if values.Get("os") != "" {
- session.And("os = ?", cast.ToUint8(values.Get("os"))-1)
- }
- if values.Get("sort") == "1" {
- session.OrderBy("id desc")
- } else {
- session.OrderBy("id asc")
- }
- return session
- }
- // 截取字符串
- func substr(s string, pos, length int) string {
- runes := []rune(s)
- l := pos + length
- if l > len(runes) {
- l = len(runes)
- }
- return string(runes[pos:l])
- }
|