Files
rose_cat707 0d84b07f68
CI / docker (push) Successful in 1m58s
feat: Wormhole 内网穿透与反向代理网关
Go + Vue 管理台:Agent 隧道、域名反代、IP 安全、访客验证与监控大盘。
Gitea Actions CI 多架构镜像;纯 Go SQLite、无 CGO Docker 构建。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-23 17:52:43 +08:00

89 lines
2.6 KiB
Go

package store
import "gorm.io/gorm"
func (s *Store) ListVisitors() ([]User, error) {
var users []User
err := s.db.Where("role = ?", "visitor").Order("id asc").Find(&users).Error
return users, err
}
func (s *Store) ListResourceVisitorIDs(resourceType string, resourceID uint) ([]uint, error) {
var bindings []ResourceVisitor
err := s.db.Where("resource_type = ? AND resource_id = ?", resourceType, resourceID).
Order("user_id asc").Find(&bindings).Error
if err != nil {
return nil, err
}
ids := make([]uint, len(bindings))
for i, b := range bindings {
ids[i] = b.UserID
}
return ids, nil
}
func (s *Store) SetResourceVisitors(resourceType string, resourceID uint, userIDs []uint) error {
return s.db.Transaction(func(tx *gorm.DB) error {
if err := tx.Where("resource_type = ? AND resource_id = ?", resourceType, resourceID).
Delete(&ResourceVisitor{}).Error; err != nil {
return err
}
for _, uid := range userIDs {
rv := ResourceVisitor{
ResourceType: resourceType,
ResourceID: resourceID,
UserID: uid,
}
if err := tx.Create(&rv).Error; err != nil {
return err
}
}
return nil
})
}
func (s *Store) DeleteResourceVisitors(resourceType string, resourceID uint) error {
return s.db.Where("resource_type = ? AND resource_id = ?", resourceType, resourceID).
Delete(&ResourceVisitor{}).Error
}
func (s *Store) ListAllResourceVisitors() ([]ResourceVisitor, error) {
var items []ResourceVisitor
err := s.db.Order("resource_type, resource_id, user_id").Find(&items).Error
return items, err
}
const MaxVisitorAccessLogsPerUser = 200
func (s *Store) AppendVisitorAccessLog(entry *VisitorAccessLog) error {
return s.db.Transaction(func(tx *gorm.DB) error {
if err := tx.Create(entry).Error; err != nil {
return err
}
var keepIDs []uint
if err := tx.Model(&VisitorAccessLog{}).Where("user_id = ?", entry.UserID).
Order("id desc").Limit(MaxVisitorAccessLogsPerUser).Pluck("id", &keepIDs).Error; err != nil {
return err
}
if len(keepIDs) == 0 {
return nil
}
return tx.Where("user_id = ? AND id NOT IN ?", entry.UserID, keepIDs).
Delete(&VisitorAccessLog{}).Error
})
}
func (s *Store) ListVisitorAccessLogs(userID uint, limit int) ([]VisitorAccessLog, error) {
if limit <= 0 || limit > MaxVisitorAccessLogsPerUser {
limit = MaxVisitorAccessLogsPerUser
}
var items []VisitorAccessLog
err := s.db.Where("user_id = ?", userID).
Order("id desc").Limit(limit).Find(&items).Error
return items, err
}
func (s *Store) DeleteVisitorAccessLogs(userID uint) error {
return s.db.Where("user_id = ?", userID).Delete(&VisitorAccessLog{}).Error
}