diff --git a/enforcer.go b/enforcer.go index 1a33cc9..29ead8f 100644 --- a/enforcer.go +++ b/enforcer.go @@ -4,7 +4,6 @@ import ( "errors" "fmt" "github.com/weloe/token-go/config" - "github.com/weloe/token-go/constant" "github.com/weloe/token-go/ctx" httpCtx "github.com/weloe/token-go/ctx/go-http-context" "github.com/weloe/token-go/log" @@ -13,7 +12,6 @@ import ( "github.com/weloe/token-go/util" log2 "log" "net/http" - "strconv" ) type Enforcer struct { @@ -183,21 +181,22 @@ func (e *Enforcer) LoginByModel(id string, loginModel *model.Login, ctx ctx.Cont // add tokenSign if session = e.GetSession(id); session == nil { - session = model.NewSession(e.spliceSessionKey(id), "account-session", id) + session = model.NewSession("0", "account-session", id) } session.AddTokenSign(&model.TokenSign{ Value: tokenValue, Device: loginModel.Device, }) + timeout := loginModel.Timeout // reset session - err = e.SetSession(id, session, loginModel.Timeout) + err = e.SetSession(id, session, timeout) if err != nil { return "", err } // set token-id - err = e.adapter.SetStr(e.spliceTokenKey(tokenValue), id, loginModel.Timeout) + err = e.SetIdByToken(id, tokenValue, timeout) if err != nil { return "", err } @@ -212,7 +211,7 @@ func (e *Enforcer) LoginByModel(id string, loginModel *model.Login, ctx ctx.Cont m := &model.Login{ Device: loginModel.Device, IsLastingCookie: loginModel.IsLastingCookie, - Timeout: loginModel.Timeout, + Timeout: timeout, JwtData: loginModel.JwtData, Token: tokenValue, IsWriteHeader: loginModel.IsWriteHeader, @@ -234,13 +233,14 @@ func (e *Enforcer) LoginByModel(id string, loginModel *model.Login, ctx ctx.Cont for _, tokenSign := range session.TokenSignList { if session.TokenSignSize() > int(tokenConfig.MaxLoginCount) { // delete tokenSign - session.RemoveTokenSign(tokenSign.Value) + tokenSignValue := tokenSign.Value + session.RemoveTokenSign(tokenSignValue) err = e.UpdateSession(id, session) if err != nil { return "", err } // delete token-id - err = e.adapter.Delete(e.spliceTokenKey(tokenSign.Value)) + err = e.deleteIdByToken(tokenSignValue) if err != nil { return "", err } @@ -262,40 +262,6 @@ func (e *Enforcer) LoginByModel(id string, loginModel *model.Login, ctx ctx.Cont return tokenValue, nil } -// Replaced replace other user -func (e *Enforcer) Replaced(id string, device string) error { - var err error - if session := e.GetSession(id); session != nil { - // get by login device - tokenSignList := session.GetFilterTokenSign(device) - // sign account replaced - for element := tokenSignList.Front(); element != nil; element = element.Next() { - if tokenSign, ok := element.Value.(*model.TokenSign); ok { - elementV := tokenSign.Value - session.RemoveTokenSign(elementV) - err = e.UpdateSession(id, session) - if err != nil { - return err - } - // sign token replaced - err = e.adapter.UpdateStr(e.spliceTokenKey(elementV), strconv.Itoa(constant.BeReplaced)) - if err != nil { - return err - } - - // called logger - e.logger.Replace(e.loginType, id, tokenSign.Value) - - // called watcher - if e.watcher != nil { - e.watcher.Replace(e.loginType, id, tokenSign.Value) - } - } - } - } - return nil -} - // Logout user logout func (e *Enforcer) Logout(ctx ctx.Context) error { tokenConfig := e.config @@ -341,7 +307,7 @@ func (e *Enforcer) LogoutByToken(token string) error { return errors.New("user not logged in") } // delete token-id - err = e.adapter.Delete(e.spliceTokenKey(token)) + err = e.deleteIdByToken(token) if err != nil { return err } @@ -404,7 +370,7 @@ func (e *Enforcer) GetIdByToken(token string) string { if token == "" { return "" } - return e.adapter.GetStr(e.spliceTokenKey(token)) + return e.getIdByToken(token) } // IsLogin check if user logged in by token. @@ -468,118 +434,12 @@ func (e *Enforcer) GetLoginCount(id string) int { return 0 } -// Banned ban user, if time == 0,the timeout is not set -func (e *Enforcer) Banned(id string, service string, level int, time int64) error { - if id == "" || service == "" { - return fmt.Errorf("parameter cannot be nil") - } - if level < 1 { - return fmt.Errorf("unexpected level = %v, level must large or equal 1", level) - } - err := e.adapter.SetStr(e.spliceBannedKey(id, service), strconv.Itoa(level), time) - if err != nil { - return err - } - - // callback - e.logger.Ban(e.loginType, id, service, level, time) - if e.watcher != nil { - e.watcher.Ban(e.loginType, id, service, level, time) - } - - return nil -} - -// UnBanned Unblock user account -func (e *Enforcer) UnBanned(id string, services ...string) error { - if id == "" { - return fmt.Errorf("parmeter id can not be nil") - } - if len(services) == 0 { - return fmt.Errorf("parmeter services length can not be 0") - } - - for _, service := range services { - err := e.adapter.DeleteStr(e.spliceBannedKey(id, service)) - if err != nil { - return err - } - e.logger.UnBan(e.loginType, id, service) - if e.watcher != nil { - e.watcher.UnBan(e.loginType, id, service) - } - } - return nil -} - -// IsBanned if banned return true, else return false -func (e *Enforcer) IsBanned(id string, services string) bool { - s := e.adapter.GetStr(e.spliceBannedKey(id, services)) - - return s != "" -} - -// GetBannedLevel get banned level -func (e *Enforcer) GetBannedLevel(id string, service string) (int64, error) { - str := e.adapter.GetStr(e.spliceBannedKey(id, service)) - if str == "" { - return 0, fmt.Errorf("loginId = %v, service = %v is not banned", id, service) - } - time, err := strconv.ParseInt(str, 10, 64) - if err != nil { - return 0, err - } - return time, nil -} - // GetBannedTime get banned time func (e *Enforcer) GetBannedTime(id string, service string) int64 { - timeout := e.adapter.GetStrTimeout(e.spliceBannedKey(id, service)) + timeout := e.getBannedTime(id, service) return timeout } -// Kickout kickout user -func (e *Enforcer) Kickout(id string, device string) error { - session := e.GetSession(id) - if session != nil { - // get by login device - tokenSignList := session.GetFilterTokenSign(device) - // sign account kicked - for element := tokenSignList.Front(); element != nil; element = element.Next() { - if tokenSign, ok := element.Value.(*model.TokenSign); ok { - elementV := tokenSign.Value - session.RemoveTokenSign(elementV) - err := e.UpdateSession(id, session) - if err != nil { - return err - } - // sign token kicked - err = e.adapter.UpdateStr(e.spliceTokenKey(elementV), strconv.Itoa(constant.BeKicked)) - if err != nil { - return err - } - - // called logger - e.logger.Kickout(e.loginType, id, tokenSign.Value) - - // called watcher - if e.watcher != nil { - e.watcher.Kickout(e.loginType, id, tokenSign.Value) - } - } - } - - } - // check TokenSignList length, if length == 0, delete this session - if session != nil && session.TokenSignSize() == 0 { - err := e.DeleteSession(id) - if err != nil { - return err - } - } - return nil -} - // GetRequestToken read token from requestHeader | cookie | requestBody func (e *Enforcer) GetRequestToken(ctx ctx.Context) string { var tokenValue string @@ -606,7 +466,7 @@ func (e *Enforcer) GetRequestToken(ctx ctx.Context) string { } // AddTokenGenerateFun add token generate strategy -func (e *Enforcer) AddTokenGenerateFun(tokenStyle string, f model.GenerateFunc) error { +func (e *Enforcer) AddTokenGenerateFun(tokenStyle string, f model.HandlerFunc) error { e.generateFunc.AddFunc(tokenStyle, f) return nil } @@ -645,53 +505,3 @@ func (e *Enforcer) UpdateSession(id string, session *model.Session) error { func (e *Enforcer) GetTokenConfig() config.TokenConfig { return e.config } - -func (e *Enforcer) OpenSafe(token string, service string, time int64) error { - if time == 0 { - return nil - } - err := e.CheckLoginByToken(token) - if err != nil { - return err - } - err = e.adapter.SetStr(e.spliceSecSafeKey(token, service), constant.DefaultSecondAuthValue, time) - if err != nil { - return err - } - e.logger.OpenSafe(e.loginType, token, service, time) - if e.watcher != nil { - e.watcher.OpenSafe(e.loginType, token, service, time) - } - return nil -} - -func (e *Enforcer) IsSafe(token string, service string) bool { - if token == "" { - return false - } - str := e.adapter.GetStr(e.spliceSecSafeKey(token, service)) - return str != "" -} - -func (e *Enforcer) GetSafeTime(token string, service string) int64 { - if token == "" { - return 0 - } - timeout := e.adapter.GetTimeout(e.spliceSecSafeKey(token, service)) - return timeout -} - -func (e *Enforcer) CloseSafe(token string, service string) error { - if token == "" { - return nil - } - err := e.adapter.DeleteStr(e.spliceSecSafeKey(token, service)) - if err != nil { - return err - } - e.logger.CloseSafe(e.loginType, token, service) - if e.watcher != nil { - e.watcher.CloseSafe(e.loginType, token, service) - } - return nil -} diff --git a/enforcer_interface.go b/enforcer_interface.go index cae98c8..dcc1c01 100644 --- a/enforcer_interface.go +++ b/enforcer_interface.go @@ -68,7 +68,7 @@ type IEnforcer interface { DeleteTempToken(service string, tempToken string) error GetRequestToken(ctx ctx.Context) string - AddTokenGenerateFun(tokenStyle string, f model.GenerateFunc) error + AddTokenGenerateFun(tokenStyle string, f model.HandlerFunc) error // Access control api SetAuth(manager interface{}) diff --git a/enforcer_internal_api.go b/enforcer_internal_api.go index 4df216d..126efd3 100644 --- a/enforcer_internal_api.go +++ b/enforcer_internal_api.go @@ -111,14 +111,90 @@ func (e *Enforcer) checkId(str string) (bool, error) { return true, nil } +func (e *Enforcer) SetIdByToken(id string, tokenValue string, timeout int64) error { + err := e.adapter.SetStr(e.spliceTokenKey(tokenValue), id, timeout) + return err +} + +func (e *Enforcer) getIdByToken(token string) string { + return e.adapter.GetStr(e.spliceTokenKey(token)) +} + +func (e *Enforcer) deleteIdByToken(tokenValue string) error { + err := e.adapter.DeleteStr(e.spliceTokenKey(tokenValue)) + return err +} + +func (e *Enforcer) updateIdByToken(tokenValue string, id string) error { + err := e.adapter.UpdateStr(e.spliceTokenKey(tokenValue), id) + return err +} + +func (e *Enforcer) setBanned(id string, service string, level int, time int64) error { + err := e.adapter.SetStr(e.spliceBannedKey(id, service), strconv.Itoa(level), time) + return err +} + +func (e *Enforcer) deleteBanned(id string, service string) error { + err := e.adapter.DeleteStr(e.spliceBannedKey(id, service)) + return err +} + +func (e *Enforcer) getBanned(id string, services string) string { + s := e.adapter.GetStr(e.spliceBannedKey(id, services)) + return s +} + +func (e *Enforcer) getBannedTime(id string, service string) int64 { + timeout := e.adapter.GetStrTimeout(e.spliceBannedKey(id, service)) + return timeout +} + +func (e *Enforcer) setSecSafe(token string, service string, time int64) error { + err := e.adapter.SetStr(e.spliceSecSafeKey(token, service), constant.DefaultSecondAuthValue, time) + return err +} + +func (e *Enforcer) getSafeTime(token string, service string) int64 { + timeout := e.adapter.GetTimeout(e.spliceSecSafeKey(token, service)) + return timeout +} + +func (e *Enforcer) getSecSafe(token string, service string) string { + str := e.adapter.GetStr(e.spliceSecSafeKey(token, service)) + return str +} + +func (e *Enforcer) deleteSecSafe(token string, service string) error { + err := e.adapter.DeleteStr(e.spliceSecSafeKey(token, service)) + return err +} + +func (e *Enforcer) setTempToken(service string, token string, value string, timeout int64) error { + err := e.adapter.SetStr(e.spliceTempTokenKey(service, token), value, timeout) + return err +} + +func (e *Enforcer) getTimeoutByTempToken(service string, token string) int64 { + return e.adapter.GetTimeout(e.spliceTempTokenKey(service, token)) +} + +func (e *Enforcer) deleteByTempToken(service string, tempToken string) error { + return e.adapter.DeleteStr(e.spliceTempTokenKey(service, tempToken)) +} + +func (e *Enforcer) getByTempToken(service string, tempToken string) string { + return e.adapter.GetStr(e.spliceTempTokenKey(service, tempToken)) +} + // spliceSessionKey splice session-id key func (e *Enforcer) spliceSessionKey(id string) string { return e.config.TokenName + ":" + e.loginType + ":session:" + id } // spliceTokenKey splice token-id key -func (e *Enforcer) spliceTokenKey(id string) string { - return e.config.TokenName + ":" + e.loginType + ":token:" + id +func (e *Enforcer) spliceTokenKey(token string) string { + return e.config.TokenName + ":" + e.loginType + ":token:" + token } func (e *Enforcer) spliceBannedKey(id string, service string) string { diff --git a/enforcer_manager_api.go b/enforcer_manager_api.go new file mode 100644 index 0000000..0ec5c20 --- /dev/null +++ b/enforcer_manager_api.go @@ -0,0 +1,227 @@ +package token_go + +import ( + "fmt" + "github.com/weloe/token-go/constant" + "github.com/weloe/token-go/model" + "strconv" +) + +// Replaced replace other user +func (e *Enforcer) Replaced(id string, device string) error { + var err error + if session := e.GetSession(id); session != nil { + // get by login device + tokenSignList := session.GetFilterTokenSign(device) + // sign account replaced + for element := tokenSignList.Front(); element != nil; element = element.Next() { + if tokenSign, ok := element.Value.(*model.TokenSign); ok { + elementV := tokenSign.Value + session.RemoveTokenSign(elementV) + err = e.UpdateSession(id, session) + if err != nil { + return err + } + // sign token replaced + err = e.updateIdByToken(elementV, strconv.Itoa(constant.BeReplaced)) + if err != nil { + return err + } + + // called logger + e.logger.Replace(e.loginType, id, elementV) + + // called watcher + if e.watcher != nil { + e.watcher.Replace(e.loginType, id, elementV) + } + } + } + } + return nil +} + +// Kickout kickout user +func (e *Enforcer) Kickout(id string, device string) error { + session := e.GetSession(id) + if session != nil { + // get by login device + tokenSignList := session.GetFilterTokenSign(device) + // sign account kicked + for element := tokenSignList.Front(); element != nil; element = element.Next() { + if tokenSign, ok := element.Value.(*model.TokenSign); ok { + elementV := tokenSign.Value + session.RemoveTokenSign(elementV) + err := e.UpdateSession(id, session) + if err != nil { + return err + } + // sign token kicked + err = e.updateIdByToken(elementV, strconv.Itoa(constant.BeKicked)) + if err != nil { + return err + } + + // called logger + e.logger.Kickout(e.loginType, id, elementV) + + // called watcher + if e.watcher != nil { + e.watcher.Kickout(e.loginType, id, elementV) + } + } + } + + } + // check TokenSignList length, if length == 0, delete this session + if session != nil && session.TokenSignSize() == 0 { + err := e.DeleteSession(id) + if err != nil { + return err + } + } + return nil +} + +// Banned ban user, if time == 0,the timeout is not set +func (e *Enforcer) Banned(id string, service string, level int, time int64) error { + if id == "" || service == "" { + return fmt.Errorf("parameter cannot be nil") + } + if level < 1 { + return fmt.Errorf("unexpected level = %v, level must large or equal 1", level) + } + err := e.setBanned(id, service, level, time) + if err != nil { + return err + } + + // callback + e.logger.Ban(e.loginType, id, service, level, time) + if e.watcher != nil { + e.watcher.Ban(e.loginType, id, service, level, time) + } + + return nil +} + +// UnBanned Unblock user account +func (e *Enforcer) UnBanned(id string, services ...string) error { + if id == "" { + return fmt.Errorf("parmeter id can not be nil") + } + if len(services) == 0 { + return fmt.Errorf("parmeter services length can not be 0") + } + + for _, service := range services { + err := e.deleteBanned(id, service) + if err != nil { + return err + } + e.logger.UnBan(e.loginType, id, service) + if e.watcher != nil { + e.watcher.UnBan(e.loginType, id, service) + } + } + return nil +} + +// IsBanned if banned return true, else return false +func (e *Enforcer) IsBanned(id string, service string) bool { + level := e.getBanned(id, service) + return level != "" +} + +// GetBannedLevel get banned level +func (e *Enforcer) GetBannedLevel(id string, service string) (int64, error) { + str := e.getBanned(id, service) + if str == "" { + return 0, fmt.Errorf("loginId = %v, service = %v is not banned", id, service) + } + time, err := strconv.ParseInt(str, 10, 64) + if err != nil { + return 0, err + } + return time, nil +} + +func (e *Enforcer) OpenSafe(token string, service string, time int64) error { + if time == 0 { + return nil + } + err := e.CheckLoginByToken(token) + if err != nil { + return err + } + err = e.setSecSafe(token, service, time) + if err != nil { + return err + } + e.logger.OpenSafe(e.loginType, token, service, time) + if e.watcher != nil { + e.watcher.OpenSafe(e.loginType, token, service, time) + } + return nil +} + +func (e *Enforcer) IsSafe(token string, service string) bool { + if token == "" { + return false + } + str := e.getSecSafe(token, service) + return str != "" +} + +func (e *Enforcer) GetSafeTime(token string, service string) int64 { + if token == "" { + return 0 + } + timeout := e.getSafeTime(token, service) + return timeout +} + +func (e *Enforcer) CloseSafe(token string, service string) error { + if token == "" { + return nil + } + err := e.deleteSecSafe(token, service) + if err != nil { + return err + } + e.logger.CloseSafe(e.loginType, token, service) + if e.watcher != nil { + e.watcher.CloseSafe(e.loginType, token, service) + } + return nil +} + +func (e *Enforcer) CreateTempToken(style string, service string, value string, timeout int64) (string, error) { + token, err := e.generateFunc.Exec(style) + if err != nil { + return "", err + } + err = e.setTempToken(service, token, value, timeout) + if err != nil { + return "", err + } + return token, nil +} + +func (e *Enforcer) GetTempTokenTimeout(service string, tempToken string) int64 { + if tempToken == "" { + return constant.NotValueExpire + } + return e.getTimeoutByTempToken(service, tempToken) +} + +func (e *Enforcer) ParseTempToken(service string, tempToken string) string { + if tempToken == "" { + return "" + } + return e.getByTempToken(service, tempToken) +} + +func (e *Enforcer) DeleteTempToken(service string, tempToken string) error { + return e.deleteByTempToken(service, tempToken) +} diff --git a/enforcer_temp_token_api_test.go b/enforcer_manager_api_test.go similarity index 100% rename from enforcer_temp_token_api_test.go rename to enforcer_manager_api_test.go diff --git a/enforcer_temp_token_api.go b/enforcer_temp_token_api.go deleted file mode 100644 index 4d27ec3..0000000 --- a/enforcer_temp_token_api.go +++ /dev/null @@ -1,33 +0,0 @@ -package token_go - -import "github.com/weloe/token-go/constant" - -func (e *Enforcer) CreateTempToken(style string, service string, value string, timeout int64) (string, error) { - token, err := e.generateFunc.Exec(style) - if err != nil { - return "", err - } - err = e.adapter.SetStr(e.spliceTempTokenKey(service, token), value, timeout) - if err != nil { - return "", err - } - return token, nil -} - -func (e *Enforcer) GetTempTokenTimeout(service string, tempToken string) int64 { - if tempToken == "" { - return constant.NotValueExpire - } - return e.adapter.GetTimeout(e.spliceTempTokenKey(service, tempToken)) -} - -func (e *Enforcer) ParseTempToken(service string, tempToken string) string { - if tempToken == "" { - return "" - } - return e.adapter.GetStr(e.spliceTempTokenKey(service, tempToken)) -} - -func (e *Enforcer) DeleteTempToken(service string, tempToken string) error { - return e.adapter.DeleteStr(e.spliceTempTokenKey(service, tempToken)) -} diff --git a/model/function.go b/model/function.go index 6d788fc..2662298 100644 --- a/model/function.go +++ b/model/function.go @@ -7,7 +7,7 @@ import ( "sync" ) -type GenerateFunc func() (string, error) +type HandlerFunc func() (string, error) type GenerateTokenFunc struct { fns *sync.Map @@ -28,7 +28,7 @@ func (g *GenerateTokenFunc) Exec(tokenForm string) (string, error) { return s, nil } -func (g *GenerateTokenFunc) GetFunction(tokenForm string) (GenerateFunc, error) { +func (g *GenerateTokenFunc) GetFunction(tokenForm string) (HandlerFunc, error) { value, ok := g.fns.Load(tokenForm) if !ok { return nil, errors.New("GetFunction() failed: load func error") @@ -36,7 +36,7 @@ func (g *GenerateTokenFunc) GetFunction(tokenForm string) (GenerateFunc, error) if value == nil { return nil, errors.New("GetFunction() failed: this tokenStyle generate func doesn't exist") } - handlerFunc := value.(GenerateFunc) + handlerFunc := value.(HandlerFunc) return handlerFunc, nil } @@ -51,6 +51,6 @@ func LoadFunctionMap() GenerateTokenFunc { return *fm } -func (g *GenerateTokenFunc) AddFunc(key string, f GenerateFunc) { +func (g *GenerateTokenFunc) AddFunc(key string, f HandlerFunc) { g.fns.LoadOrStore(key, f) }