Skip to content

Commit a64ba42

Browse files
committed
fix AdminEditUserForm
1 parent bf1af92 commit a64ba42

File tree

2 files changed

+93
-48
lines changed

2 files changed

+93
-48
lines changed

routers/web/admin/users.go

Lines changed: 66 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package admin
66

77
import (
8+
"fmt"
89
"net/http"
910
"net/url"
1011
"strconv"
@@ -28,6 +29,11 @@ import (
2829
user_service "code.gitea.io/gitea/services/user"
2930
)
3031

32+
type EditUserForm struct {
33+
*forms.AdminEditUserForm
34+
*forms.AvatarForm
35+
}
36+
3137
const (
3238
tplUsers base.TplName = "admin/user/list"
3339
tplUserNew base.TplName = "admin/user/new"
@@ -207,48 +213,86 @@ func NewUserPost(ctx *context.Context) {
207213
ctx.Redirect(setting.AppSubURL + "/admin/users/" + strconv.FormatInt(u.ID, 10))
208214
}
209215

210-
func prepareUserInfo(ctx *context.Context) *user_model.User {
216+
func prepareUserInfo(ctx *context.Context, adminEditUserForm *forms.AdminEditUserForm, avatarForm *forms.AvatarForm) (*user_model.User, *EditUserForm) {
211217
u, err := user_model.GetUserByID(ctx, ctx.ParamsInt64(":userid"))
212218
if err != nil {
213219
if user_model.IsErrUserNotExist(err) {
214220
ctx.Redirect(setting.AppSubURL + "/admin/users")
215221
} else {
216222
ctx.ServerError("GetUserByID", err)
217223
}
218-
return nil
224+
return nil, nil
219225
}
220226
ctx.Data["User"] = u
221227

228+
var loginSource *auth.Source
222229
if u.LoginSource > 0 {
223-
ctx.Data["LoginSource"], err = auth.GetSourceByID(u.LoginSource)
230+
loginSource, err = auth.GetSourceByID(u.LoginSource)
224231
if err != nil {
225232
ctx.ServerError("auth.GetSourceByID", err)
226-
return nil
233+
return nil, nil
227234
}
228235
} else {
229-
ctx.Data["LoginSource"] = &auth.Source{}
236+
loginSource = &auth.Source{}
230237
}
238+
ctx.Data["LoginSource"] = loginSource
231239

232240
sources, err := auth.Sources()
233241
if err != nil {
234242
ctx.ServerError("auth.Sources", err)
235-
return nil
243+
return nil, nil
236244
}
237245
ctx.Data["Sources"] = sources
238246

239247
hasTOTP, err := auth.HasTwoFactorByUID(u.ID)
240248
if err != nil {
241249
ctx.ServerError("auth.HasTwoFactorByUID", err)
242-
return nil
250+
return nil, nil
243251
}
244252
hasWebAuthn, err := auth.HasWebAuthnRegistrationsByUID(u.ID)
245253
if err != nil {
246254
ctx.ServerError("auth.HasWebAuthnRegistrationsByUID", err)
247-
return nil
255+
return nil, nil
248256
}
249257
ctx.Data["TwoFactorEnabled"] = hasTOTP || hasWebAuthn
250258

251-
return u
259+
var source string
260+
if u.UseCustomAvatar {
261+
source = "local"
262+
} else {
263+
source = "lookup"
264+
}
265+
266+
if adminEditUserForm == nil {
267+
adminEditUserForm = &forms.AdminEditUserForm{
268+
LoginType: fmt.Sprintf("%d-%d", loginSource.Type.Int(), loginSource.ID),
269+
UserName: u.Name,
270+
LoginName: u.LoginName,
271+
FullName: u.FullName,
272+
Email: u.Email,
273+
Website: u.Website,
274+
Location: u.Location,
275+
MaxRepoCreation: u.MaxRepoCreation,
276+
Active: u.IsActive,
277+
Admin: u.IsAdmin,
278+
Restricted: u.IsRestricted,
279+
AllowGitHook: u.CanEditGitHook(),
280+
AllowImportLocal: u.CanImportLocal(),
281+
AllowCreateOrganization: u.CanCreateOrganization(),
282+
ProhibitLogin: u.ProhibitLogin,
283+
Visibility: u.Visibility,
284+
}
285+
}
286+
if avatarForm == nil {
287+
avatarForm = &forms.AvatarForm{
288+
Source: source,
289+
Gravatar: u.AvatarEmail,
290+
}
291+
}
292+
form := &EditUserForm{adminEditUserForm, avatarForm}
293+
ctx.Data["Form"] = form
294+
295+
return u, form
252296
}
253297

254298
// EditUser show editing user page
@@ -260,7 +304,7 @@ func EditUser(ctx *context.Context) {
260304
ctx.Data["DisableMigrations"] = setting.Repository.DisableMigrations
261305
ctx.Data["AllowedUserVisibilityModes"] = setting.Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice()
262306

263-
prepareUserInfo(ctx)
307+
prepareUserInfo(ctx, nil, nil)
264308
if ctx.Written() {
265309
return
266310
}
@@ -277,7 +321,7 @@ func EditUserPost(ctx *context.Context) {
277321
ctx.Data["DisableMigrations"] = setting.Repository.DisableMigrations
278322
ctx.Data["AllowedUserVisibilityModes"] = setting.Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice()
279323

280-
u := prepareUserInfo(ctx)
324+
u, f := prepareUserInfo(ctx, form, nil)
281325
if ctx.Written() {
282326
return
283327
}
@@ -302,11 +346,11 @@ func EditUserPost(ctx *context.Context) {
302346
var err error
303347
if len(form.Password) < setting.MinPasswordLength {
304348
ctx.Data["Err_Password"] = true
305-
ctx.RenderWithErr(ctx.Tr("auth.password_too_short", setting.MinPasswordLength), tplUserEdit, &form)
349+
ctx.RenderWithErr(ctx.Tr("auth.password_too_short", setting.MinPasswordLength), tplUserEdit, &f)
306350
return
307351
}
308352
if !password.IsComplexEnough(form.Password) {
309-
ctx.RenderWithErr(password.BuildComplexityError(ctx), tplUserEdit, &form)
353+
ctx.RenderWithErr(password.BuildComplexityError(ctx), tplUserEdit, &f)
310354
return
311355
}
312356
pwned, err := password.IsPwned(ctx, form.Password)
@@ -317,13 +361,13 @@ func EditUserPost(ctx *context.Context) {
317361
log.Error(err.Error())
318362
errMsg = ctx.Tr("auth.password_pwned_err")
319363
}
320-
ctx.RenderWithErr(errMsg, tplUserEdit, &form)
364+
ctx.RenderWithErr(errMsg, tplUserEdit, &f)
321365
return
322366
}
323367

324368
if err := user_model.ValidateEmail(form.Email); err != nil {
325369
ctx.Data["Err_Email"] = true
326-
ctx.RenderWithErr(ctx.Tr("form.email_error"), tplUserEdit, &form)
370+
ctx.RenderWithErr(ctx.Tr("form.email_error"), tplUserEdit, &f)
327371
return
328372
}
329373

@@ -342,7 +386,7 @@ func EditUserPost(ctx *context.Context) {
342386
if ctx.Written() {
343387
return
344388
}
345-
ctx.RenderWithErr(ctx.Flash.ErrorMsg, tplUserEdit, &form)
389+
ctx.RenderWithErr(ctx.Flash.ErrorMsg, tplUserEdit, &f)
346390
return
347391
}
348392
u.Name = form.UserName
@@ -401,11 +445,11 @@ func EditUserPost(ctx *context.Context) {
401445
if err := user_model.UpdateUser(ctx, u, emailChanged); err != nil {
402446
if user_model.IsErrEmailAlreadyUsed(err) {
403447
ctx.Data["Err_Email"] = true
404-
ctx.RenderWithErr(ctx.Tr("form.email_been_used"), tplUserEdit, &form)
448+
ctx.RenderWithErr(ctx.Tr("form.email_been_used"), tplUserEdit, &f)
405449
} else if user_model.IsErrEmailCharIsNotSupported(err) ||
406450
user_model.IsErrEmailInvalid(err) {
407451
ctx.Data["Err_Email"] = true
408-
ctx.RenderWithErr(ctx.Tr("form.email_invalid"), tplUserEdit, &form)
452+
ctx.RenderWithErr(ctx.Tr("form.email_invalid"), tplUserEdit, &f)
409453
} else {
410454
ctx.ServerError("UpdateUser", err)
411455
}
@@ -456,12 +500,13 @@ func DeleteUser(ctx *context.Context) {
456500

457501
// AvatarPost response for change user's avatar request
458502
func AvatarPost(ctx *context.Context) {
459-
u := prepareUserInfo(ctx)
503+
form := web.GetForm(ctx).(*forms.AvatarForm)
504+
505+
u, _ := prepareUserInfo(ctx, nil, form)
460506
if ctx.Written() {
461507
return
462508
}
463509

464-
form := web.GetForm(ctx).(*forms.AvatarForm)
465510
if err := user_setting.UpdateAvatarSetting(ctx, form, u); err != nil {
466511
ctx.Flash.Error(err.Error())
467512
} else {
@@ -473,7 +518,7 @@ func AvatarPost(ctx *context.Context) {
473518

474519
// DeleteAvatar render delete avatar page
475520
func DeleteAvatar(ctx *context.Context) {
476-
u := prepareUserInfo(ctx)
521+
u, _ := prepareUserInfo(ctx, nil, nil)
477522
if ctx.Written() {
478523
return
479524
}

templates/admin/user/edit.tmpl

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@
1212
{{.CsrfTokenHtml}}
1313
<div class="field {{if .Err_UserName}}error{{end}}">
1414
<label for="user_name">{{.locale.Tr "username"}}</label>
15-
<input id="user_name" name="user_name" value="{{.User.Name}}" autofocus {{if not .User.IsLocal}}disabled{{end}}>
15+
<input id="user_name" name="user_name" value="{{.Form.UserName}}" autofocus {{if not .User.IsLocal}}disabled{{end}}>
1616
</div>
1717
<!-- Types and name -->
1818
<div class="inline required field {{if .Err_LoginType}}error{{end}}">
1919
<label>{{.locale.Tr "admin.users.auth_source"}}</label>
2020
<div class="ui selection type dropdown">
21-
<input type="hidden" id="login_type" name="login_type" value="{{.LoginSource.Type.Int}}-{{.LoginSource.ID}}" required>
21+
<input type="hidden" id="login_type" name="login_type" value="{{.Form.LoginType}}" required>
2222
<div class="text">{{.locale.Tr "admin.users.local"}}</div>
2323
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
2424
<div class="menu">
@@ -33,13 +33,13 @@
3333
<div class="inline field {{if .Err_Visibility}}error{{end}}">
3434
<span class="inline required field"><label for="visibility">{{.locale.Tr "settings.visibility"}}</label></span>
3535
<div class="ui selection type dropdown">
36-
{{if .User.Visibility.IsPublic}}<input type="hidden" id="visibility" name="visibility" value="0">{{end}}
37-
{{if .User.Visibility.IsLimited}}<input type="hidden" id="visibility" name="visibility" value="1">{{end}}
38-
{{if .User.Visibility.IsPrivate}}<input type="hidden" id="visibility" name="visibility" value="2">{{end}}
36+
{{if .Form.Visibility.IsPublic}}<input type="hidden" id="visibility" name="visibility" value="0">{{end}}
37+
{{if .Form.Visibility.IsLimited}}<input type="hidden" id="visibility" name="visibility" value="1">{{end}}
38+
{{if .Form.Visibility.IsPrivate}}<input type="hidden" id="visibility" name="visibility" value="2">{{end}}
3939
<div class="text">
40-
{{if .User.Visibility.IsPublic}}{{.locale.Tr "settings.visibility.public"}}{{end}}
41-
{{if .User.Visibility.IsLimited}}{{.locale.Tr "settings.visibility.limited"}}{{end}}
42-
{{if .User.Visibility.IsPrivate}}{{.locale.Tr "settings.visibility.private"}}{{end}}
40+
{{if .Form.Visibility.IsPublic}}{{.locale.Tr "settings.visibility.public"}}{{end}}
41+
{{if .Form.Visibility.IsLimited}}{{.locale.Tr "settings.visibility.limited"}}{{end}}
42+
{{if .Form.Visibility.IsPrivate}}{{.locale.Tr "settings.visibility.private"}}{{end}}
4343
</div>
4444
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
4545
<div class="menu">
@@ -58,35 +58,35 @@
5858

5959
<div class="required non-local field {{if .Err_LoginName}}error{{end}} {{if eq .User.LoginSource 0}}gt-hidden{{end}}">
6060
<label for="login_name">{{.locale.Tr "admin.users.auth_login_name"}}</label>
61-
<input id="login_name" name="login_name" value="{{.User.LoginName}}" autofocus>
61+
<input id="login_name" name="login_name" value="{{.Form.LoginName}}" autofocus>
6262
</div>
6363
<div class="field {{if .Err_FullName}}error{{end}}">
6464
<label for="full_name">{{.locale.Tr "settings.full_name"}}</label>
65-
<input id="full_name" name="full_name" value="{{.User.FullName}}">
65+
<input id="full_name" name="full_name" value="{{.Form.FullName}}">
6666
</div>
6767
<div class="required field {{if .Err_Email}}error{{end}}">
6868
<label for="email">{{.locale.Tr "email"}}</label>
69-
<input id="email" name="email" type="email" value="{{.User.Email}}" autofocus required>
69+
<input id="email" name="email" type="email" value="{{.Form.Email}}" autofocus required>
7070
</div>
7171
<div class="local field {{if .Err_Password}}error{{end}} {{if not (or (.User.IsLocal) (.User.IsOAuth2))}}gt-hidden{{end}}">
7272
<label for="password">{{.locale.Tr "password"}}</label>
73-
<input id="password" name="password" type="password" autocomplete="new-password">
73+
<input id="password" name="password" type="password" autocomplete="new-password" value="{{.Form.Password}}">
7474
<p class="help">{{.locale.Tr "admin.users.password_helper"}}</p>
7575
</div>
7676
<div class="field {{if .Err_Website}}error{{end}}">
7777
<label for="website">{{.locale.Tr "settings.website"}}</label>
78-
<input id="website" name="website" type="url" value="{{.User.Website}}" placeholder="e.g. http://mydomain.com or https://mydomain.com">
78+
<input id="website" name="website" type="url" value="{{.Form.Website}}" placeholder="e.g. http://mydomain.com or https://mydomain.com">
7979
</div>
8080
<div class="field {{if .Err_Location}}error{{end}}">
8181
<label for="location">{{.locale.Tr "settings.location"}}</label>
82-
<input id="location" name="location" value="{{.User.Location}}">
82+
<input id="location" name="location" value="{{.Form.Location}}">
8383
</div>
8484

8585
<div class="ui divider"></div>
8686

8787
<div class="inline field {{if .Err_MaxRepoCreation}}error{{end}}">
8888
<label for="max_repo_creation">{{.locale.Tr "admin.users.max_repo_creation"}}</label>
89-
<input id="max_repo_creation" name="max_repo_creation" type="number" value="{{.User.MaxRepoCreation}}">
89+
<input id="max_repo_creation" name="max_repo_creation" type="number" value="{{.Form.MaxRepoCreation}}">
9090
<p class="help">{{.locale.Tr "admin.users.max_repo_creation_desc"}}</p>
9191
</div>
9292

@@ -95,44 +95,44 @@
9595
<div class="inline field">
9696
<div class="ui checkbox">
9797
<label><strong>{{.locale.Tr "admin.users.is_activated"}}</strong></label>
98-
<input name="active" type="checkbox" {{if .User.IsActive}}checked{{end}}>
98+
<input name="active" type="checkbox" {{if .Form.Active}}checked{{end}}>
9999
</div>
100100
</div>
101101
<div class="inline field">
102102
<div class="ui checkbox">
103103
<label><strong>{{.locale.Tr "admin.users.prohibit_login"}}</strong></label>
104-
<input name="prohibit_login" type="checkbox" {{if .User.ProhibitLogin}}checked{{end}} {{if (eq .User.ID .SignedUserID)}}disabled{{end}}>
104+
<input name="prohibit_login" type="checkbox" {{if .Form.ProhibitLogin}}checked{{end}} {{if (eq .User.ID .SignedUserID)}}disabled{{end}}>
105105
</div>
106106
</div>
107107
<div class="inline field">
108108
<div class="ui checkbox">
109109
<label><strong>{{.locale.Tr "admin.users.is_admin"}}</strong></label>
110-
<input name="admin" type="checkbox" {{if .User.IsAdmin}}checked{{end}}>
110+
<input name="admin" type="checkbox" {{if .Form.Admin}}checked{{end}}>
111111
</div>
112112
</div>
113113
<div class="inline field">
114114
<div class="ui checkbox">
115115
<label><strong>{{.locale.Tr "admin.users.is_restricted"}}</strong></label>
116-
<input name="restricted" type="checkbox" {{if .User.IsRestricted}}checked{{end}}>
116+
<input name="restricted" type="checkbox" {{if .Form.Restricted}}checked{{end}}>
117117
</div>
118118
</div>
119119
<div class="inline field {{if DisableGitHooks}}gt-hidden{{end}}">
120120
<div class="ui checkbox" data-tooltip-content="{{.locale.Tr "admin.users.allow_git_hook_tooltip"}}">
121121
<label><strong>{{.locale.Tr "admin.users.allow_git_hook"}}</strong></label>
122-
<input name="allow_git_hook" type="checkbox" {{if .User.CanEditGitHook}}checked{{end}} {{if DisableGitHooks}}disabled{{end}}>
122+
<input name="allow_git_hook" type="checkbox" {{if .Form.AllowGitHook}}checked{{end}} {{if DisableGitHooks}}disabled{{end}}>
123123
</div>
124124
</div>
125125
<div class="inline field {{if or (DisableImportLocal) (.DisableMigrations)}}gt-hidden{{end}}">
126126
<div class="ui checkbox">
127127
<label><strong>{{.locale.Tr "admin.users.allow_import_local"}}</strong></label>
128-
<input name="allow_import_local" type="checkbox" {{if .User.CanImportLocal}}checked{{end}} {{if DisableImportLocal}}disabled{{end}}>
128+
<input name="allow_import_local" type="checkbox" {{if .Form.AllowImportLocal}}checked{{end}} {{if DisableImportLocal}}disabled{{end}}>
129129
</div>
130130
</div>
131131
{{if not .DisableRegularOrgCreation}}
132132
<div class="inline field">
133133
<div class="ui checkbox">
134134
<label><strong>{{.locale.Tr "admin.users.allow_create_organization"}}</strong></label>
135-
<input name="allow_create_organization" type="checkbox" {{if .User.CanCreateOrganization}}checked{{end}}>
135+
<input name="allow_create_organization" type="checkbox" {{if .Form.AllowCreateOrganization}}checked{{end}}>
136136
</div>
137137
</div>
138138
{{end}}
@@ -142,7 +142,7 @@
142142
<div class="inline field">
143143
<div class="ui checkbox">
144144
<label><strong>{{.locale.Tr "admin.users.reset_2fa"}}</strong></label>
145-
<input name="reset_2fa" type="checkbox">
145+
<input name="reset_2fa" type="checkbox" {{if .Form.Reset2FA}}checked{{end}}>
146146
</div>
147147
</div>
148148
{{end}}
@@ -165,26 +165,26 @@
165165
{{if not (DisableGravatar $.Context)}}
166166
<div class="inline field">
167167
<div class="ui radio checkbox">
168-
<input name="source" value="lookup" type="radio" {{if not .User.UseCustomAvatar}}checked{{end}}>
168+
<input name="source" value="lookup" type="radio" {{if eq .Form.Source "lookup"}}checked{{end}}>
169169
<label>{{.locale.Tr "settings.lookup_avatar_by_mail"}}</label>
170170
</div>
171171
</div>
172172
<div class="field {{if .Err_Gravatar}}error{{end}}">
173173
<label for="gravatar">Avatar {{.locale.Tr "email"}}</label>
174-
<input id="gravatar" name="gravatar" value="{{.User.AvatarEmail}}">
174+
<input id="gravatar" name="gravatar" value="{{.Form.Gravatar}}">
175175
</div>
176176
{{end}}
177177

178178
<div class="inline field">
179179
<div class="ui radio checkbox">
180-
<input name="source" value="local" type="radio" {{if .User.UseCustomAvatar}}checked{{end}}>
180+
<input name="source" value="local" type="radio" {{if eq .Form.Source "local"}}checked{{end}}>
181181
<label>{{.locale.Tr "settings.enable_custom_avatar"}}</label>
182182
</div>
183183
</div>
184184

185185
<div class="inline field">
186186
<label for="avatar">{{.locale.Tr "settings.choose_new_avatar"}}</label>
187-
<input name="avatar" type="file" >
187+
<input name="avatar" type="file" value="{{.Form.Avatar}}">
188188
</div>
189189

190190
<div class="field">

0 commit comments

Comments
 (0)