mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-10-31 02:38:07 +08:00
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:
@@ -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)
|
||||
|
||||
@@ -25,6 +25,8 @@ type SUserExtended struct {
|
||||
LastActiveAt time.Time
|
||||
DomainId string
|
||||
|
||||
IsSystemAccount bool
|
||||
|
||||
Displayname string
|
||||
Email string
|
||||
Mobile string
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user