migrate from github

This commit is contained in:
2026-07-15 22:42:31 +08:00
commit 3ad559f05e
262 changed files with 21637 additions and 0 deletions
+7
View File
@@ -0,0 +1,7 @@
package utils
import "encoding/base64"
func DecodeBase64(value string) ([]byte, error) {
return base64.StdEncoding.DecodeString(value)
}
+23
View File
@@ -0,0 +1,23 @@
package utils
import (
"github.com/XingfenD/yoresee_doc/internal/config"
"golang.org/x/crypto/bcrypt"
)
func HashPassword(password string) (string, error) {
cost := bcrypt.DefaultCost
if config.GlobalConfig != nil {
c := config.GlobalConfig.Backend.Security.PasswordHashCost
if c >= bcrypt.MinCost && c <= bcrypt.MaxCost {
cost = c
}
}
bytes, err := bcrypt.GenerateFromPassword([]byte(password), cost)
return string(bytes), err
}
func CheckPassword(password, hash string) bool {
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
return err == nil
}
+36
View File
@@ -0,0 +1,36 @@
package utils
import (
"context"
"os"
"os/signal"
"syscall"
"github.com/sirupsen/logrus"
)
type ShutdownHook struct {
Name string
Fn func() error
}
func ShutdownContext() (context.Context, context.CancelFunc) {
return signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
}
func WaitForShutdownSignal() {
ctx, stop := ShutdownContext()
defer stop()
<-ctx.Done()
}
func RunShutdownHooks(hooks ...ShutdownHook) {
for _, hook := range hooks {
if hook.Fn == nil {
continue
}
if err := hook.Fn(); err != nil {
logrus.Errorf("Close %s failed: %v", hook.Name, err)
}
}
}
+45
View File
@@ -0,0 +1,45 @@
package utils
import (
"crypto/md5"
"encoding/hex"
"sync"
"github.com/bwmarrin/snowflake"
)
var (
node *snowflake.Node
nodeOnce sync.Once
nodeErr error
)
type ExternalIDContext string
const (
ExternalIDContextUser ExternalIDContext = "user"
ExternalIDKnowledgeBase ExternalIDContext = "knowledge_base"
ExternalIDContextDocument ExternalIDContext = "document"
ExternalIDContextUserGroup ExternalIDContext = "user_group"
ExternalIDContextOrgNode ExternalIDContext = "org_node"
ExternalIDContextComment ExternalIDContext = "comment"
ExternalIDContextNotification ExternalIDContext = "notification"
ExternalIDContextAttachment ExternalIDContext = "attachment"
)
func GenerateExternalID(context ExternalIDContext) string {
initSnowflakeNode()
if nodeErr != nil {
panic(nodeErr)
}
id := node.Generate()
combined := string(context) + ":" + id.String()
hash := md5.Sum([]byte(combined))
return hex.EncodeToString(hash[:])
}
func initSnowflakeNode() {
nodeOnce.Do(func() {
node, nodeErr = snowflake.NewNode(1)
})
}
+43
View File
@@ -0,0 +1,43 @@
package utils
import (
"strconv"
"strings"
)
func Int64ToString(i int64) string {
return strconv.FormatInt(i, 10)
}
func ParseInt64(value string) (int64, error) {
return strconv.ParseInt(strings.TrimSpace(value), 10, 64)
}
func NormalizeToken(raw, fallback string) string {
fallback = strings.TrimSpace(fallback)
if fallback == "" {
fallback = "default"
}
raw = strings.TrimSpace(raw)
if raw == "" {
return fallback
}
var b strings.Builder
for _, r := range raw {
if (r >= 'a' && r <= 'z') ||
(r >= 'A' && r <= 'Z') ||
(r >= '0' && r <= '9') ||
r == '.' || r == '-' || r == '_' {
b.WriteRune(r)
continue
}
b.WriteByte('-')
}
if b.Len() == 0 {
return fallback
}
return b.String()
}
+28
View File
@@ -0,0 +1,28 @@
package utils
import (
"gorm.io/gorm"
)
// WithTransaction 执行一个包含事务的操作
func WithTransaction(db *gorm.DB, fn func(tx *gorm.DB) error) error {
tx := db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
panic(r)
}
}()
if err := fn(tx); err != nil {
tx.Rollback()
return err
}
if err := tx.Commit().Error; err != nil {
tx.Rollback()
return err
}
return nil
}
+22
View File
@@ -0,0 +1,22 @@
package utils
import (
"os"
"strings"
)
func Of[T any](v T) *T {
return &v
}
func GenConfigKey(parts ...string) string {
return strings.Join(parts, ".")
}
func GetEnvVar(key, defaultValue string) string {
value := strings.TrimSpace(os.Getenv(key))
if value == "" {
return strings.TrimSpace(defaultValue)
}
return value
}
+21
View File
@@ -0,0 +1,21 @@
package utils
import "testing"
func TestGetEnvVar(t *testing.T) {
t.Run("use env value", func(t *testing.T) {
t.Setenv("GET_ENV_VAR_TEST", " value ")
got := GetEnvVar("GET_ENV_VAR_TEST", "default")
if got != "value" {
t.Fatalf("expected value, got %q", got)
}
})
t.Run("fallback to default", func(t *testing.T) {
t.Setenv("GET_ENV_VAR_TEST", "")
got := GetEnvVar("GET_ENV_VAR_TEST", " default ")
if got != "default" {
t.Fatalf("expected default, got %q", got)
}
})
}