WIP: Full restruct, seprate service and api
Signed-off-by: Asai Neko <sugar@sne.moe>
This commit is contained in:
65
internal/authcode/authcode.go
Normal file
65
internal/authcode/authcode.go
Normal file
@@ -0,0 +1,65 @@
|
||||
package authcode
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"nixcn-cms/data"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
type Token struct {
|
||||
ClientId string
|
||||
Email string
|
||||
}
|
||||
|
||||
func NewAuthCode(ctx context.Context, clientId string, email string) (string, error) {
|
||||
// generate random code
|
||||
b := make([]byte, 32)
|
||||
if _, err := rand.Read(b); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
code := base64.RawURLEncoding.EncodeToString(b)
|
||||
key := "auth_code:" + code
|
||||
|
||||
ttl := viper.GetDuration("ttl.auth_code_ttl")
|
||||
|
||||
// store auth code metadata in Redis
|
||||
if err := data.Redis.HSet(
|
||||
ctx,
|
||||
key,
|
||||
map[string]any{
|
||||
"client_id": clientId,
|
||||
"email": email,
|
||||
},
|
||||
).Err(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// set expiration (one-time auth code)
|
||||
if err := data.Redis.Expire(ctx, key, ttl).Err(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return code, nil
|
||||
}
|
||||
|
||||
func VerifyAuthCode(ctx context.Context, code string) (*Token, bool) {
|
||||
key := "auth_code:" + code
|
||||
|
||||
// Read auth code payload
|
||||
dataMap, err := data.Redis.HGetAll(ctx, key).Result()
|
||||
if err != nil || len(dataMap) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// Delete auth code immediately (one-time use)
|
||||
_ = data.Redis.Del(ctx, key).Err()
|
||||
|
||||
return &Token{
|
||||
ClientId: dataMap["client_id"],
|
||||
Email: dataMap["email"],
|
||||
}, true
|
||||
}
|
||||
Reference in New Issue
Block a user