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
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)
}
@@ -256,38 +259,37 @@ func (e *Enforcer) LoginByModel(id string, loginModel *model.Login, ctx ctx.Cont
if session = e.GetSession(id); session != nil {
// get by login device
tokenSignList := session.GetFilterTokenSign(device)
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 tokenSign, ok := element.Value.(*model.TokenSign); ok {
if session.TokenSignSize() > int(tokenConfig.DeviceMaxLoginCount) {
// delete tokenSign
tokenSignValue := tokenSign.Value
session.RemoveTokenSign(tokenSignValue)
err = e.UpdateSession(id, session)
if err != nil {
return "", err
}
// delete token-id
err = e.deleteIdByToken(tokenSignValue)
if err != nil {
return "", err
}
e.logger.Logout(e.loginType, id, tokenSignValue)
if tokenSignList.Len() > int(tokenConfig.DeviceMaxLoginCount) {
// if loginCount > maxLoginCount, logout account until single device Login count is equal to DeviceMaxLoginCount
for element := tokenSignList.Front(); element != nil; element = element.Next() {
if tokenSign, ok := element.Value.(*model.TokenSign); ok {
if session.TokenSignSize() > int(tokenConfig.DeviceMaxLoginCount) {
// delete tokenSign
tokenSignValue := tokenSign.Value
session.RemoveTokenSign(tokenSignValue)
err = e.UpdateSession(id, session)
if err != nil {
return "", err
}
// delete token-id
err = e.deleteIdByToken(tokenSignValue)
if err != nil {
return "", err
}
e.logger.Logout(e.loginType, id, tokenSignValue)
if e.watcher != nil {
e.watcher.Logout(e.loginType, id, tokenSignValue)
if e.watcher != nil {
e.watcher.Logout(e.loginType, id, tokenSignValue)
}
}
}
}
}
// check TokenSignList length, if length == 0, delete this session
if session != nil && session.TokenSignSize() == 0 {
err = e.DeleteSession(id)
if err != nil {
return "", err
// check TokenSignList length, if length == 0, delete this session
if session != nil && session.TokenSignSize() == 0 {
err = e.DeleteSession(id)
if err != nil {
return "", err
}
}
}
}
@@ -358,13 +360,20 @@ func (e *Enforcer) Logout(ctx ctx.Context) error {
}
// 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)
if session != nil {
for _, tokenSign := range session.TokenSignList {
err := e.LogoutByToken(tokenSign.Value)
if err != nil {
return err
if len(device) > 0 && device[0] != "" && tokenSign.Device == device[0] {
err := e.LogoutByToken(tokenSign.Value)
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.
// 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
session := e.GetSession(id)
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 {
err = e.CheckLoginByToken(tokenSign.Value)
if err != nil {
@@ -500,8 +514,12 @@ func (e *Enforcer) GetLoginIdByToken(token string) (string, error) {
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 len(device) > 0 && device[0] != "" {
return session.GetFilterTokenSign(device[0]).Len()
}
return session.TokenSignSize()
}
return 0

View File

@@ -26,16 +26,16 @@ type IEnforcer interface {
// Login login api
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)
Logout(ctx ctx.Context) error
LogoutById(id string) error
LogoutById(id string, device ...string) error
LogoutByToken(token string) error
IsLogin(ctx ctx.Context) (bool, error)
IsLoginByToken(token string) (bool, error)
IsLoginById(id string) (bool, error)
IsLoginById(id string, device ...string) (bool, error)
CheckLogin(ctx ctx.Context) error
CheckLoginByToken(token string) error
@@ -43,7 +43,7 @@ type IEnforcer interface {
GetLoginIdByToken(token string) (string, error)
GetId(ctx ctx.Context) string
GetIdByToken(token string) string
GetLoginCount(id string) int
GetLoginCount(id string, device ...string) int
GetLoginCounts() (int, error)
GetLoginTokenCounts() (int, error)

View File

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

View File

@@ -189,6 +189,10 @@ func TestEnforcer_Login(t *testing.T) {
if !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)
if err != nil {
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) {
err, ctx := NewTestHttpContext(t)
if ctx == nil {

View File

@@ -19,3 +19,14 @@ func DefaultLoginModel() *Login {
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
func (s *Session) GetFilterTokenSign(device string) *list.List {
copyList := list.New()
@@ -111,6 +122,9 @@ func (s *Session) RemoveTokenSignByIndex(i int) {
// GetLastTokenByDevice get TokenSign.Value by device
func (s *Session) GetLastTokenByDevice(device string) string {
tokenSignList := s.GetFilterTokenSign(device)
if tokenSignList.Len() == 0 {
return ""
}
if tokenSign, ok := tokenSignList.Back().Value.(*TokenSign); ok {
return tokenSign.Value
}