migrate from github
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/XingfenD/yoresee_doc/internal/status"
|
||||
"github.com/XingfenD/yoresee_doc/pkg/key"
|
||||
"github.com/XingfenD/yoresee_doc/pkg/storage"
|
||||
"github.com/redis/go-redis/v9"
|
||||
)
|
||||
|
||||
func hashToken(token string) string {
|
||||
sum := sha256.Sum256([]byte(token))
|
||||
return hex.EncodeToString(sum[:])
|
||||
}
|
||||
|
||||
func StoreJWTToken(userExternalID, token string, ttl time.Duration) error {
|
||||
if storage.KVS == nil {
|
||||
return status.StatusRedisNotInitialized
|
||||
}
|
||||
if ttl <= 0 {
|
||||
return status.GenErrWithCustomMsg(status.StatusInternalParamsError, "invalid jwt ttl")
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tokenHash := hashToken(token)
|
||||
pipe := storage.KVS.TxPipeline()
|
||||
pipe.Set(ctx, key.KeyJWTActiveToken(tokenHash), userExternalID, ttl)
|
||||
pipe.SAdd(ctx, key.KeyJWTUserTokenSet(userExternalID), tokenHash)
|
||||
pipe.Expire(ctx, key.KeyJWTUserTokenSet(userExternalID), ttl)
|
||||
if _, err := pipe.Exec(ctx); err != nil {
|
||||
return fmt.Errorf("persist jwt token failed: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ValidateJWTTokenInRedis(userExternalID, token string) error {
|
||||
if storage.KVS == nil {
|
||||
return status.StatusRedisNotInitialized
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tokenHash := hashToken(token)
|
||||
blacklisted, err := storage.KVS.Exists(ctx, key.KeyJWTBlacklistToken(tokenHash)).Result()
|
||||
if err != nil {
|
||||
return fmt.Errorf("query jwt blacklist failed: %w", err)
|
||||
}
|
||||
if blacklisted > 0 {
|
||||
return status.GenErrWithCustomMsg(status.StatusTokenInvalid, "token is blacklisted")
|
||||
}
|
||||
|
||||
storedUserExternalID, err := storage.KVS.Get(ctx, key.KeyJWTActiveToken(tokenHash)).Result()
|
||||
if err != nil {
|
||||
if err == redis.Nil {
|
||||
return status.GenErrWithCustomMsg(status.StatusTokenInvalid, "token is invalid")
|
||||
}
|
||||
return fmt.Errorf("query active jwt token failed: %w", err)
|
||||
}
|
||||
if storedUserExternalID != userExternalID {
|
||||
return status.GenErrWithCustomMsg(status.StatusTokenInvalid, "token user mismatch")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func BlacklistUserJWTs(userExternalID string) error {
|
||||
if storage.KVS == nil {
|
||||
return status.StatusRedisNotInitialized
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tokenHashes, err := storage.KVS.SMembers(ctx, key.KeyJWTUserTokenSet(userExternalID)).Result()
|
||||
if err != nil {
|
||||
return fmt.Errorf("list user jwt tokens failed: %w", err)
|
||||
}
|
||||
if len(tokenHashes) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
pipe := storage.KVS.TxPipeline()
|
||||
for _, tokenHash := range tokenHashes {
|
||||
activeKey := key.KeyJWTActiveToken(tokenHash)
|
||||
ttlCmd := storage.KVS.TTL(ctx, activeKey)
|
||||
ttl, ttlErr := ttlCmd.Result()
|
||||
if ttlErr != nil && ttlErr != redis.Nil {
|
||||
return fmt.Errorf("query token ttl failed: %w", ttlErr)
|
||||
}
|
||||
if ttl <= 0 {
|
||||
ttl = 24 * time.Hour
|
||||
}
|
||||
pipe.Set(ctx, key.KeyJWTBlacklistToken(tokenHash), "1", ttl)
|
||||
pipe.Del(ctx, activeKey)
|
||||
}
|
||||
pipe.Del(ctx, key.KeyJWTUserTokenSet(userExternalID))
|
||||
if _, err := pipe.Exec(ctx); err != nil {
|
||||
return fmt.Errorf("blacklist user jwt tokens failed: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user