feat: add param device, update LoginByModel

This commit is contained in:
weloe
2023-10-28 01:24:21 +08:00
parent 7b920a1a59
commit 90e576f015
6 changed files with 130 additions and 43 deletions

View File

@@ -183,10 +183,13 @@ func (e *Enforcer) IsLogEnable() bool {
// Login login by id and default loginModel, return tokenValue and error // Login login by id and default loginModel, return tokenValue and error
func (e *Enforcer) Login(id string, ctx ctx.Context) (string, error) { func (e *Enforcer) Login(id string, ctx ctx.Context) (string, error) {
return e.LoginByModel(id, model.DefaultLoginModel(), ctx) return e.LoginByModel(id, model.CreateLoginModelByDevice(""), ctx)
} }
func (e *Enforcer) LoginById(id string) (string, error) { func (e *Enforcer) LoginById(id string, device ...string) (string, error) {
if len(device) > 0 && device[0] != "" {
return e.LoginByModel(id, model.CreateLoginModelByDevice(device[0]), nil)
}
return e.Login(id, nil) return e.Login(id, nil)
} }
@@ -256,38 +259,37 @@ func (e *Enforcer) LoginByModel(id string, loginModel *model.Login, ctx ctx.Cont
if session = e.GetSession(id); session != nil { if session = e.GetSession(id); session != nil {
// get by login device // get by login device
tokenSignList := session.GetFilterTokenSign(device) tokenSignList := session.GetFilterTokenSign(device)
if tokenSignList.Len() <= int(tokenConfig.DeviceMaxLoginCount) { if tokenSignList.Len() > int(tokenConfig.DeviceMaxLoginCount) {
return tokenValue, nil // if loginCount > maxLoginCount, logout account until single device Login count is equal to DeviceMaxLoginCount
} for element := tokenSignList.Front(); element != nil; element = element.Next() {
// if loginCount > maxLoginCount, logout account until single device Login count is equal to DeviceMaxLoginCount if tokenSign, ok := element.Value.(*model.TokenSign); ok {
for element := tokenSignList.Front(); element != nil; element = element.Next() { if session.TokenSignSize() > int(tokenConfig.DeviceMaxLoginCount) {
if tokenSign, ok := element.Value.(*model.TokenSign); ok { // delete tokenSign
if session.TokenSignSize() > int(tokenConfig.DeviceMaxLoginCount) { tokenSignValue := tokenSign.Value
// delete tokenSign session.RemoveTokenSign(tokenSignValue)
tokenSignValue := tokenSign.Value err = e.UpdateSession(id, session)
session.RemoveTokenSign(tokenSignValue) if err != nil {
err = e.UpdateSession(id, session) return "", err
if err != nil { }
return "", err // delete token-id
} err = e.deleteIdByToken(tokenSignValue)
// delete token-id if err != nil {
err = e.deleteIdByToken(tokenSignValue) return "", err
if err != nil { }
return "", err e.logger.Logout(e.loginType, id, tokenSignValue)
}
e.logger.Logout(e.loginType, id, tokenSignValue)
if e.watcher != nil { if e.watcher != nil {
e.watcher.Logout(e.loginType, id, tokenSignValue) e.watcher.Logout(e.loginType, id, tokenSignValue)
}
} }
} }
} }
} // check TokenSignList length, if length == 0, delete this session
// check TokenSignList length, if length == 0, delete this session if session != nil && session.TokenSignSize() == 0 {
if session != nil && session.TokenSignSize() == 0 { err = e.DeleteSession(id)
err = e.DeleteSession(id) if err != nil {
if err != nil { return "", err
return "", err }
} }
} }
} }
@@ -358,13 +360,20 @@ func (e *Enforcer) Logout(ctx ctx.Context) error {
} }
// LogoutById force user to logout // LogoutById force user to logout
func (e *Enforcer) LogoutById(id string) error { func (e *Enforcer) LogoutById(id string, device ...string) error {
session := e.GetSession(id) session := e.GetSession(id)
if session != nil { if session != nil {
for _, tokenSign := range session.TokenSignList { for _, tokenSign := range session.TokenSignList {
err := e.LogoutByToken(tokenSign.Value) if len(device) > 0 && device[0] != "" && tokenSign.Device == device[0] {
if err != nil { err := e.LogoutByToken(tokenSign.Value)
return err if err != nil {
return err
}
} else {
err := e.LogoutByToken(tokenSign.Value)
if err != nil {
return err
}
} }
} }
} }
@@ -412,11 +421,16 @@ func (e *Enforcer) LogoutByToken(token string) error {
// IsLoginById check if user logged in by loginId. // IsLoginById check if user logged in by loginId.
// check all tokenValue and if one is validated return true // check all tokenValue and if one is validated return true
func (e *Enforcer) IsLoginById(id string) (bool, error) { func (e *Enforcer) IsLoginById(id string, device ...string) (bool, error) {
var err error var err error
session := e.GetSession(id) session := e.GetSession(id)
if session != nil { if session != nil {
l := session.TokenSignList var l []*model.TokenSign
if len(device) > 0 && device[0] != "" {
l = session.GetFilterTokenSignSlice(device[0])
} else {
l = session.TokenSignList
}
for _, tokenSign := range l { for _, tokenSign := range l {
err = e.CheckLoginByToken(tokenSign.Value) err = e.CheckLoginByToken(tokenSign.Value)
if err != nil { if err != nil {
@@ -500,8 +514,12 @@ func (e *Enforcer) GetLoginIdByToken(token string) (string, error) {
return str, nil return str, nil
} }
func (e *Enforcer) GetLoginCount(id string) int { func (e *Enforcer) GetLoginCount(id string, device ...string) int {
if session := e.GetSession(id); session != nil { if session := e.GetSession(id); session != nil {
if len(device) > 0 && device[0] != "" {
return session.GetFilterTokenSign(device[0]).Len()
}
return session.TokenSignSize() return session.TokenSignSize()
} }
return 0 return 0

View File

@@ -26,16 +26,16 @@ type IEnforcer interface {
// Login login api // Login login api
Login(id string, ctx ctx.Context) (string, error) Login(id string, ctx ctx.Context) (string, error)
LoginById(id string) (string, error) LoginById(id string, device ...string) (string, error)
LoginByModel(id string, loginModel *model.Login, ctx ctx.Context) (string, error) LoginByModel(id string, loginModel *model.Login, ctx ctx.Context) (string, error)
Logout(ctx ctx.Context) error Logout(ctx ctx.Context) error
LogoutById(id string) error LogoutById(id string, device ...string) error
LogoutByToken(token string) error LogoutByToken(token string) error
IsLogin(ctx ctx.Context) (bool, error) IsLogin(ctx ctx.Context) (bool, error)
IsLoginByToken(token string) (bool, error) IsLoginByToken(token string) (bool, error)
IsLoginById(id string) (bool, error) IsLoginById(id string, device ...string) (bool, error)
CheckLogin(ctx ctx.Context) error CheckLogin(ctx ctx.Context) error
CheckLoginByToken(token string) error CheckLoginByToken(token string) error
@@ -43,7 +43,7 @@ type IEnforcer interface {
GetLoginIdByToken(token string) (string, error) GetLoginIdByToken(token string) (string, error)
GetId(ctx ctx.Context) string GetId(ctx ctx.Context) string
GetIdByToken(token string) string GetIdByToken(token string) string
GetLoginCount(id string) int GetLoginCount(id string, device ...string) int
GetLoginCounts() (int, error) GetLoginCounts() (int, error)
GetLoginTokenCounts() (int, error) GetLoginTokenCounts() (int, error)

View File

@@ -13,7 +13,7 @@ func (e *Enforcer) Replaced(id string, device ...string) error {
var err error var err error
if session := e.GetSession(id); session != nil { if session := e.GetSession(id); session != nil {
var tokenSignList *list.List var tokenSignList *list.List
if len(device) == 0 { if len(device) == 0 || device[0] == "" {
tokenSignList = session.GetTokenSignListCopy() tokenSignList = session.GetTokenSignListCopy()
} else { } else {
// get by login device // get by login device
@@ -52,7 +52,7 @@ func (e *Enforcer) Kickout(id string, device ...string) error {
session := e.GetSession(id) session := e.GetSession(id)
if session != nil { if session != nil {
var tokenSignList *list.List var tokenSignList *list.List
if len(device) == 0 { if len(device) == 0 || device[0] == "" {
tokenSignList = session.GetTokenSignListCopy() tokenSignList = session.GetTokenSignListCopy()
} else { } else {
// get by login device // get by login device

View File

@@ -189,6 +189,10 @@ func TestEnforcer_Login(t *testing.T) {
if !login { if !login {
t.Errorf("IsLoginById() failed: IsLoginById() = %v", login) t.Errorf("IsLoginById() failed: IsLoginById() = %v", login)
} }
err = enforcer.Replaced("1")
if err != nil {
t.Errorf("Replaced() failed: %v", err)
}
err = enforcer.Replaced("1", loginModel.Device) err = enforcer.Replaced("1", loginModel.Device)
if err != nil { if err != nil {
t.Errorf("Replaced() failed: %v", err) t.Errorf("Replaced() failed: %v", err)
@@ -365,6 +369,46 @@ func TestEnforcer_ConcurrentNotShareMultiLogin(t *testing.T) {
} }
func TestEnforcer_ConcurrentNotShareMultiDeviceLogin(t *testing.T) {
var err error
err, enforcer, _ := NewTestConcurrentEnforcer(t)
t.Logf("concurrent: %v, share: %v", enforcer.config.IsConcurrent, enforcer.config.IsShare)
if err != nil {
t.Errorf("InitWithConfig() failed: %v", err)
}
for i := 0; i < 14; i++ {
_, err = enforcer.LoginById("id", fmt.Sprintf("device%v", i))
if err != nil {
t.Errorf("Login() failed: %v", err)
}
}
session := enforcer.GetSession("id")
if session.TokenSignSize() != 12 {
t.Errorf("Login() failed: unexpected session.TokenSignList length = %v", session.TokenSignSize())
}
b, err := enforcer.IsLoginById("id")
if err != nil {
t.Log(err)
}
if b == false {
t.Errorf("IsLoginById = %v, want is true", false)
}
b, err = enforcer.IsLoginById("id", "device0")
if err != nil {
t.Log(err)
}
if b == true {
t.Errorf("IsLoginById = %v, want is false", true)
}
if count := enforcer.GetLoginCount("id"); count != 12 {
t.Errorf("Login() failed: unexpected login count = %v", count)
}
if count := enforcer.GetLoginCount("id", "device1"); count != 0 {
t.Errorf("Login() failed: unexpected login count = %v", count)
}
}
func TestNewDefaultEnforcer(t *testing.T) { func TestNewDefaultEnforcer(t *testing.T) {
err, ctx := NewTestHttpContext(t) err, ctx := NewTestHttpContext(t)
if ctx == nil { if ctx == nil {

View File

@@ -19,3 +19,14 @@ func DefaultLoginModel() *Login {
IsWriteHeader: true, IsWriteHeader: true,
} }
} }
func CreateLoginModelByDevice(device string) *Login {
return &Login{
Device: device,
IsLastingCookie: true,
Timeout: 60 * 60 * 24 * 30,
JwtData: nil,
Token: "",
IsWriteHeader: true,
}
}

View File

@@ -47,6 +47,17 @@ func NewSession(id string, sessionType string, loginId string) *Session {
} }
} }
func (s *Session) GetFilterTokenSignSlice(device string) []*TokenSign {
l := make([]*TokenSign, 0)
for _, tokenSign := range s.TokenSignList {
if tokenSign.Device == device {
l = append(l, tokenSign)
}
}
return l
}
// GetFilterTokenSign filter by TokenSign.Device from all TokenSign // GetFilterTokenSign filter by TokenSign.Device from all TokenSign
func (s *Session) GetFilterTokenSign(device string) *list.List { func (s *Session) GetFilterTokenSign(device string) *list.List {
copyList := list.New() copyList := list.New()
@@ -111,6 +122,9 @@ func (s *Session) RemoveTokenSignByIndex(i int) {
// GetLastTokenByDevice get TokenSign.Value by device // GetLastTokenByDevice get TokenSign.Value by device
func (s *Session) GetLastTokenByDevice(device string) string { func (s *Session) GetLastTokenByDevice(device string) string {
tokenSignList := s.GetFilterTokenSign(device) tokenSignList := s.GetFilterTokenSign(device)
if tokenSignList.Len() == 0 {
return ""
}
if tokenSign, ok := tokenSignList.Back().Value.(*TokenSign); ok { if tokenSign, ok := tokenSignList.Back().Value.(*TokenSign); ok {
return tokenSign.Value return tokenSign.Value
} }