Skip to content

Commit 8107662

Browse files
committed
combined totp, access tokens, linked accounts and openid into security settings page
1 parent 47faa79 commit 8107662

File tree

14 files changed

+332
-439
lines changed

14 files changed

+332
-439
lines changed

integrations/links_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,8 @@ func testLinksAsUser(userName string, t *testing.T) {
9797
"/user/settings/security",
9898
"/user/settings/security/two_factor/enroll",
9999
"/user/settings/keys",
100-
"/user/settings/applications",
101-
"/user/settings/account_link",
102100
"/user/settings/organization",
101+
"/user/settings/repos",
103102
}
104103

105104
session := loginUser(t, userName)

routers/routes/routes.go

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -225,28 +225,28 @@ func RegisterRoutes(m *macaron.Macaron) {
225225
m.Post("/email/delete", user.DeleteEmail)
226226
m.Post("/delete", user.SettingsDelete)
227227
})
228-
m.Get("/security", user.SettingsSecurity)
229-
m.Group("/openid", func() {
230-
m.Combo("").Get(user.SettingsOpenID).
231-
Post(bindIgnErr(auth.AddOpenIDForm{}), user.SettingsOpenIDPost)
232-
m.Post("/delete", user.DeleteOpenID)
233-
m.Post("/toggle_visibility", user.ToggleOpenIDVisibility)
234-
}, openIDSignInEnabled)
228+
m.Group("/security", func() {
229+
m.Get("", user.SettingsSecurity)
230+
m.Group("/two_factor", func() {
231+
m.Post("/regenerate_scratch", user.SettingsTwoFactorRegenerateScratch)
232+
m.Post("/disable", user.SettingsTwoFactorDisable)
233+
m.Get("/enroll", user.SettingsTwoFactorEnroll)
234+
m.Post("/enroll", bindIgnErr(auth.TwoFactorAuthForm{}), user.SettingsTwoFactorEnrollPost)
235+
})
236+
m.Group("/openid", func() {
237+
m.Post("", bindIgnErr(auth.AddOpenIDForm{}), user.SettingsOpenIDPost)
238+
m.Post("/delete", user.DeleteOpenID)
239+
m.Post("/toggle_visibility", user.ToggleOpenIDVisibility)
240+
}, openIDSignInEnabled)
241+
m.Post("/applications", bindIgnErr(auth.NewAccessTokenForm{}), user.SettingsApplicationsPost)
242+
m.Post("/applications/delete", user.SettingsDeleteApplication)
243+
m.Post("/account_link", user.SettingsDeleteAccountLink)
244+
})
235245
m.Combo("/keys").Get(user.SettingsKeys).
236246
Post(bindIgnErr(auth.AddKeyForm{}), user.SettingsKeysPost)
237247
m.Post("/keys/delete", user.DeleteKey)
238-
m.Combo("/applications").Get(user.SettingsApplications).
239-
Post(bindIgnErr(auth.NewAccessTokenForm{}), user.SettingsApplicationsPost)
240-
m.Post("/applications/delete", user.SettingsDeleteApplication)
241-
m.Combo("/account_link").Get(user.SettingsAccountLinks).Post(user.SettingsDeleteAccountLink)
242248
m.Get("/organization", user.SettingsOrganization)
243249
m.Get("/repos", user.SettingsRepos)
244-
m.Group("/security/two_factor", func() {
245-
m.Post("/regenerate_scratch", user.SettingsTwoFactorRegenerateScratch)
246-
m.Post("/disable", user.SettingsTwoFactorDisable)
247-
m.Get("/enroll", user.SettingsTwoFactorEnroll)
248-
m.Post("/enroll", bindIgnErr(auth.TwoFactorAuthForm{}), user.SettingsTwoFactorEnrollPost)
249-
})
250250
}, reqSignIn, func(ctx *context.Context) {
251251
ctx.Data["PageIsUserSettings"] = true
252252
})

routers/user/setting.go

Lines changed: 101 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,11 @@ import (
3131
const (
3232
tplSettingsProfile base.TplName = "user/settings/profile"
3333
tplSettingsAccount base.TplName = "user/settings/account"
34-
tplSettingsKeys base.TplName = "user/settings/keys"
35-
tplSettingsSocial base.TplName = "user/settings/social"
36-
tplSettingsApplications base.TplName = "user/settings/applications"
37-
tplSettingsTwofa base.TplName = "user/settings/twofa"
34+
tplSettingsSecurity base.TplName = "user/settings/security"
3835
tplSettingsTwofaEnroll base.TplName = "user/settings/twofa_enroll"
39-
tplSettingsAccountLink base.TplName = "user/settings/account_link"
36+
tplSettingsKeys base.TplName = "user/settings/keys"
4037
tplSettingsOrganization base.TplName = "user/settings/organization"
4138
tplSettingsRepositories base.TplName = "user/settings/repos"
42-
tplSettingsSecurity base.TplName = "user/settings/security"
4339
)
4440

4541
// Settings render user's profile page
@@ -356,11 +352,109 @@ func SettingsSecurity(ctx *context.Context) {
356352
return
357353
}
358354
}
359-
360355
ctx.Data["TwofaEnrolled"] = enrolled
356+
357+
tokens, err := models.ListAccessTokens(ctx.User.ID)
358+
if err != nil {
359+
ctx.ServerError("ListAccessTokens", err)
360+
return
361+
}
362+
ctx.Data["Tokens"] = tokens
363+
364+
accountLinks, err := models.ListAccountLinks(ctx.User)
365+
if err != nil {
366+
ctx.ServerError("ListAccountLinks", err)
367+
return
368+
}
369+
370+
// map the provider display name with the LoginSource
371+
sources := make(map[*models.LoginSource]string)
372+
for _, externalAccount := range accountLinks {
373+
if loginSource, err := models.GetLoginSourceByID(externalAccount.LoginSourceID); err == nil {
374+
var providerDisplayName string
375+
if loginSource.IsOAuth2() {
376+
providerTechnicalName := loginSource.OAuth2().Provider
377+
providerDisplayName = models.OAuth2Providers[providerTechnicalName].DisplayName
378+
} else {
379+
providerDisplayName = loginSource.Name
380+
}
381+
sources[loginSource] = providerDisplayName
382+
}
383+
}
384+
ctx.Data["AccountLinks"] = sources
385+
386+
if ctx.Query("openid.return_to") != "" {
387+
settingsOpenIDVerify(ctx)
388+
return
389+
}
390+
391+
openid, err := models.GetUserOpenIDs(ctx.User.ID)
392+
if err != nil {
393+
ctx.ServerError("GetUserOpenIDs", err)
394+
return
395+
}
396+
ctx.Data["OpenIDs"] = openid
397+
361398
ctx.HTML(200, tplSettingsSecurity)
362399
}
363400

401+
// SettingsApplicationsPost response for add user's access token
402+
func SettingsApplicationsPost(ctx *context.Context, form auth.NewAccessTokenForm) {
403+
ctx.Data["Title"] = ctx.Tr("settings")
404+
ctx.Data["PageIsSettingsApplications"] = true
405+
406+
if ctx.HasError() {
407+
tokens, err := models.ListAccessTokens(ctx.User.ID)
408+
if err != nil {
409+
ctx.ServerError("ListAccessTokens", err)
410+
return
411+
}
412+
ctx.Data["Tokens"] = tokens
413+
ctx.HTML(200, tplSettingsSecurity)
414+
return
415+
}
416+
417+
t := &models.AccessToken{
418+
UID: ctx.User.ID,
419+
Name: form.Name,
420+
}
421+
if err := models.NewAccessToken(t); err != nil {
422+
ctx.ServerError("NewAccessToken", err)
423+
return
424+
}
425+
426+
ctx.Flash.Success(ctx.Tr("settings.generate_token_success"))
427+
ctx.Flash.Info(t.Sha1)
428+
429+
ctx.Redirect(setting.AppSubURL + "/user/settings/security")
430+
}
431+
432+
// SettingsDeleteApplication response for delete user access token
433+
func SettingsDeleteApplication(ctx *context.Context) {
434+
if err := models.DeleteAccessTokenByID(ctx.QueryInt64("id"), ctx.User.ID); err != nil {
435+
ctx.Flash.Error("DeleteAccessTokenByID: " + err.Error())
436+
} else {
437+
ctx.Flash.Success(ctx.Tr("settings.delete_token_success"))
438+
}
439+
440+
ctx.JSON(200, map[string]interface{}{
441+
"redirect": setting.AppSubURL + "/user/settings/security",
442+
})
443+
}
444+
445+
// SettingsDeleteAccountLink delete a single account link
446+
func SettingsDeleteAccountLink(ctx *context.Context) {
447+
if _, err := models.RemoveAccountLink(ctx.User, ctx.QueryInt64("loginSourceID")); err != nil {
448+
ctx.Flash.Error("RemoveAccountLink: " + err.Error())
449+
} else {
450+
ctx.Flash.Success(ctx.Tr("settings.remove_account_link_success"))
451+
}
452+
453+
ctx.JSON(200, map[string]interface{}{
454+
"redirect": setting.AppSubURL + "/user/settings/security",
455+
})
456+
}
457+
364458
// SettingsKeys render user's SSH/GPG public keys page
365459
func SettingsKeys(ctx *context.Context) {
366460
ctx.Data["Title"] = ctx.Tr("settings")
@@ -492,65 +586,6 @@ func DeleteKey(ctx *context.Context) {
492586
})
493587
}
494588

495-
// SettingsApplications render user's access tokens page
496-
func SettingsApplications(ctx *context.Context) {
497-
ctx.Data["Title"] = ctx.Tr("settings")
498-
ctx.Data["PageIsSettingsApplications"] = true
499-
500-
tokens, err := models.ListAccessTokens(ctx.User.ID)
501-
if err != nil {
502-
ctx.ServerError("ListAccessTokens", err)
503-
return
504-
}
505-
ctx.Data["Tokens"] = tokens
506-
507-
ctx.HTML(200, tplSettingsApplications)
508-
}
509-
510-
// SettingsApplicationsPost response for add user's access token
511-
func SettingsApplicationsPost(ctx *context.Context, form auth.NewAccessTokenForm) {
512-
ctx.Data["Title"] = ctx.Tr("settings")
513-
ctx.Data["PageIsSettingsApplications"] = true
514-
515-
if ctx.HasError() {
516-
tokens, err := models.ListAccessTokens(ctx.User.ID)
517-
if err != nil {
518-
ctx.ServerError("ListAccessTokens", err)
519-
return
520-
}
521-
ctx.Data["Tokens"] = tokens
522-
ctx.HTML(200, tplSettingsApplications)
523-
return
524-
}
525-
526-
t := &models.AccessToken{
527-
UID: ctx.User.ID,
528-
Name: form.Name,
529-
}
530-
if err := models.NewAccessToken(t); err != nil {
531-
ctx.ServerError("NewAccessToken", err)
532-
return
533-
}
534-
535-
ctx.Flash.Success(ctx.Tr("settings.generate_token_success"))
536-
ctx.Flash.Info(t.Sha1)
537-
538-
ctx.Redirect(setting.AppSubURL + "/user/settings/applications")
539-
}
540-
541-
// SettingsDeleteApplication response for delete user access token
542-
func SettingsDeleteApplication(ctx *context.Context) {
543-
if err := models.DeleteAccessTokenByID(ctx.QueryInt64("id"), ctx.User.ID); err != nil {
544-
ctx.Flash.Error("DeleteAccessTokenByID: " + err.Error())
545-
} else {
546-
ctx.Flash.Success(ctx.Tr("settings.delete_token_success"))
547-
}
548-
549-
ctx.JSON(200, map[string]interface{}{
550-
"redirect": setting.AppSubURL + "/user/settings/applications",
551-
})
552-
}
553-
554589
// SettingsTwoFactorRegenerateScratch regenerates the user's 2FA scratch code.
555590
func SettingsTwoFactorRegenerateScratch(ctx *context.Context) {
556591
ctx.Data["Title"] = ctx.Tr("settings")
@@ -716,49 +751,6 @@ func SettingsTwoFactorEnrollPost(ctx *context.Context, form auth.TwoFactorAuthFo
716751
ctx.Redirect(setting.AppSubURL + "/user/settings/security")
717752
}
718753

719-
// SettingsAccountLinks render the account links settings page
720-
func SettingsAccountLinks(ctx *context.Context) {
721-
ctx.Data["Title"] = ctx.Tr("settings")
722-
ctx.Data["PageIsSettingsAccountLink"] = true
723-
724-
accountLinks, err := models.ListAccountLinks(ctx.User)
725-
if err != nil {
726-
ctx.ServerError("ListAccountLinks", err)
727-
return
728-
}
729-
730-
// map the provider display name with the LoginSource
731-
sources := make(map[*models.LoginSource]string)
732-
for _, externalAccount := range accountLinks {
733-
if loginSource, err := models.GetLoginSourceByID(externalAccount.LoginSourceID); err == nil {
734-
var providerDisplayName string
735-
if loginSource.IsOAuth2() {
736-
providerTechnicalName := loginSource.OAuth2().Provider
737-
providerDisplayName = models.OAuth2Providers[providerTechnicalName].DisplayName
738-
} else {
739-
providerDisplayName = loginSource.Name
740-
}
741-
sources[loginSource] = providerDisplayName
742-
}
743-
}
744-
ctx.Data["AccountLinks"] = sources
745-
746-
ctx.HTML(200, tplSettingsAccountLink)
747-
}
748-
749-
// SettingsDeleteAccountLink delete a single account link
750-
func SettingsDeleteAccountLink(ctx *context.Context) {
751-
if _, err := models.RemoveAccountLink(ctx.User, ctx.QueryInt64("loginSourceID")); err != nil {
752-
ctx.Flash.Error("RemoveAccountLink: " + err.Error())
753-
} else {
754-
ctx.Flash.Success(ctx.Tr("settings.remove_account_link_success"))
755-
}
756-
757-
ctx.JSON(200, map[string]interface{}{
758-
"redirect": setting.AppSubURL + "/user/settings/account_link",
759-
})
760-
}
761-
762754
// SettingsOrganization render all the organization of the user
763755
func SettingsOrganization(ctx *context.Context) {
764756
ctx.Data["Title"] = ctx.Tr("settings")

0 commit comments

Comments
 (0)