mirror of
https://github.com/GMWalletApp/epusdt.git
synced 2026-07-08 02:36:16 +00:00
feat: add admin panel with multi-chain support and notification system
- Add full admin REST API: auth, API keys, chains, chain tokens, wallets, orders, RPC nodes, settings, dashboard stats, notifications - Add JWT-based admin authentication and API key auth middleware - Add multi-chain listeners: BSC, ETH, Polygon, Plasma, EVM WebSocket - Add RPC node health check job with automatic failover - Add Telegram notification channel for order events - Add installer for first-run database initialization - Add new DB models: admin_user, api_key, chain, chain_token, rpc_node, settings, notification_channel - Add order statistics aggregation (daily/monthly/by-chain) - Serve built admin SPA from embedded www/ assets - Add comprehensive test coverage for all new features
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
package jwt
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/assimon/luuu/model/data"
|
||||
"github.com/assimon/luuu/model/mdb"
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
)
|
||||
|
||||
// DefaultExpiration is the token lifetime for admin sessions.
|
||||
const DefaultExpiration = 24 * time.Hour
|
||||
|
||||
// AdminClaims is the JWT payload for admin sessions.
|
||||
type AdminClaims struct {
|
||||
AdminUserID uint64 `json:"uid"`
|
||||
Username string `json:"usr"`
|
||||
jwt.RegisteredClaims
|
||||
}
|
||||
|
||||
// EnsureSecret reads system.jwt_secret from settings; if absent,
|
||||
// generates a new 32-byte random hex string and persists it. Called once
|
||||
// at startup so subsequent sign/verify can assume the secret exists.
|
||||
func EnsureSecret() (string, error) {
|
||||
secret := data.GetSettingString(mdb.SettingKeyJwtSecret, "")
|
||||
if secret != "" {
|
||||
return secret, nil
|
||||
}
|
||||
buf := make([]byte, 32)
|
||||
if _, err := rand.Read(buf); err != nil {
|
||||
return "", err
|
||||
}
|
||||
secret = hex.EncodeToString(buf)
|
||||
if err := data.SetSetting(mdb.SettingGroupSystem, mdb.SettingKeyJwtSecret, secret, mdb.SettingTypeString); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return secret, nil
|
||||
}
|
||||
|
||||
// Sign returns a signed JWT for the given admin user.
|
||||
func Sign(userID uint64, username string) (string, error) {
|
||||
secret, err := EnsureSecret()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
claims := AdminClaims{
|
||||
AdminUserID: userID,
|
||||
Username: username,
|
||||
RegisteredClaims: jwt.RegisteredClaims{
|
||||
ExpiresAt: jwt.NewNumericDate(time.Now().Add(DefaultExpiration)),
|
||||
IssuedAt: jwt.NewNumericDate(time.Now()),
|
||||
},
|
||||
}
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
return token.SignedString([]byte(secret))
|
||||
}
|
||||
|
||||
// Parse validates a token string and returns its claims.
|
||||
func Parse(tokenStr string) (*AdminClaims, error) {
|
||||
secret, err := EnsureSecret()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
claims := &AdminClaims{}
|
||||
_, err = jwt.ParseWithClaims(tokenStr, claims, func(t *jwt.Token) (interface{}, error) {
|
||||
if _, ok := t.Method.(*jwt.SigningMethodHMAC); !ok {
|
||||
return nil, errors.New("unexpected signing method")
|
||||
}
|
||||
return []byte(secret), nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return claims, nil
|
||||
}
|
||||
Reference in New Issue
Block a user