mirror of
https://github.com/weloe/token-go.git
synced 2025-09-27 03:46:01 +08:00
feat: add QRCode state api, support QRCode login
This commit is contained in:
@@ -70,6 +70,15 @@ type IEnforcer interface {
|
||||
GetRequestToken(ctx ctx.Context) string
|
||||
AddTokenGenerateFun(tokenStyle string, f model.HandlerFunc) error
|
||||
|
||||
// QRCode api
|
||||
CreateQRCodeState(QRCodeId string, timeout int64) error
|
||||
GetQRCode(QRCodeId string) *model.QRCode
|
||||
GetQRCodeState(QRCodeId string) model.QRCodeState
|
||||
GetQRCodeTimeout(QRCodeId string) int64
|
||||
Scanned(QRCodeId string, token string) (string, error)
|
||||
ConfirmAuth(QRCodeTempToken string) error
|
||||
CancelAuth(QRCodeTempToken string) error
|
||||
|
||||
// Access control api
|
||||
SetAuth(manager interface{})
|
||||
CheckRole(ctx ctx.Context, role string) error
|
||||
|
@@ -1,10 +1,12 @@
|
||||
package token_go
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/weloe/token-go/constant"
|
||||
"github.com/weloe/token-go/ctx"
|
||||
"github.com/weloe/token-go/errors"
|
||||
"github.com/weloe/token-go/model"
|
||||
"github.com/weloe/token-go/util"
|
||||
"math"
|
||||
"strconv"
|
||||
)
|
||||
@@ -183,6 +185,35 @@ func (e *Enforcer) deleteByTempToken(service string, tempToken string) error {
|
||||
return e.adapter.DeleteStr(e.spliceTempTokenKey(service, tempToken))
|
||||
}
|
||||
|
||||
func (e *Enforcer) createQRCode(id string, timeout int64) error {
|
||||
return e.adapter.Set(e.spliceQRCodeKey(id), model.NewQRCode(id), timeout)
|
||||
}
|
||||
|
||||
func (e *Enforcer) getQRCode(id string) *model.QRCode {
|
||||
i := e.adapter.Get(e.spliceQRCodeKey(id), util.GetType(&model.QRCode{}))
|
||||
if i == nil {
|
||||
return nil
|
||||
}
|
||||
return i.(*model.QRCode)
|
||||
}
|
||||
|
||||
func (e *Enforcer) getQRCodeTimeout(id string) int64 {
|
||||
return e.adapter.GetTimeout(id)
|
||||
}
|
||||
|
||||
func (e *Enforcer) updateQRCodeState(id string, state model.QRCodeState) error {
|
||||
qrCode := e.getQRCode(id)
|
||||
if qrCode == nil {
|
||||
return fmt.Errorf("QRCode doesn't exist")
|
||||
}
|
||||
qrCode.State = state
|
||||
return e.updateQRCode(id, qrCode)
|
||||
}
|
||||
|
||||
func (e *Enforcer) updateQRCode(id string, qrCode *model.QRCode) error {
|
||||
return e.adapter.Update(e.spliceQRCodeKey(id), qrCode)
|
||||
}
|
||||
|
||||
func (e *Enforcer) getByTempToken(service string, tempToken string) string {
|
||||
return e.adapter.GetStr(e.spliceTempTokenKey(service, tempToken))
|
||||
}
|
||||
@@ -209,6 +240,10 @@ func (e *Enforcer) spliceTempTokenKey(service string, token string) string {
|
||||
return e.config.TokenName + ":" + "temp-token" + ":temp:" + service + ":" + token
|
||||
}
|
||||
|
||||
func (e *Enforcer) spliceQRCodeKey(QRCodeId string) string {
|
||||
return e.config.TokenName + ":" + "QRCode" + ":QRCode" + QRCodeId
|
||||
}
|
||||
|
||||
func (e *Enforcer) SetJwtSecretKey(key string) {
|
||||
e.config.JwtSecretKey = key
|
||||
}
|
||||
|
@@ -225,3 +225,99 @@ func (e *Enforcer) ParseTempToken(service string, tempToken string) string {
|
||||
func (e *Enforcer) DeleteTempToken(service string, tempToken string) error {
|
||||
return e.deleteByTempToken(service, tempToken)
|
||||
}
|
||||
|
||||
func (e *Enforcer) CreateQRCodeState(QRCodeId string, timeout int64) error {
|
||||
return e.createQRCode(QRCodeId, timeout)
|
||||
}
|
||||
|
||||
// Scanned update state to constant.WaitAuth, return tempToken
|
||||
func (e *Enforcer) Scanned(QRCodeId string, token string) (string, error) {
|
||||
err := e.CheckLoginByToken(token)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
err = e.CheckQRCodeState(QRCodeId, model.WaitScan)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
err = e.updateQRCodeState(QRCodeId, model.WaitAuth)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
tempToken, err := e.CreateTempToken(e.config.TokenStyle, "qrCode", QRCodeId, e.config.Timeout)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return tempToken, nil
|
||||
}
|
||||
|
||||
// ConfirmAuth update state to constant.ConfirmAuth
|
||||
func (e *Enforcer) ConfirmAuth(tempToken string) error {
|
||||
qrCodeId := e.ParseTempToken("qrCode", tempToken)
|
||||
if qrCodeId == "" {
|
||||
return fmt.Errorf("confirm failed, tempToken error: %v", tempToken)
|
||||
}
|
||||
err := e.CheckQRCodeState(qrCodeId, model.WaitAuth)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = e.updateQRCodeState(qrCodeId, model.ConfirmAuth)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = e.DeleteTempToken("qrCode", tempToken)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// CancelAuth update state to constant.CancelAuth
|
||||
func (e *Enforcer) CancelAuth(tempToken string) error {
|
||||
qrCodeId := e.ParseTempToken("qrCode", tempToken)
|
||||
if qrCodeId == "" {
|
||||
return fmt.Errorf("confirm failed, tempToken error: %v", qrCodeId)
|
||||
}
|
||||
err := e.CheckQRCodeState(qrCodeId, model.WaitAuth)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = e.updateQRCodeState(qrCodeId, model.CancelAuth)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = e.DeleteTempToken("qrCode", tempToken)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (e *Enforcer) GetQRCode(QRCodeId string) *model.QRCode {
|
||||
return e.getQRCode(QRCodeId)
|
||||
}
|
||||
|
||||
// GetQRCodeState
|
||||
// WaitScan = 1
|
||||
// WaitAuth = 2
|
||||
// ConfirmAuth = 3
|
||||
// CancelAuth = 4
|
||||
// Expired = 5
|
||||
func (e *Enforcer) GetQRCodeState(QRCodeId string) model.QRCodeState {
|
||||
qrCode := e.getQRCode(QRCodeId)
|
||||
if qrCode == nil {
|
||||
return model.Expired
|
||||
}
|
||||
return qrCode.State
|
||||
}
|
||||
|
||||
func (e *Enforcer) GetQRCodeTimeout(QRCodeId string) int64 {
|
||||
return e.getQRCodeTimeout(QRCodeId)
|
||||
}
|
||||
|
||||
func (e *Enforcer) CheckQRCodeState(QRCodeId string, want model.QRCodeState) error {
|
||||
if s := e.GetQRCodeState(QRCodeId); s != want {
|
||||
return fmt.Errorf("QRCode state error: unexpected state value %v, want is %v", s, want)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
package token_go
|
||||
|
||||
import (
|
||||
"github.com/weloe/token-go/model"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -33,3 +34,67 @@ func TestEnforcer_TempToken(t *testing.T) {
|
||||
t.Errorf("ParseTempToken() failed, unexpected codeValue: %v", codeValue)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnforcer_ConfirmQRCode(t *testing.T) {
|
||||
enforcer, _ := NewTestEnforcer(t)
|
||||
// in APP
|
||||
token, err := enforcer.LoginById("1")
|
||||
if err != nil {
|
||||
t.Fatalf("Login failed: %v", err)
|
||||
}
|
||||
t.Logf("login token: %v", token)
|
||||
|
||||
qrCodeId := "q1"
|
||||
|
||||
err = enforcer.CreateQRCodeState(qrCodeId, -1)
|
||||
if err != nil {
|
||||
t.Fatalf("CreateQRCodeState() failed: %v", err)
|
||||
}
|
||||
t.Logf("After CreateQRCodeState(), current QRCode state: %v", enforcer.GetQRCodeState(qrCodeId))
|
||||
tempToken, err := enforcer.Scanned(qrCodeId, token)
|
||||
if err != nil {
|
||||
t.Fatalf("Scanned() failed: %v", err)
|
||||
}
|
||||
t.Logf("After Scanned(), current QRCode state: %v", enforcer.GetQRCodeState(qrCodeId))
|
||||
t.Logf("tempToken: %v", tempToken)
|
||||
err = enforcer.ConfirmAuth(tempToken)
|
||||
if err != nil {
|
||||
t.Fatalf("ConfirmAuth() failed: %v", err)
|
||||
}
|
||||
t.Logf("After ConfirmAuth(), current QRCode state: %v", enforcer.GetQRCodeState(qrCodeId))
|
||||
if enforcer.GetQRCodeState(qrCodeId) == model.ConfirmAuth {
|
||||
t.Logf(" QRCode login successfully.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnforcer_CancelAuthQRCode(t *testing.T) {
|
||||
enforcer, _ := NewTestEnforcer(t)
|
||||
// in APP
|
||||
token, err := enforcer.LoginById("1")
|
||||
if err != nil {
|
||||
t.Fatalf("Login failed: %v", err)
|
||||
}
|
||||
t.Logf("login token: %v", token)
|
||||
|
||||
qrCodeId := "q1"
|
||||
|
||||
err = enforcer.CreateQRCodeState(qrCodeId, -1)
|
||||
if err != nil {
|
||||
t.Fatalf("CreateQRCodeState() failed: %v", err)
|
||||
}
|
||||
t.Logf("After CreateQRCodeState(), current QRCode state: %v", enforcer.GetQRCodeState(qrCodeId))
|
||||
tempToken, err := enforcer.Scanned(qrCodeId, token)
|
||||
if err != nil {
|
||||
t.Fatalf("Scanned() failed: %v", err)
|
||||
}
|
||||
t.Logf("After Scanned(), current QRCode state: %v", enforcer.GetQRCodeState(qrCodeId))
|
||||
t.Logf("tempToken: %v", tempToken)
|
||||
err = enforcer.CancelAuth(tempToken)
|
||||
if err != nil {
|
||||
t.Fatalf("CancelAuth() failed: %v", err)
|
||||
}
|
||||
t.Logf("After CancelAuth(), current QRCode state: %v", enforcer.GetQRCodeState(qrCodeId))
|
||||
if enforcer.GetQRCodeState(qrCodeId) == model.CancelAuth {
|
||||
t.Logf(" QRCode login is cancelled.")
|
||||
}
|
||||
}
|
||||
|
23
model/qrcode.go
Normal file
23
model/qrcode.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package model
|
||||
|
||||
type QRCodeState int
|
||||
|
||||
// QRCode State
|
||||
const (
|
||||
WaitScan QRCodeState = 1
|
||||
WaitAuth QRCodeState = 2
|
||||
ConfirmAuth QRCodeState = 3
|
||||
CancelAuth QRCodeState = 4
|
||||
Expired QRCodeState = 5
|
||||
)
|
||||
|
||||
type QRCode struct {
|
||||
id string
|
||||
State QRCodeState
|
||||
LoginId string
|
||||
Ticket string
|
||||
}
|
||||
|
||||
func NewQRCode(id string) *QRCode {
|
||||
return &QRCode{id: id, State: WaitScan}
|
||||
}
|
Reference in New Issue
Block a user