Skip to content

Commit 23acb29

Browse files
committed
force users to change password if account was created by an admin
1 parent 68d57a1 commit 23acb29

File tree

4 files changed

+107
-21
lines changed

4 files changed

+107
-21
lines changed

models/user.go

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"errors"
1515
"fmt"
1616
"image"
17+
1718
// Needed for jpeg support
1819
_ "image/jpeg"
1920
"image/png"
@@ -83,18 +84,23 @@ type User struct {
8384
Email string `xorm:"NOT NULL"`
8485
KeepEmailPrivate bool
8586
Passwd string `xorm:"NOT NULL"`
86-
LoginType LoginType
87-
LoginSource int64 `xorm:"NOT NULL DEFAULT 0"`
88-
LoginName string
89-
Type UserType
90-
OwnedOrgs []*User `xorm:"-"`
91-
Orgs []*User `xorm:"-"`
92-
Repos []*Repository `xorm:"-"`
93-
Location string
94-
Website string
95-
Rands string `xorm:"VARCHAR(10)"`
96-
Salt string `xorm:"VARCHAR(10)"`
97-
Language string `xorm:"VARCHAR(5)"`
87+
88+
// MustChangePassword is an attribute that determines if a user
89+
// is to change his/her password after registration.
90+
MustChangePassword bool `xorm:"NOT NULL DEFAULT false"`
91+
92+
LoginType LoginType
93+
LoginSource int64 `xorm:"NOT NULL DEFAULT 0"`
94+
LoginName string
95+
Type UserType
96+
OwnedOrgs []*User `xorm:"-"`
97+
Orgs []*User `xorm:"-"`
98+
Repos []*Repository `xorm:"-"`
99+
Location string
100+
Website string
101+
Rands string `xorm:"VARCHAR(10)"`
102+
Salt string `xorm:"VARCHAR(10)"`
103+
Language string `xorm:"VARCHAR(5)"`
98104

99105
CreatedUnix util.TimeStamp `xorm:"INDEX created"`
100106
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"`

modules/context/auth.go

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,22 @@ func Toggle(options *ToggleOptions) macaron.Handler {
3131
}
3232

3333
// Check prohibit login users.
34-
if ctx.IsSigned && ctx.User.ProhibitLogin {
35-
ctx.Data["Title"] = ctx.Tr("auth.prohibit_login")
36-
ctx.HTML(200, "user/auth/prohibit_login")
37-
return
34+
if ctx.IsSigned {
35+
36+
if ctx.User.ProhibitLogin {
37+
ctx.Data["Title"] = ctx.Tr("auth.prohibit_login")
38+
ctx.HTML(200, "user/auth/prohibit_login")
39+
return
40+
}
41+
42+
if ctx.Req.URL.Path == "/user/change_password" {
43+
return
44+
} else if ctx.User.MustChangePassword {
45+
ctx.Data["Title"] = ctx.Tr("auth.must_change_password")
46+
ctx.Data["ChangePasscodeLink"] = setting.AppSubURL + "/user/change_password"
47+
ctx.Redirect(setting.AppSubURL + "/user/change_password")
48+
return
49+
}
3850
}
3951

4052
// Redirect to dashboard if user tries to visit any non-login page.

routers/admin/users.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,12 @@ func NewUserPost(ctx *context.Context, form auth.AdminCreateUserForm) {
7777
}
7878

7979
u := &models.User{
80-
Name: form.UserName,
81-
Email: form.Email,
82-
Passwd: form.Password,
83-
IsActive: true,
84-
LoginType: models.LoginPlain,
80+
Name: form.UserName,
81+
Email: form.Email,
82+
Passwd: form.Password,
83+
IsActive: true,
84+
LoginType: models.LoginPlain,
85+
MustChangePassword: false,
8586
}
8687

8788
if len(form.LoginType) > 0 {

routers/user/auth.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
)
2929

3030
const (
31+
tplMustChangePassword = "user/auth/change_passwd"
3132
// tplSignIn template for sign in page
3233
tplSignIn base.TplName = "user/auth/signin"
3334
// tplSignUp template path for sign up page
@@ -1185,3 +1186,69 @@ func ResetPasswdPost(ctx *context.Context) {
11851186
ctx.Data["IsResetFailed"] = true
11861187
ctx.HTML(200, tplResetPassword)
11871188
}
1189+
1190+
// MustChangePassword renders the page to change a user's password
1191+
func MustChangePassword(ctx *context.Context) {
1192+
ctx.Data["Title"] = ctx.Tr("auth.must_change_password")
1193+
ctx.Data["ChangePasscodeLink"] = setting.AppSubURL + "/user/change_password"
1194+
1195+
ctx.HTML(200, tplMustChangePassword)
1196+
}
1197+
1198+
// MustChangePasswordPost response for updating a user's password after his/her
1199+
// account was created by an admin
1200+
func MustChangePasswordPost(ctx *context.Context, cpt *captcha.Captcha, form auth.MustChangePasswordForm) {
1201+
ctx.Data["Title"] = ctx.Tr("auth.must_change_password")
1202+
1203+
ctx.Data["ChangePasscodeLink"] = setting.AppSubURL + "/user/sign_up"
1204+
1205+
if ctx.HasError() {
1206+
ctx.HTML(200, tplMustChangePassword)
1207+
return
1208+
}
1209+
1210+
u := ctx.User
1211+
1212+
// Make sure only requests for users who are eligible to change their password via
1213+
// this method passes through
1214+
if !u.MustChangePassword {
1215+
ctx.ServerError("MustUpdatePassword", errors.New("cannot update password.. Please visit the settings page"))
1216+
return
1217+
}
1218+
1219+
if form.Password != form.Retype {
1220+
ctx.Data["Err_Password"] = true
1221+
ctx.RenderWithErr(ctx.Tr("form.password_not_match"), tplMustChangePassword, &form)
1222+
return
1223+
}
1224+
1225+
if len(form.Password) < setting.MinPasswordLength {
1226+
ctx.Data["Err_Password"] = true
1227+
ctx.RenderWithErr(ctx.Tr("auth.password_too_short", setting.MinPasswordLength), tplMustChangePassword, &form)
1228+
return
1229+
}
1230+
1231+
var err error
1232+
if u.Rands, err = models.GetUserSalt(); err != nil {
1233+
ctx.ServerError("UpdateUser", err)
1234+
return
1235+
}
1236+
1237+
if u.Salt, err = models.GetUserSalt(); err != nil {
1238+
ctx.ServerError("UpdateUser", err)
1239+
return
1240+
}
1241+
1242+
u.HashPassword(form.Password)
1243+
u.MustChangePassword = false
1244+
1245+
if err := models.UpdateUserCols(u, "must_change_password", "passwd", "rands", "salt"); err != nil {
1246+
ctx.ServerError("UpdateUser", err)
1247+
return
1248+
}
1249+
1250+
ctx.Flash.Success(ctx.Tr("settings.change_password_success"))
1251+
1252+
log.Trace("User updated password: %s", u.Name)
1253+
ctx.Redirect(setting.AppSubURL + "/")
1254+
}

0 commit comments

Comments
 (0)