Merge pull request #3432 from swordqiu/hotfix/qj-user-add-expire-password-info

fix: user details add password expiration info
This commit is contained in:
yunion-ci-robot
2019-11-04 22:41:13 +08:00
committed by GitHub
6 changed files with 63 additions and 31 deletions
+8 -1
View File
@@ -671,7 +671,14 @@ func getUserInfo(ctx context.Context, s *mcclient.ClientSession, token mcclient.
return nil, fmt.Errorf("not found user %s", token.GetUserId())
}
data := jsonutils.NewDict()
for _, k := range []string{"displayname", "email", "id", "name", "enabled", "mobile", "allow_web_console", "created_at", "enable_mfa", "is_system_account", "last_active_at", "last_login_ip", "last_login_source", "idp_driver"} {
for _, k := range []string{
"displayname", "email", "id", "name",
"enabled", "mobile", "allow_web_console",
"created_at", "enable_mfa", "is_system_account",
"last_active_at", "last_login_ip",
"last_login_source", "idp_driver",
"password_expires_at", "failed_auth_count", "failed_auth_at",
} {
v, e := usr.Get(k)
if e == nil {
data.Add(v, k)
+2
View File
@@ -25,6 +25,8 @@ type SUserExtended struct {
LastActiveAt time.Time
DomainId string
IsSystemAccount bool
Displayname string
Email string
Mobile string
+1 -1
View File
@@ -50,7 +50,7 @@ func (sql *SSQLDriver) Authenticate(ctx context.Context, ident mcclient.SAuthent
if err != nil {
return nil, errors.Wrap(err, "UserManager.FetchUserExtended")
}
localUser, err := models.LocalUserManager.FetchLocalUser(usrExt)
localUser, err := models.LocalUserManager.FetchLocalUserById(usrExt.LocalId)
if err != nil {
return nil, errors.Wrap(err, "LocalUserManager.FetchLocalUser")
}
+27 -20
View File
@@ -19,9 +19,9 @@ import (
"fmt"
"time"
"github.com/pkg/errors"
"yunion.io/x/pkg/errors"
"yunion.io/x/sqlchemy"
api "yunion.io/x/onecloud/pkg/apis/identity"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
)
@@ -75,47 +75,54 @@ func (user *SLocalUser) GetName() string {
return user.Name
}
func (manager *SLocalUserManager) FetchLocalUser(usrExt *api.SUserExtended) (*SLocalUser, error) {
func (manager *SLocalUserManager) FetchLocalUserById(localId int) (*SLocalUser, error) {
return manager.fetchLocalUser("", "", localId)
}
func (manager *SLocalUserManager) fetchLocalUser(userId string, domainId string, localId int) (*SLocalUser, error) {
localUser := SLocalUser{}
localUser.SetModelManager(manager, &localUser)
q := manager.Query().Equals("id", usrExt.LocalId)
var q *sqlchemy.SQuery
if len(userId) > 0 && len(domainId) > 0 {
q = manager.Query().Equals("user_id", userId).Equals("domain_id", domainId)
} else {
q = manager.Query().Equals("id", localId)
}
err := q.First(&localUser)
if err != nil {
return nil, errors.Wrap(err, "Query")
if err == sql.ErrNoRows {
return nil, err
} else {
return nil, errors.Wrap(err, "Query")
}
}
return &localUser, nil
}
func (manager *SLocalUserManager) register(userId string, domainId string, name string) (*SLocalUser, error) {
localUser := SLocalUser{}
localUser.SetModelManager(manager, &localUser)
q := manager.Query().Equals("user_id", userId).Equals("domain_id", domainId)
err := q.First(&localUser)
localUser, err := manager.fetchLocalUser(userId, domainId, 0)
if err != nil && err != sql.ErrNoRows {
return nil, errors.Wrap(err, "Query")
}
if err == nil {
return &localUser, nil
return localUser, nil
}
localUser = &SLocalUser{}
localUser.UserId = userId
localUser.DomainId = domainId
localUser.Name = name
err = manager.TableSpec().Insert(&localUser)
err = manager.TableSpec().Insert(localUser)
if err != nil {
return nil, errors.Wrap(err, "Insert")
}
return &localUser, nil
return localUser, nil
}
func (manager *SLocalUserManager) delete(userId string, domainId string) (*SLocalUser, error) {
localUser := SLocalUser{}
localUser.SetModelManager(manager, &localUser)
q := manager.Query().Equals("user_id", userId).Equals("domain_id", domainId)
err := q.First(&localUser)
localUser, err := manager.fetchLocalUser(userId, domainId, 0)
if err != nil && err != sql.ErrNoRows {
return nil, errors.Wrap(err, "Query")
}
@@ -123,7 +130,7 @@ func (manager *SLocalUserManager) delete(userId string, domainId string) (*SLoca
return nil, nil
}
_, err = db.Update(&localUser, func() error {
_, err = db.Update(localUser, func() error {
return localUser.MarkDelete()
})
@@ -131,7 +138,7 @@ func (manager *SLocalUserManager) delete(userId string, domainId string) (*SLoca
return nil, errors.Wrap(err, "MarkDelete")
}
return &localUser, nil
return localUser, nil
}
func (usr *SLocalUser) SaveFailedAuth() error {
+3 -3
View File
@@ -110,7 +110,7 @@ func (manager *SPasswordManager) fetchByLocaluserId(localUserId int) ([]SPasswor
return passes, nil
}
func (manager *SPasswordManager) verifyPassword(localUserId int, password string) error {
func (manager *SPasswordManager) validatePassword(localUserId int, password string) error {
if o.Options.PasswordMinimalLength > 0 && len(password) < o.Options.PasswordMinimalLength {
return errors.Error("too simple password")
}
@@ -129,7 +129,7 @@ func (manager *SPasswordManager) verifyPassword(localUserId int, password string
return nil
}
func (manager *SPasswordManager) savePassword(localUserId int, password string) error {
func (manager *SPasswordManager) savePassword(localUserId int, password string, isSystemAccount bool) error {
hash, err := seclib2.BcryptPassword(password)
if err != nil {
return errors.Wrap(err, "seclib2.BcryptPassword")
@@ -140,7 +140,7 @@ func (manager *SPasswordManager) savePassword(localUserId int, password string)
rec.Password = shaPassword(password)
now := time.Now()
rec.CreatedAtInt = now.UnixNano() / 1000
if o.Options.PasswordExpirationDays > 0 {
if o.Options.PasswordExpirationDays > 0 && !isSystemAccount {
rec.ExpiresAt = now.Add(24 * time.Hour * time.Duration(o.Options.PasswordExpirationDays))
rec.ExpiresAtInt = rec.ExpiresAt.UnixNano() / 1000
}
+22 -6
View File
@@ -244,6 +244,7 @@ func (manager *SUserManager) FetchUserExtended(userId, userName, domainId, domai
users.Field("created_at"),
users.Field("last_active_at"),
users.Field("domain_id"),
users.Field("is_system_account"),
localUsers.Field("id", "local_id"),
localUsers.Field("name", "local_name"),
domains.Field("name", "domain_name"),
@@ -300,13 +301,15 @@ func localUserVerifyPassword(user *api.SUserExtended, passwd string) error {
if len(passes) == 0 {
return nil
}
//for i := range passes {
// password expiration check skip system account
if !passes[0].ExpiresAt.IsZero() && passes[0].ExpiresAt.Before(time.Now()) && !user.IsSystemAccount {
return errors.Error("password expires")
}
err = seclib2.BcryptVerifyPassword(passwd, passes[0].PasswordHash)
if err == nil {
return nil
}
//}
return fmt.Errorf("invalid password for %s", user.Name)
return errors.Error("invalid password")
}
func (manager *SUserManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*sqlchemy.SQuery, error) {
@@ -421,7 +424,7 @@ func (user *SUser) ValidateUpdateData(ctx context.Context, userCred mcclient.Tok
if err != nil {
return nil, errors.Wrap(err, "UserManager.FetchUserExtended")
}
err = PasswordManager.verifyPassword(usrExt.LocalId, passwd)
err = PasswordManager.validatePassword(usrExt.LocalId, passwd)
if err != nil {
return nil, httperrors.NewInputParameterError("invalid password: %s", err)
}
@@ -483,6 +486,19 @@ func userExtra(user *SUser, extra *jsonutils.JSONDict) *jsonutils.JSONDict {
extra.Add(jsonutils.NewInt(int64(prjCnt)), "project_count")
credCnt, _ := user.GetCredentialCount()
extra.Add(jsonutils.NewInt(int64(credCnt)), "credential_count")
localUser, _ := LocalUserManager.fetchLocalUser(user.Id, user.DomainId, 0)
if localUser != nil {
if localUser.FailedAuthCount > 0 {
extra.Add(jsonutils.NewInt(int64(localUser.FailedAuthCount)), "failed_auth_count")
extra.Add(jsonutils.NewTimeString(localUser.FailedAuthAt), "failed_auth_at")
}
localPass, _ := PasswordManager.FetchLastPassword(localUser.Id)
if localPass != nil && !localPass.ExpiresAt.IsZero() {
extra.Add(jsonutils.NewTimeString(localPass.ExpiresAt), "password_expires_at")
}
}
return extra
}
@@ -492,7 +508,7 @@ func (user *SUser) initLocalData(passwd string) error {
return errors.Wrap(err, "register localuser")
}
if len(passwd) > 0 {
err = PasswordManager.savePassword(localUsr.Id, passwd)
err = PasswordManager.savePassword(localUsr.Id, passwd, user.IsSystemAccount.Bool())
if err != nil {
return errors.Wrap(err, "save password")
}
@@ -521,7 +537,7 @@ func (user *SUser) PostUpdate(ctx context.Context, userCred mcclient.TokenCreden
log.Errorf("UserManager.FetchUserExtended fail %s", err)
return
}
err = PasswordManager.savePassword(usrExt.LocalId, passwd)
err = PasswordManager.savePassword(usrExt.LocalId, passwd, user.IsSystemAccount.Bool())
if err != nil {
log.Errorf("fail to set password %s", err)
return