Files
Wormhole/internal/store/apikey.go
T
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

88 lines
1.9 KiB
Go

package store
import (
"crypto/rand"
"crypto/sha256"
"encoding/hex"
"errors"
"fmt"
)
func hashAPIKey(key string) string {
sum := sha256.Sum256([]byte(key))
return hex.EncodeToString(sum[:])
}
func generateAPIKeyPlain() (string, string, error) {
b := make([]byte, 24)
if _, err := rand.Read(b); err != nil {
return "", "", err
}
plain := "wh_" + hex.EncodeToString(b)
prefix := plain
if len(prefix) > 12 {
prefix = prefix[:12]
}
return plain, prefix, nil
}
func (s *Store) ListAPIKeys(userID uint, isAdmin bool) ([]APIKey, error) {
var keys []APIKey
q := s.db.Order("id asc")
if !isAdmin {
q = q.Where("user_id = ?", userID)
}
return keys, q.Find(&keys).Error
}
func (s *Store) CreateAPIKey(name string, userID uint) (*APIKey, string, error) {
if name == "" {
return nil, "", errors.New("name required")
}
plain, prefix, err := generateAPIKeyPlain()
if err != nil {
return nil, "", err
}
key := &APIKey{
Name: name,
KeyPrefix: prefix,
KeyHash: hashAPIKey(plain),
UserID: userID,
Status: true,
}
if err := s.db.Create(key).Error; err != nil {
return nil, "", err
}
return key, plain, nil
}
func (s *Store) DeleteAPIKey(id uint, userID uint, isAdmin bool) error {
var key APIKey
if err := s.db.First(&key, id).Error; err != nil {
return err
}
if !isAdmin && key.UserID != userID {
return fmt.Errorf("permission denied")
}
return s.db.Delete(&APIKey{}, id).Error
}
func (s *Store) ValidateAPIKey(plain string) (*User, error) {
if plain == "" {
return nil, errors.New("empty api key")
}
hash := hashAPIKey(plain)
var key APIKey
if err := s.db.Where("key_hash = ? AND status = ?", hash, true).First(&key).Error; err != nil {
return nil, errors.New("invalid api key")
}
user, err := s.GetUserByID(key.UserID)
if err != nil {
return nil, err
}
if !user.Status {
return nil, errors.New("user disabled")
}
return user, nil
}