Skip to content

Commit

Permalink
feat: Force users to change their passwords after 3/6/12 months (casd…
Browse files Browse the repository at this point in the history
…oor#3352)

* feat: Force users to change their passwords after 3/6/12 months

* feat: Check if the password has expired by using the last_change_password_time field added to the user table

* feat: Use the created_time field of the user table to aid password expiration checking

* feat: Rename variable
  • Loading branch information
ljl66-66 authored Nov 19, 2024
1 parent 5960164 commit dff65ee
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 4 deletions.
3 changes: 2 additions & 1 deletion controllers/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -561,8 +561,9 @@ func (c *ApiController) SetPassword() {
targetUser.Password = newPassword
targetUser.UpdateUserPassword(organization)
targetUser.NeedUpdatePassword = false
targetUser.LastChangePasswordTime = util.GetCurrentTime()

_, err = object.UpdateUser(userId, targetUser, []string{"password", "need_update_password", "password_type"}, false)
_, err = object.UpdateUser(userId, targetUser, []string{"password", "need_update_password", "password_type", "last_change_password_time"}, false)
if err != nil {
c.ResponseError(err.Error())
return
Expand Down
6 changes: 6 additions & 0 deletions object/check.go
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,13 @@ func CheckUserPassword(organization string, username string, password string, la
if err != nil {
return nil, err
}

err = checkPasswordExpired(user, lang)
if err != nil {
return nil, err
}
}

return user, nil
}

Expand Down
53 changes: 53 additions & 0 deletions object/check_password_expired.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright 2024 The Casdoor Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package object

import (
"fmt"
"time"

"github.com/casdoor/casdoor/i18n"
"github.com/casdoor/casdoor/util"
)

func checkPasswordExpired(user *User, lang string) error {
organization, err := GetOrganizationByUser(user)
if err != nil {
return err
}
if organization == nil {
return fmt.Errorf(i18n.Translate(lang, "check:Organization does not exist"))
}

passwordExpireDays := organization.PasswordExpireDays
if passwordExpireDays <= 0 {
return nil
}

lastChangePasswordTime := user.LastChangePasswordTime
if lastChangePasswordTime == "" {
if user.CreatedTime == "" {
return fmt.Errorf(i18n.Translate(lang, "check:Your password has expired. Please reset your password by clicking \"Forgot password\""))
}
lastChangePasswordTime = user.CreatedTime
}

lastTime := util.String2Time(lastChangePasswordTime)
expireTime := lastTime.AddDate(0, 0, passwordExpireDays)
if time.Now().After(expireTime) {
return fmt.Errorf(i18n.Translate(lang, "check:Your password has expired. Please reset your password by clicking \"Forgot password\""))
}
return nil
}
7 changes: 4 additions & 3 deletions object/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,9 @@ type User struct {
Permissions []*Permission `json:"permissions"`
Groups []string `xorm:"groups varchar(1000)" json:"groups"`

LastSigninWrongTime string `xorm:"varchar(100)" json:"lastSigninWrongTime"`
SigninWrongTimes int `json:"signinWrongTimes"`
LastChangePasswordTime string `xorm:"varchar(100)" json:"lastChangePasswordTime"`
LastSigninWrongTime string `xorm:"varchar(100)" json:"lastSigninWrongTime"`
SigninWrongTimes int `json:"signinWrongTimes"`

ManagedAccounts []ManagedAccount `xorm:"managedAccounts blob" json:"managedAccounts"`
MfaAccounts []MfaAccount `xorm:"mfaAccounts blob" json:"mfaAccounts"`
Expand Down Expand Up @@ -690,7 +691,7 @@ func UpdateUser(id string, user *User, columns []string, isAdmin bool) (bool, er
"owner", "display_name", "avatar", "first_name", "last_name",
"location", "address", "country_code", "region", "language", "affiliation", "title", "id_card_type", "id_card", "homepage", "bio", "tag", "language", "gender", "birthday", "education", "score", "karma", "ranking", "signup_application",
"is_admin", "is_forbidden", "is_deleted", "hash", "is_default_avatar", "properties", "webauthnCredentials", "managedAccounts", "face_ids", "mfaAccounts",
"signin_wrong_times", "last_signin_wrong_time", "groups", "access_key", "access_secret", "mfa_phone_enabled", "mfa_email_enabled",
"signin_wrong_times", "last_change_password_time", "last_signin_wrong_time", "groups", "access_key", "access_secret", "mfa_phone_enabled", "mfa_email_enabled",
"github", "google", "qq", "wechat", "facebook", "dingtalk", "weibo", "gitee", "linkedin", "wecom", "lark", "gitlab", "adfs",
"baidu", "alipay", "casdoor", "infoflow", "apple", "azuread", "azureadb2c", "slack", "steam", "bilibili", "okta", "douyin", "line", "amazon",
"auth0", "battlenet", "bitbucket", "box", "cloudfoundry", "dailymotion", "deezer", "digitalocean", "discord", "dropbox",
Expand Down
13 changes: 13 additions & 0 deletions web/src/UserEditPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -1009,6 +1009,19 @@ class UserEditPage extends React.Component {
</Col>
</Row>
);
} else if (accountItem.name === "Last change password time") {
return (
<Row style={{marginTop: "20px"}} >
<Col style={{marginTop: "5px"}} span={(Setting.isMobile()) ? 22 : 2}>
{Setting.getLabel(i18next.t("user:Last change password time"), i18next.t("user:Last change password time"))} :
</Col>
<Col span={22}>
<Input value={this.state.user.lastChangePasswordTime} onChange={e => {
this.updateUserField("lastChangePasswordTime", e.target.value);
}} />
</Col>
</Row>
);
} else if (accountItem.name === "Managed accounts") {
return (
<Row style={{marginTop: "20px"}} >
Expand Down

0 comments on commit dff65ee

Please sign in to comment.