Refactor User Settings (#3900)
* moved avatar to profile page * combined password change, email and account deletion into account settings page * combined totp, access tokens, linked accounts and openid into security settings page * move access tokens to applications settings page * small change to restart drone build * fix change avatar url on profile page * redirect old settings urls to new ones * enforce only one autofocus attribute on settings pages * set correct redirect status code * fmt fix
This commit is contained in:
parent
1546458f7d
commit
099372d76c
25 changed files with 582 additions and 688 deletions
|
@ -37,6 +37,7 @@ import (
|
|||
"github.com/go-macaron/session"
|
||||
"github.com/go-macaron/toolbox"
|
||||
"gopkg.in/macaron.v1"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// NewMacaron initializes Macaron instance.
|
||||
|
@ -217,35 +218,54 @@ func RegisterRoutes(m *macaron.Macaron) {
|
|||
m.Group("/user/settings", func() {
|
||||
m.Get("", user.Settings)
|
||||
m.Post("", bindIgnErr(auth.UpdateProfileForm{}), user.SettingsPost)
|
||||
m.Combo("/avatar").Get(user.SettingsAvatar).
|
||||
Post(binding.MultipartForm(auth.AvatarForm{}), user.SettingsAvatarPost)
|
||||
m.Post("/avatar", binding.MultipartForm(auth.AvatarForm{}), user.SettingsAvatarPost)
|
||||
m.Post("/avatar/delete", user.SettingsDeleteAvatar)
|
||||
m.Combo("/email").Get(user.SettingsEmails).
|
||||
Post(bindIgnErr(auth.AddEmailForm{}), user.SettingsEmailPost)
|
||||
m.Post("/email/delete", user.DeleteEmail)
|
||||
m.Get("/security", user.SettingsSecurity)
|
||||
m.Post("/security", bindIgnErr(auth.ChangePasswordForm{}), user.SettingsSecurityPost)
|
||||
m.Group("/openid", func() {
|
||||
m.Combo("").Get(user.SettingsOpenID).
|
||||
Post(bindIgnErr(auth.AddOpenIDForm{}), user.SettingsOpenIDPost)
|
||||
m.Post("/delete", user.DeleteOpenID)
|
||||
m.Post("/toggle_visibility", user.ToggleOpenIDVisibility)
|
||||
}, openIDSignInEnabled)
|
||||
m.Combo("/keys").Get(user.SettingsKeys).
|
||||
Post(bindIgnErr(auth.AddKeyForm{}), user.SettingsKeysPost)
|
||||
m.Post("/keys/delete", user.DeleteKey)
|
||||
m.Group("/account", func() {
|
||||
m.Combo("").Get(user.SettingsAccount).Post(bindIgnErr(auth.ChangePasswordForm{}), user.SettingsAccountPost)
|
||||
m.Post("/email", bindIgnErr(auth.AddEmailForm{}), user.SettingsEmailPost)
|
||||
m.Post("/email/delete", user.DeleteEmail)
|
||||
m.Post("/delete", user.SettingsDelete)
|
||||
})
|
||||
m.Group("/security", func() {
|
||||
m.Get("", user.SettingsSecurity)
|
||||
m.Group("/two_factor", func() {
|
||||
m.Post("/regenerate_scratch", user.SettingsTwoFactorRegenerateScratch)
|
||||
m.Post("/disable", user.SettingsTwoFactorDisable)
|
||||
m.Get("/enroll", user.SettingsTwoFactorEnroll)
|
||||
m.Post("/enroll", bindIgnErr(auth.TwoFactorAuthForm{}), user.SettingsTwoFactorEnrollPost)
|
||||
})
|
||||
m.Group("/openid", func() {
|
||||
m.Post("", bindIgnErr(auth.AddOpenIDForm{}), user.SettingsOpenIDPost)
|
||||
m.Post("/delete", user.DeleteOpenID)
|
||||
m.Post("/toggle_visibility", user.ToggleOpenIDVisibility)
|
||||
}, openIDSignInEnabled)
|
||||
m.Post("/account_link", user.SettingsDeleteAccountLink)
|
||||
})
|
||||
m.Combo("/applications").Get(user.SettingsApplications).
|
||||
Post(bindIgnErr(auth.NewAccessTokenForm{}), user.SettingsApplicationsPost)
|
||||
m.Post("/applications/delete", user.SettingsDeleteApplication)
|
||||
m.Route("/delete", "GET,POST", user.SettingsDelete)
|
||||
m.Combo("/account_link").Get(user.SettingsAccountLinks).Post(user.SettingsDeleteAccountLink)
|
||||
m.Combo("/keys").Get(user.SettingsKeys).
|
||||
Post(bindIgnErr(auth.AddKeyForm{}), user.SettingsKeysPost)
|
||||
m.Post("/keys/delete", user.DeleteKey)
|
||||
m.Get("/organization", user.SettingsOrganization)
|
||||
m.Get("/repos", user.SettingsRepos)
|
||||
m.Group("/security/two_factor", func() {
|
||||
m.Post("/regenerate_scratch", user.SettingsTwoFactorRegenerateScratch)
|
||||
m.Post("/disable", user.SettingsTwoFactorDisable)
|
||||
m.Get("/enroll", user.SettingsTwoFactorEnroll)
|
||||
m.Post("/enroll", bindIgnErr(auth.TwoFactorAuthForm{}), user.SettingsTwoFactorEnrollPost)
|
||||
|
||||
// redirects from old settings urls to new ones
|
||||
// TODO: can be removed on next major version
|
||||
m.Get("/avatar", func(ctx *context.Context) {
|
||||
ctx.Redirect(setting.AppSubURL+"/user/settings", http.StatusMovedPermanently)
|
||||
})
|
||||
m.Get("/email", func(ctx *context.Context) {
|
||||
ctx.Redirect(setting.AppSubURL+"/user/settings/account", http.StatusMovedPermanently)
|
||||
})
|
||||
m.Get("/delete", func(ctx *context.Context) {
|
||||
ctx.Redirect(setting.AppSubURL+"/user/settings/account", http.StatusMovedPermanently)
|
||||
})
|
||||
m.Get("/openid", func(ctx *context.Context) {
|
||||
ctx.Redirect(setting.AppSubURL+"/user/settings/security", http.StatusMovedPermanently)
|
||||
})
|
||||
m.Get("/account_link", func(ctx *context.Context) {
|
||||
ctx.Redirect(setting.AppSubURL+"/user/settings/security", http.StatusMovedPermanently)
|
||||
})
|
||||
}, reqSignIn, func(ctx *context.Context) {
|
||||
ctx.Data["PageIsUserSettings"] = true
|
||||
|
|
|
@ -30,18 +30,13 @@ import (
|
|||
|
||||
const (
|
||||
tplSettingsProfile base.TplName = "user/settings/profile"
|
||||
tplSettingsAvatar base.TplName = "user/settings/avatar"
|
||||
tplSettingsEmails base.TplName = "user/settings/email"
|
||||
tplSettingsKeys base.TplName = "user/settings/keys"
|
||||
tplSettingsSocial base.TplName = "user/settings/social"
|
||||
tplSettingsApplications base.TplName = "user/settings/applications"
|
||||
tplSettingsTwofa base.TplName = "user/settings/twofa"
|
||||
tplSettingsAccount base.TplName = "user/settings/account"
|
||||
tplSettingsSecurity base.TplName = "user/settings/security"
|
||||
tplSettingsTwofaEnroll base.TplName = "user/settings/twofa_enroll"
|
||||
tplSettingsAccountLink base.TplName = "user/settings/account_link"
|
||||
tplSettingsApplications base.TplName = "user/settings/applications"
|
||||
tplSettingsKeys base.TplName = "user/settings/keys"
|
||||
tplSettingsOrganization base.TplName = "user/settings/organization"
|
||||
tplSettingsRepositories base.TplName = "user/settings/repos"
|
||||
tplSettingsDelete base.TplName = "user/settings/delete"
|
||||
tplSettingsSecurity base.TplName = "user/settings/security"
|
||||
)
|
||||
|
||||
// Settings render user's profile page
|
||||
|
@ -168,13 +163,6 @@ func UpdateAvatarSetting(ctx *context.Context, form auth.AvatarForm, ctxUser *mo
|
|||
return nil
|
||||
}
|
||||
|
||||
// SettingsAvatar render user avatar page
|
||||
func SettingsAvatar(ctx *context.Context) {
|
||||
ctx.Data["Title"] = ctx.Tr("settings")
|
||||
ctx.Data["PageIsSettingsAvatar"] = true
|
||||
ctx.HTML(200, tplSettingsAvatar)
|
||||
}
|
||||
|
||||
// SettingsAvatarPost response for change user's avatar request
|
||||
func SettingsAvatarPost(ctx *context.Context, form auth.AvatarForm) {
|
||||
if err := UpdateAvatarSetting(ctx, form, ctx.User); err != nil {
|
||||
|
@ -183,7 +171,7 @@ func SettingsAvatarPost(ctx *context.Context, form auth.AvatarForm) {
|
|||
ctx.Flash.Success(ctx.Tr("settings.update_avatar_success"))
|
||||
}
|
||||
|
||||
ctx.Redirect(setting.AppSubURL + "/user/settings/avatar")
|
||||
ctx.Redirect(setting.AppSubURL + "/user/settings")
|
||||
}
|
||||
|
||||
// SettingsDeleteAvatar render delete avatar page
|
||||
|
@ -192,38 +180,32 @@ func SettingsDeleteAvatar(ctx *context.Context) {
|
|||
ctx.Flash.Error(err.Error())
|
||||
}
|
||||
|
||||
ctx.Redirect(setting.AppSubURL + "/user/settings/avatar")
|
||||
ctx.Redirect(setting.AppSubURL + "/user/settings")
|
||||
}
|
||||
|
||||
// SettingsSecurity render change user's password page and 2FA
|
||||
func SettingsSecurity(ctx *context.Context) {
|
||||
// SettingsAccount renders change user's password, user's email and user suicide page
|
||||
func SettingsAccount(ctx *context.Context) {
|
||||
ctx.Data["Title"] = ctx.Tr("settings")
|
||||
ctx.Data["PageIsSettingsSecurity"] = true
|
||||
ctx.Data["PageIsSettingsAccount"] = true
|
||||
ctx.Data["Email"] = ctx.User.Email
|
||||
|
||||
enrolled := true
|
||||
_, err := models.GetTwoFactorByUID(ctx.User.ID)
|
||||
emails, err := models.GetEmailAddresses(ctx.User.ID)
|
||||
if err != nil {
|
||||
if models.IsErrTwoFactorNotEnrolled(err) {
|
||||
enrolled = false
|
||||
} else {
|
||||
ctx.ServerError("SettingsTwoFactor", err)
|
||||
return
|
||||
}
|
||||
ctx.ServerError("GetEmailAddresses", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["Emails"] = emails
|
||||
|
||||
ctx.Data["TwofaEnrolled"] = enrolled
|
||||
ctx.HTML(200, tplSettingsSecurity)
|
||||
ctx.HTML(200, tplSettingsAccount)
|
||||
}
|
||||
|
||||
// SettingsSecurityPost response for change user's password
|
||||
func SettingsSecurityPost(ctx *context.Context, form auth.ChangePasswordForm) {
|
||||
// SettingsAccountPost response for change user's password
|
||||
func SettingsAccountPost(ctx *context.Context, form auth.ChangePasswordForm) {
|
||||
ctx.Data["Title"] = ctx.Tr("settings")
|
||||
ctx.Data["PageIsSettingsSecurity"] = true
|
||||
ctx.Data["PageIsSettingsDelete"] = true
|
||||
ctx.Data["PageIsSettingsAccount"] = true
|
||||
|
||||
if ctx.HasError() {
|
||||
ctx.HTML(200, tplSettingsSecurity)
|
||||
ctx.HTML(200, tplSettingsAccount)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -248,28 +230,13 @@ func SettingsSecurityPost(ctx *context.Context, form auth.ChangePasswordForm) {
|
|||
ctx.Flash.Success(ctx.Tr("settings.change_password_success"))
|
||||
}
|
||||
|
||||
ctx.Redirect(setting.AppSubURL + "/user/settings/security")
|
||||
}
|
||||
|
||||
// SettingsEmails render user's emails page
|
||||
func SettingsEmails(ctx *context.Context) {
|
||||
ctx.Data["Title"] = ctx.Tr("settings")
|
||||
ctx.Data["PageIsSettingsEmails"] = true
|
||||
|
||||
emails, err := models.GetEmailAddresses(ctx.User.ID)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetEmailAddresses", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["Emails"] = emails
|
||||
|
||||
ctx.HTML(200, tplSettingsEmails)
|
||||
ctx.Redirect(setting.AppSubURL + "/user/settings/account")
|
||||
}
|
||||
|
||||
// SettingsEmailPost response for change user's email
|
||||
func SettingsEmailPost(ctx *context.Context, form auth.AddEmailForm) {
|
||||
ctx.Data["Title"] = ctx.Tr("settings")
|
||||
ctx.Data["PageIsSettingsEmails"] = true
|
||||
ctx.Data["PageIsSettingsAccount"] = true
|
||||
|
||||
// Make emailaddress primary.
|
||||
if ctx.Query("_method") == "PRIMARY" {
|
||||
|
@ -279,7 +246,7 @@ func SettingsEmailPost(ctx *context.Context, form auth.AddEmailForm) {
|
|||
}
|
||||
|
||||
log.Trace("Email made primary: %s", ctx.User.Name)
|
||||
ctx.Redirect(setting.AppSubURL + "/user/settings/email")
|
||||
ctx.Redirect(setting.AppSubURL + "/user/settings/account")
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -292,7 +259,7 @@ func SettingsEmailPost(ctx *context.Context, form auth.AddEmailForm) {
|
|||
ctx.Data["Emails"] = emails
|
||||
|
||||
if ctx.HasError() {
|
||||
ctx.HTML(200, tplSettingsEmails)
|
||||
ctx.HTML(200, tplSettingsAccount)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -303,7 +270,7 @@ func SettingsEmailPost(ctx *context.Context, form auth.AddEmailForm) {
|
|||
}
|
||||
if err := models.AddEmailAddress(email); err != nil {
|
||||
if models.IsErrEmailAlreadyUsed(err) {
|
||||
ctx.RenderWithErr(ctx.Tr("form.email_been_used"), tplSettingsEmails, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("form.email_been_used"), tplSettingsAccount, &form)
|
||||
return
|
||||
}
|
||||
ctx.ServerError("AddEmailAddress", err)
|
||||
|
@ -323,7 +290,7 @@ func SettingsEmailPost(ctx *context.Context, form auth.AddEmailForm) {
|
|||
}
|
||||
|
||||
log.Trace("Email address added: %s", email.Email)
|
||||
ctx.Redirect(setting.AppSubURL + "/user/settings/email")
|
||||
ctx.Redirect(setting.AppSubURL + "/user/settings/account")
|
||||
}
|
||||
|
||||
// DeleteEmail response for delete user's email
|
||||
|
@ -336,7 +303,164 @@ func DeleteEmail(ctx *context.Context) {
|
|||
|
||||
ctx.Flash.Success(ctx.Tr("settings.email_deletion_success"))
|
||||
ctx.JSON(200, map[string]interface{}{
|
||||
"redirect": setting.AppSubURL + "/user/settings/email",
|
||||
"redirect": setting.AppSubURL + "/user/settings/account",
|
||||
})
|
||||
}
|
||||
|
||||
// SettingsDelete render user suicide page and response for delete user himself
|
||||
func SettingsDelete(ctx *context.Context) {
|
||||
ctx.Data["Title"] = ctx.Tr("settings")
|
||||
ctx.Data["PageIsSettingsAccount"] = true
|
||||
|
||||
if _, err := models.UserSignIn(ctx.User.Name, ctx.Query("password")); err != nil {
|
||||
if models.IsErrUserNotExist(err) {
|
||||
ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_password"), tplSettingsAccount, nil)
|
||||
} else {
|
||||
ctx.ServerError("UserSignIn", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if err := models.DeleteUser(ctx.User); err != nil {
|
||||
switch {
|
||||
case models.IsErrUserOwnRepos(err):
|
||||
ctx.Flash.Error(ctx.Tr("form.still_own_repo"))
|
||||
ctx.Redirect(setting.AppSubURL + "/user/settings/account")
|
||||
case models.IsErrUserHasOrgs(err):
|
||||
ctx.Flash.Error(ctx.Tr("form.still_has_org"))
|
||||
ctx.Redirect(setting.AppSubURL + "/user/settings/account")
|
||||
default:
|
||||
ctx.ServerError("DeleteUser", err)
|
||||
}
|
||||
} else {
|
||||
log.Trace("Account deleted: %s", ctx.User.Name)
|
||||
ctx.Redirect(setting.AppSubURL + "/")
|
||||
}
|
||||
}
|
||||
|
||||
// SettingsSecurity render change user's password page and 2FA
|
||||
func SettingsSecurity(ctx *context.Context) {
|
||||
ctx.Data["Title"] = ctx.Tr("settings")
|
||||
ctx.Data["PageIsSettingsSecurity"] = true
|
||||
|
||||
enrolled := true
|
||||
_, err := models.GetTwoFactorByUID(ctx.User.ID)
|
||||
if err != nil {
|
||||
if models.IsErrTwoFactorNotEnrolled(err) {
|
||||
enrolled = false
|
||||
} else {
|
||||
ctx.ServerError("SettingsTwoFactor", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
ctx.Data["TwofaEnrolled"] = enrolled
|
||||
|
||||
accountLinks, err := models.ListAccountLinks(ctx.User)
|
||||
if err != nil {
|
||||
ctx.ServerError("ListAccountLinks", err)
|
||||
return
|
||||
}
|
||||
|
||||
// map the provider display name with the LoginSource
|
||||
sources := make(map[*models.LoginSource]string)
|
||||
for _, externalAccount := range accountLinks {
|
||||
if loginSource, err := models.GetLoginSourceByID(externalAccount.LoginSourceID); err == nil {
|
||||
var providerDisplayName string
|
||||
if loginSource.IsOAuth2() {
|
||||
providerTechnicalName := loginSource.OAuth2().Provider
|
||||
providerDisplayName = models.OAuth2Providers[providerTechnicalName].DisplayName
|
||||
} else {
|
||||
providerDisplayName = loginSource.Name
|
||||
}
|
||||
sources[loginSource] = providerDisplayName
|
||||
}
|
||||
}
|
||||
ctx.Data["AccountLinks"] = sources
|
||||
|
||||
if ctx.Query("openid.return_to") != "" {
|
||||
settingsOpenIDVerify(ctx)
|
||||
return
|
||||
}
|
||||
|
||||
openid, err := models.GetUserOpenIDs(ctx.User.ID)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetUserOpenIDs", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["OpenIDs"] = openid
|
||||
|
||||
ctx.HTML(200, tplSettingsSecurity)
|
||||
}
|
||||
|
||||
// SettingsDeleteAccountLink delete a single account link
|
||||
func SettingsDeleteAccountLink(ctx *context.Context) {
|
||||
if _, err := models.RemoveAccountLink(ctx.User, ctx.QueryInt64("loginSourceID")); err != nil {
|
||||
ctx.Flash.Error("RemoveAccountLink: " + err.Error())
|
||||
} else {
|
||||
ctx.Flash.Success(ctx.Tr("settings.remove_account_link_success"))
|
||||
}
|
||||
|
||||
ctx.JSON(200, map[string]interface{}{
|
||||
"redirect": setting.AppSubURL + "/user/settings/security",
|
||||
})
|
||||
}
|
||||
|
||||
// SettingsApplications render manage access token page
|
||||
func SettingsApplications(ctx *context.Context) {
|
||||
ctx.Data["Title"] = ctx.Tr("settings")
|
||||
ctx.Data["PageIsSettingsApplications"] = true
|
||||
|
||||
tokens, err := models.ListAccessTokens(ctx.User.ID)
|
||||
if err != nil {
|
||||
ctx.ServerError("ListAccessTokens", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["Tokens"] = tokens
|
||||
|
||||
ctx.HTML(200, tplSettingsApplications)
|
||||
}
|
||||
|
||||
// SettingsApplicationsPost response for add user's access token
|
||||
func SettingsApplicationsPost(ctx *context.Context, form auth.NewAccessTokenForm) {
|
||||
ctx.Data["Title"] = ctx.Tr("settings")
|
||||
ctx.Data["PageIsSettingsApplications"] = true
|
||||
|
||||
if ctx.HasError() {
|
||||
tokens, err := models.ListAccessTokens(ctx.User.ID)
|
||||
if err != nil {
|
||||
ctx.ServerError("ListAccessTokens", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["Tokens"] = tokens
|
||||
ctx.HTML(200, tplSettingsApplications)
|
||||
return
|
||||
}
|
||||
|
||||
t := &models.AccessToken{
|
||||
UID: ctx.User.ID,
|
||||
Name: form.Name,
|
||||
}
|
||||
if err := models.NewAccessToken(t); err != nil {
|
||||
ctx.ServerError("NewAccessToken", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Flash.Success(ctx.Tr("settings.generate_token_success"))
|
||||
ctx.Flash.Info(t.Sha1)
|
||||
|
||||
ctx.Redirect(setting.AppSubURL + "/user/settings/applications")
|
||||
}
|
||||
|
||||
// SettingsDeleteApplication response for delete user access token
|
||||
func SettingsDeleteApplication(ctx *context.Context) {
|
||||
if err := models.DeleteAccessTokenByID(ctx.QueryInt64("id"), ctx.User.ID); err != nil {
|
||||
ctx.Flash.Error("DeleteAccessTokenByID: " + err.Error())
|
||||
} else {
|
||||
ctx.Flash.Success(ctx.Tr("settings.delete_token_success"))
|
||||
}
|
||||
|
||||
ctx.JSON(200, map[string]interface{}{
|
||||
"redirect": setting.AppSubURL + "/user/settings/applications",
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -471,65 +595,6 @@ func DeleteKey(ctx *context.Context) {
|
|||
})
|
||||
}
|
||||
|
||||
// SettingsApplications render user's access tokens page
|
||||
func SettingsApplications(ctx *context.Context) {
|
||||
ctx.Data["Title"] = ctx.Tr("settings")
|
||||
ctx.Data["PageIsSettingsApplications"] = true
|
||||
|
||||
tokens, err := models.ListAccessTokens(ctx.User.ID)
|
||||
if err != nil {
|
||||
ctx.ServerError("ListAccessTokens", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["Tokens"] = tokens
|
||||
|
||||
ctx.HTML(200, tplSettingsApplications)
|
||||
}
|
||||
|
||||
// SettingsApplicationsPost response for add user's access token
|
||||
func SettingsApplicationsPost(ctx *context.Context, form auth.NewAccessTokenForm) {
|
||||
ctx.Data["Title"] = ctx.Tr("settings")
|
||||
ctx.Data["PageIsSettingsApplications"] = true
|
||||
|
||||
if ctx.HasError() {
|
||||
tokens, err := models.ListAccessTokens(ctx.User.ID)
|
||||
if err != nil {
|
||||
ctx.ServerError("ListAccessTokens", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["Tokens"] = tokens
|
||||
ctx.HTML(200, tplSettingsApplications)
|
||||
return
|
||||
}
|
||||
|
||||
t := &models.AccessToken{
|
||||
UID: ctx.User.ID,
|
||||
Name: form.Name,
|
||||
}
|
||||
if err := models.NewAccessToken(t); err != nil {
|
||||
ctx.ServerError("NewAccessToken", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Flash.Success(ctx.Tr("settings.generate_token_success"))
|
||||
ctx.Flash.Info(t.Sha1)
|
||||
|
||||
ctx.Redirect(setting.AppSubURL + "/user/settings/applications")
|
||||
}
|
||||
|
||||
// SettingsDeleteApplication response for delete user access token
|
||||
func SettingsDeleteApplication(ctx *context.Context) {
|
||||
if err := models.DeleteAccessTokenByID(ctx.QueryInt64("id"), ctx.User.ID); err != nil {
|
||||
ctx.Flash.Error("DeleteAccessTokenByID: " + err.Error())
|
||||
} else {
|
||||
ctx.Flash.Success(ctx.Tr("settings.delete_token_success"))
|
||||
}
|
||||
|
||||
ctx.JSON(200, map[string]interface{}{
|
||||
"redirect": setting.AppSubURL + "/user/settings/applications",
|
||||
})
|
||||
}
|
||||
|
||||
// SettingsTwoFactorRegenerateScratch regenerates the user's 2FA scratch code.
|
||||
func SettingsTwoFactorRegenerateScratch(ctx *context.Context) {
|
||||
ctx.Data["Title"] = ctx.Tr("settings")
|
||||
|
@ -695,86 +760,6 @@ func SettingsTwoFactorEnrollPost(ctx *context.Context, form auth.TwoFactorAuthFo
|
|||
ctx.Redirect(setting.AppSubURL + "/user/settings/security")
|
||||
}
|
||||
|
||||
// SettingsAccountLinks render the account links settings page
|
||||
func SettingsAccountLinks(ctx *context.Context) {
|
||||
ctx.Data["Title"] = ctx.Tr("settings")
|
||||
ctx.Data["PageIsSettingsAccountLink"] = true
|
||||
|
||||
accountLinks, err := models.ListAccountLinks(ctx.User)
|
||||
if err != nil {
|
||||
ctx.ServerError("ListAccountLinks", err)
|
||||
return
|
||||
}
|
||||
|
||||
// map the provider display name with the LoginSource
|
||||
sources := make(map[*models.LoginSource]string)
|
||||
for _, externalAccount := range accountLinks {
|
||||
if loginSource, err := models.GetLoginSourceByID(externalAccount.LoginSourceID); err == nil {
|
||||
var providerDisplayName string
|
||||
if loginSource.IsOAuth2() {
|
||||
providerTechnicalName := loginSource.OAuth2().Provider
|
||||
providerDisplayName = models.OAuth2Providers[providerTechnicalName].DisplayName
|
||||
} else {
|
||||
providerDisplayName = loginSource.Name
|
||||
}
|
||||
sources[loginSource] = providerDisplayName
|
||||
}
|
||||
}
|
||||
ctx.Data["AccountLinks"] = sources
|
||||
|
||||
ctx.HTML(200, tplSettingsAccountLink)
|
||||
}
|
||||
|
||||
// SettingsDeleteAccountLink delete a single account link
|
||||
func SettingsDeleteAccountLink(ctx *context.Context) {
|
||||
if _, err := models.RemoveAccountLink(ctx.User, ctx.QueryInt64("loginSourceID")); err != nil {
|
||||
ctx.Flash.Error("RemoveAccountLink: " + err.Error())
|
||||
} else {
|
||||
ctx.Flash.Success(ctx.Tr("settings.remove_account_link_success"))
|
||||
}
|
||||
|
||||
ctx.JSON(200, map[string]interface{}{
|
||||
"redirect": setting.AppSubURL + "/user/settings/account_link",
|
||||
})
|
||||
}
|
||||
|
||||
// SettingsDelete render user suicide page and response for delete user himself
|
||||
func SettingsDelete(ctx *context.Context) {
|
||||
ctx.Data["Title"] = ctx.Tr("settings")
|
||||
ctx.Data["PageIsSettingsDelete"] = true
|
||||
ctx.Data["Email"] = ctx.User.Email
|
||||
|
||||
if ctx.Req.Method == "POST" {
|
||||
if _, err := models.UserSignIn(ctx.User.Name, ctx.Query("password")); err != nil {
|
||||
if models.IsErrUserNotExist(err) {
|
||||
ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_password"), tplSettingsDelete, nil)
|
||||
} else {
|
||||
ctx.ServerError("UserSignIn", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if err := models.DeleteUser(ctx.User); err != nil {
|
||||
switch {
|
||||
case models.IsErrUserOwnRepos(err):
|
||||
ctx.Flash.Error(ctx.Tr("form.still_own_repo"))
|
||||
ctx.Redirect(setting.AppSubURL + "/user/settings/delete")
|
||||
case models.IsErrUserHasOrgs(err):
|
||||
ctx.Flash.Error(ctx.Tr("form.still_has_org"))
|
||||
ctx.Redirect(setting.AppSubURL + "/user/settings/delete")
|
||||
default:
|
||||
ctx.ServerError("DeleteUser", err)
|
||||
}
|
||||
} else {
|
||||
log.Trace("Account deleted: %s", ctx.User.Name)
|
||||
ctx.Redirect(setting.AppSubURL + "/")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
ctx.HTML(200, tplSettingsDelete)
|
||||
}
|
||||
|
||||
// SettingsOrganization render all the organization of the user
|
||||
func SettingsOrganization(ctx *context.Context) {
|
||||
ctx.Data["Title"] = ctx.Tr("settings")
|
||||
|
|
|
@ -8,40 +8,15 @@ import (
|
|||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/auth"
|
||||
"code.gitea.io/gitea/modules/auth/openid"
|
||||
"code.gitea.io/gitea/modules/base"
|
||||
"code.gitea.io/gitea/modules/context"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
)
|
||||
|
||||
const (
|
||||
tplSettingsOpenID base.TplName = "user/settings/openid"
|
||||
)
|
||||
|
||||
// SettingsOpenID renders change user's openid page
|
||||
func SettingsOpenID(ctx *context.Context) {
|
||||
ctx.Data["Title"] = ctx.Tr("settings")
|
||||
ctx.Data["PageIsSettingsOpenID"] = true
|
||||
|
||||
if ctx.Query("openid.return_to") != "" {
|
||||
settingsOpenIDVerify(ctx)
|
||||
return
|
||||
}
|
||||
|
||||
openid, err := models.GetUserOpenIDs(ctx.User.ID)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetUserOpenIDs", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["OpenIDs"] = openid
|
||||
|
||||
ctx.HTML(200, tplSettingsOpenID)
|
||||
}
|
||||
|
||||
// SettingsOpenIDPost response for change user's openid
|
||||
func SettingsOpenIDPost(ctx *context.Context, form auth.AddOpenIDForm) {
|
||||
ctx.Data["Title"] = ctx.Tr("settings")
|
||||
ctx.Data["PageIsSettingsOpenID"] = true
|
||||
ctx.Data["PageIsSettingsSecurity"] = true
|
||||
|
||||
if ctx.HasError() {
|
||||
openid, err := models.GetUserOpenIDs(ctx.User.ID)
|
||||
|
@ -50,7 +25,7 @@ func SettingsOpenIDPost(ctx *context.Context, form auth.AddOpenIDForm) {
|
|||
return
|
||||
}
|
||||
ctx.Data["OpenIDs"] = openid
|
||||
ctx.HTML(200, tplSettingsOpenID)
|
||||
ctx.HTML(200, tplSettingsSecurity)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -62,7 +37,7 @@ func SettingsOpenIDPost(ctx *context.Context, form auth.AddOpenIDForm) {
|
|||
|
||||
id, err := openid.Normalize(form.Openid)
|
||||
if err != nil {
|
||||
ctx.RenderWithErr(err.Error(), tplSettingsOpenID, &form)
|
||||
ctx.RenderWithErr(err.Error(), tplSettingsSecurity, &form)
|
||||
return
|
||||
}
|
||||
form.Openid = id
|
||||
|
@ -78,15 +53,15 @@ func SettingsOpenIDPost(ctx *context.Context, form auth.AddOpenIDForm) {
|
|||
// Check that the OpenID is not already used
|
||||
for _, obj := range oids {
|
||||
if obj.URI == id {
|
||||
ctx.RenderWithErr(ctx.Tr("form.openid_been_used", id), tplSettingsOpenID, &form)
|
||||
ctx.RenderWithErr(ctx.Tr("form.openid_been_used", id), tplSettingsSecurity, &form)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
redirectTo := setting.AppURL + "user/settings/openid"
|
||||
redirectTo := setting.AppURL + "user/settings/security"
|
||||
url, err := openid.RedirectURL(id, redirectTo, setting.AppURL)
|
||||
if err != nil {
|
||||
ctx.RenderWithErr(err.Error(), tplSettingsOpenID, &form)
|
||||
ctx.RenderWithErr(err.Error(), tplSettingsSecurity, &form)
|
||||
return
|
||||
}
|
||||
ctx.Redirect(url)
|
||||
|
@ -107,7 +82,7 @@ func settingsOpenIDVerify(ctx *context.Context) {
|
|||
|
||||
id, err := openid.Verify(fullURL)
|
||||
if err != nil {
|
||||
ctx.RenderWithErr(err.Error(), tplSettingsOpenID, &auth.AddOpenIDForm{
|
||||
ctx.RenderWithErr(err.Error(), tplSettingsSecurity, &auth.AddOpenIDForm{
|
||||
Openid: id,
|
||||
})
|
||||
return
|
||||
|
@ -118,7 +93,7 @@ func settingsOpenIDVerify(ctx *context.Context) {
|
|||
oid := &models.UserOpenID{UID: ctx.User.ID, URI: id}
|
||||
if err = models.AddUserOpenID(oid); err != nil {
|
||||
if models.IsErrOpenIDAlreadyUsed(err) {
|
||||
ctx.RenderWithErr(ctx.Tr("form.openid_been_used", id), tplSettingsOpenID, &auth.AddOpenIDForm{Openid: id})
|
||||
ctx.RenderWithErr(ctx.Tr("form.openid_been_used", id), tplSettingsSecurity, &auth.AddOpenIDForm{Openid: id})
|
||||
return
|
||||
}
|
||||
ctx.ServerError("AddUserOpenID", err)
|
||||
|
@ -127,7 +102,7 @@ func settingsOpenIDVerify(ctx *context.Context) {
|
|||
log.Trace("Associated OpenID %s to user %s", id, ctx.User.Name)
|
||||
ctx.Flash.Success(ctx.Tr("settings.add_openid_success"))
|
||||
|
||||
ctx.Redirect(setting.AppSubURL + "/user/settings/openid")
|
||||
ctx.Redirect(setting.AppSubURL + "/user/settings/security")
|
||||
}
|
||||
|
||||
// DeleteOpenID response for delete user's openid
|
||||
|
@ -140,7 +115,7 @@ func DeleteOpenID(ctx *context.Context) {
|
|||
|
||||
ctx.Flash.Success(ctx.Tr("settings.openid_deletion_success"))
|
||||
ctx.JSON(200, map[string]interface{}{
|
||||
"redirect": setting.AppSubURL + "/user/settings/openid",
|
||||
"redirect": setting.AppSubURL + "/user/settings/security",
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -151,5 +126,5 @@ func ToggleOpenIDVisibility(ctx *context.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
ctx.Redirect(setting.AppSubURL + "/user/settings/openid")
|
||||
ctx.Redirect(setting.AppSubURL + "/user/settings/security")
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ func TestChangePassword(t *testing.T) {
|
|||
test.LoadUser(t, ctx, 2)
|
||||
test.LoadRepo(t, ctx, 1)
|
||||
|
||||
SettingsSecurityPost(ctx, auth.ChangePasswordForm{
|
||||
SettingsAccountPost(ctx, auth.ChangePasswordForm{
|
||||
OldPassword: req.OldPassword,
|
||||
Password: req.NewPassword,
|
||||
Retype: req.Retype,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue