0d84b07f68
CI / docker (push) Successful in 1m58s
Go + Vue 管理台:Agent 隧道、域名反代、IP 安全、访客验证与监控大盘。 Gitea Actions CI 多架构镜像;纯 Go SQLite、无 CGO Docker 构建。 Co-authored-by: Cursor <cursoragent@cursor.com>
89 lines
2.6 KiB
Go
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
|
|
}
|