migrate from github
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
package utils
|
||||
|
||||
import "encoding/base64"
|
||||
|
||||
func DecodeBase64(value string) ([]byte, error) {
|
||||
return base64.StdEncoding.DecodeString(value)
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
})
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user