612d68f56f
Go + Vue 管理台,SQLite 持久化;支持隧道/域名穿透、域名转发插件链、访客认证、 IP 规则、API Key、Docker 单镜像部署;配置通过 Web 系统设置管理,无需 YAML 文件。 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
|
|
}
|