| @@ -249,7 +249,7 @@ func runWeb(ctx *cli.Context) { | |||||
| }) | }) | ||||
| }, ignSignIn) | }, ignSignIn) | ||||
| // User. | |||||
| // ***** START: User ***** | |||||
| m.Group("/user", func() { | m.Group("/user", func() { | ||||
| m.Get("/login", user.SignIn) | m.Get("/login", user.SignIn) | ||||
| m.Post("/login", bindIgnErr(auth.SignInForm{}), user.SignInPost) | m.Post("/login", bindIgnErr(auth.SignInForm{}), user.SignInPost) | ||||
| @@ -259,6 +259,7 @@ func runWeb(ctx *cli.Context) { | |||||
| m.Get("/reset_password", user.ResetPasswd) | m.Get("/reset_password", user.ResetPasswd) | ||||
| m.Post("/reset_password", user.ResetPasswdPost) | m.Post("/reset_password", user.ResetPasswdPost) | ||||
| }, reqSignOut) | }, reqSignOut) | ||||
| m.Group("/user/settings", func() { | m.Group("/user/settings", func() { | ||||
| m.Get("", user.Settings) | m.Get("", user.Settings) | ||||
| m.Post("", bindIgnErr(auth.UpdateProfileForm{}), user.SettingsPost) | m.Post("", bindIgnErr(auth.UpdateProfileForm{}), user.SettingsPost) | ||||
| @@ -272,7 +273,11 @@ func runWeb(ctx *cli.Context) { | |||||
| m.Get("/social", user.SettingsSocial) | m.Get("/social", user.SettingsSocial) | ||||
| m.Combo("/applications").Get(user.SettingsApplications).Post(bindIgnErr(auth.NewAccessTokenForm{}), user.SettingsApplicationsPost) | m.Combo("/applications").Get(user.SettingsApplications).Post(bindIgnErr(auth.NewAccessTokenForm{}), user.SettingsApplicationsPost) | ||||
| m.Route("/delete", "GET,POST", user.SettingsDelete) | m.Route("/delete", "GET,POST", user.SettingsDelete) | ||||
| }, reqSignIn) | |||||
| }, reqSignIn, func(ctx *middleware.Context) { | |||||
| ctx.Data["PageIsUserSettings"] = true | |||||
| ctx.Data["HasOAuthService"] = setting.OauthService != nil | |||||
| }) | |||||
| m.Group("/user", func() { | m.Group("/user", func() { | ||||
| // r.Get("/feeds", binding.Bind(auth.FeedsForm{}), user.Feeds) | // r.Get("/feeds", binding.Bind(auth.FeedsForm{}), user.Feeds) | ||||
| m.Any("/activate", user.Activate) | m.Any("/activate", user.Activate) | ||||
| @@ -282,6 +287,7 @@ func runWeb(ctx *cli.Context) { | |||||
| m.Post("/forget_password", user.ForgotPasswdPost) | m.Post("/forget_password", user.ForgotPasswdPost) | ||||
| m.Get("/logout", user.SignOut) | m.Get("/logout", user.SignOut) | ||||
| }) | }) | ||||
| // ***** END: User ***** | |||||
| // Gravatar service. | // Gravatar service. | ||||
| avt := avatar.CacheServer("public/img/avatar/", "public/img/avatar_default.jpg") | avt := avatar.CacheServer("public/img/avatar/", "public/img/avatar_default.jpg") | ||||
| @@ -395,6 +395,26 @@ | |||||
| "strictMath": 0, | "strictMath": 0, | ||||
| "strictUnits": 0 | "strictUnits": 0 | ||||
| }, | }, | ||||
| "\/public\/less\/_user.less": { | |||||
| "allowInsecureImports": 0, | |||||
| "createSourceMap": 0, | |||||
| "disableJavascript": 0, | |||||
| "fileType": 1, | |||||
| "ieCompatibility": 1, | |||||
| "ignore": 1, | |||||
| "ignoreWasSetByUser": 0, | |||||
| "inputAbbreviatedPath": "\/public\/less\/_user.less", | |||||
| "outputAbbreviatedPath": "\/public\/css\/_user.css", | |||||
| "outputPathIsOutsideProject": 0, | |||||
| "outputPathIsSetByUser": 0, | |||||
| "outputStyle": 0, | |||||
| "relativeURLS": 0, | |||||
| "shouldRunAutoprefixer": 0, | |||||
| "shouldRunBless": 0, | |||||
| "strictImports": 0, | |||||
| "strictMath": 0, | |||||
| "strictUnits": 0 | |||||
| }, | |||||
| "\/public\/less\/gogs.less": { | "\/public\/less\/gogs.less": { | ||||
| "allowInsecureImports": 0, | "allowInsecureImports": 0, | ||||
| "createSourceMap": 0, | "createSourceMap": 0, | ||||
| @@ -17,7 +17,7 @@ import ( | |||||
| "github.com/gogits/gogs/modules/setting" | "github.com/gogits/gogs/modules/setting" | ||||
| ) | ) | ||||
| const APP_VER = "0.6.5.0818 Beta" | |||||
| const APP_VER = "0.6.5.0819 Beta" | |||||
| func init() { | func init() { | ||||
| runtime.GOMAXPROCS(runtime.NumCPU()) | runtime.GOMAXPROCS(runtime.NumCPU()) | ||||
| @@ -336,6 +336,11 @@ $(document).ready(function () { | |||||
| $('.delete.modal').modal({ | $('.delete.modal').modal({ | ||||
| closable: false, | closable: false, | ||||
| onApprove: function () { | onApprove: function () { | ||||
| if ($this.data('type') == "form") { | |||||
| $($this.data('form')).submit(); | |||||
| return; | |||||
| } | |||||
| $.post($this.data('url'), { | $.post($this.data('url'), { | ||||
| "_csrf": csrf, | "_csrf": csrf, | ||||
| "id": $this.data("id") | "id": $this.data("id") | ||||
| @@ -102,6 +102,15 @@ img { | |||||
| padding-left: 0.75rem; | padding-left: 0.75rem; | ||||
| vertical-align: middle; | vertical-align: middle; | ||||
| } | } | ||||
| .warning { | |||||
| &.header { | |||||
| background-color: #F9EDBE!important; | |||||
| border-color: #F0C36D; | |||||
| } | |||||
| &.segment { | |||||
| border-color: #F0C36D; | |||||
| } | |||||
| } | |||||
| .avatar.image { | .avatar.image { | ||||
| border-radius: 3px; | border-radius: 3px; | ||||
| @@ -0,0 +1,4 @@ | |||||
| .user { | |||||
| padding-top: 15px; | |||||
| padding-bottom: @footer-margin * 3; | |||||
| } | |||||
| @@ -5,4 +5,5 @@ | |||||
| @import "_install"; | @import "_install"; | ||||
| @import "_form"; | @import "_form"; | ||||
| @import "_repository"; | @import "_repository"; | ||||
| @import "_user"; | |||||
| @import "_admin"; | @import "_admin"; | ||||
| @@ -33,14 +33,12 @@ const ( | |||||
| func Settings(ctx *middleware.Context) { | func Settings(ctx *middleware.Context) { | ||||
| ctx.Data["Title"] = ctx.Tr("settings") | ctx.Data["Title"] = ctx.Tr("settings") | ||||
| ctx.Data["PageIsUserSettings"] = true | |||||
| ctx.Data["PageIsSettingsProfile"] = true | ctx.Data["PageIsSettingsProfile"] = true | ||||
| ctx.HTML(200, SETTINGS_PROFILE) | ctx.HTML(200, SETTINGS_PROFILE) | ||||
| } | } | ||||
| func SettingsPost(ctx *middleware.Context, form auth.UpdateProfileForm) { | func SettingsPost(ctx *middleware.Context, form auth.UpdateProfileForm) { | ||||
| ctx.Data["Title"] = ctx.Tr("settings") | ctx.Data["Title"] = ctx.Tr("settings") | ||||
| ctx.Data["PageIsUserSettings"] = true | |||||
| ctx.Data["PageIsSettingsProfile"] = true | ctx.Data["PageIsSettingsProfile"] = true | ||||
| if ctx.HasError() { | if ctx.HasError() { | ||||
| @@ -132,7 +130,6 @@ func SettingsAvatar(ctx *middleware.Context, form auth.UploadAvatarForm) { | |||||
| func SettingsEmails(ctx *middleware.Context) { | func SettingsEmails(ctx *middleware.Context) { | ||||
| ctx.Data["Title"] = ctx.Tr("settings") | ctx.Data["Title"] = ctx.Tr("settings") | ||||
| ctx.Data["PageIsUserSettings"] = true | |||||
| ctx.Data["PageIsSettingsEmails"] = true | ctx.Data["PageIsSettingsEmails"] = true | ||||
| emails, err := models.GetEmailAddresses(ctx.User.Id) | emails, err := models.GetEmailAddresses(ctx.User.Id) | ||||
| @@ -147,7 +144,6 @@ func SettingsEmails(ctx *middleware.Context) { | |||||
| func SettingsEmailPost(ctx *middleware.Context, form auth.AddEmailForm) { | func SettingsEmailPost(ctx *middleware.Context, form auth.AddEmailForm) { | ||||
| ctx.Data["Title"] = ctx.Tr("settings") | ctx.Data["Title"] = ctx.Tr("settings") | ||||
| ctx.Data["PageIsUserSettings"] = true | |||||
| ctx.Data["PageIsSettingsEmails"] = true | ctx.Data["PageIsSettingsEmails"] = true | ||||
| emails, err := models.GetEmailAddresses(ctx.User.Id) | emails, err := models.GetEmailAddresses(ctx.User.Id) | ||||
| @@ -232,14 +228,12 @@ func SettingsEmailPost(ctx *middleware.Context, form auth.AddEmailForm) { | |||||
| func SettingsPassword(ctx *middleware.Context) { | func SettingsPassword(ctx *middleware.Context) { | ||||
| ctx.Data["Title"] = ctx.Tr("settings") | ctx.Data["Title"] = ctx.Tr("settings") | ||||
| ctx.Data["PageIsUserSettings"] = true | |||||
| ctx.Data["PageIsSettingsPassword"] = true | ctx.Data["PageIsSettingsPassword"] = true | ||||
| ctx.HTML(200, SETTINGS_PASSWORD) | ctx.HTML(200, SETTINGS_PASSWORD) | ||||
| } | } | ||||
| func SettingsPasswordPost(ctx *middleware.Context, form auth.ChangePasswordForm) { | func SettingsPasswordPost(ctx *middleware.Context, form auth.ChangePasswordForm) { | ||||
| ctx.Data["Title"] = ctx.Tr("settings") | ctx.Data["Title"] = ctx.Tr("settings") | ||||
| ctx.Data["PageIsUserSettings"] = true | |||||
| ctx.Data["PageIsSettingsPassword"] = true | ctx.Data["PageIsSettingsPassword"] = true | ||||
| if ctx.HasError() { | if ctx.HasError() { | ||||
| @@ -273,7 +267,6 @@ func SettingsPasswordPost(ctx *middleware.Context, form auth.ChangePasswordForm) | |||||
| func SettingsSSHKeys(ctx *middleware.Context) { | func SettingsSSHKeys(ctx *middleware.Context) { | ||||
| ctx.Data["Title"] = ctx.Tr("settings") | ctx.Data["Title"] = ctx.Tr("settings") | ||||
| ctx.Data["PageIsUserSettings"] = true | |||||
| ctx.Data["PageIsSettingsSSHKeys"] = true | ctx.Data["PageIsSettingsSSHKeys"] = true | ||||
| var err error | var err error | ||||
| @@ -288,7 +281,6 @@ func SettingsSSHKeys(ctx *middleware.Context) { | |||||
| func SettingsSSHKeysPost(ctx *middleware.Context, form auth.AddSSHKeyForm) { | func SettingsSSHKeysPost(ctx *middleware.Context, form auth.AddSSHKeyForm) { | ||||
| ctx.Data["Title"] = ctx.Tr("settings") | ctx.Data["Title"] = ctx.Tr("settings") | ||||
| ctx.Data["PageIsUserSettings"] = true | |||||
| ctx.Data["PageIsSettingsSSHKeys"] = true | ctx.Data["PageIsSettingsSSHKeys"] = true | ||||
| var err error | var err error | ||||
| @@ -355,7 +347,6 @@ func SettingsSSHKeysPost(ctx *middleware.Context, form auth.AddSSHKeyForm) { | |||||
| func SettingsSocial(ctx *middleware.Context) { | func SettingsSocial(ctx *middleware.Context) { | ||||
| ctx.Data["Title"] = ctx.Tr("settings") | ctx.Data["Title"] = ctx.Tr("settings") | ||||
| ctx.Data["PageIsUserSettings"] = true | |||||
| ctx.Data["PageIsSettingsSocial"] = true | ctx.Data["PageIsSettingsSocial"] = true | ||||
| // Unbind social account. | // Unbind social account. | ||||
| @@ -381,7 +372,6 @@ func SettingsSocial(ctx *middleware.Context) { | |||||
| func SettingsApplications(ctx *middleware.Context) { | func SettingsApplications(ctx *middleware.Context) { | ||||
| ctx.Data["Title"] = ctx.Tr("settings") | ctx.Data["Title"] = ctx.Tr("settings") | ||||
| ctx.Data["PageIsUserSettings"] = true | |||||
| ctx.Data["PageIsSettingsApplications"] = true | ctx.Data["PageIsSettingsApplications"] = true | ||||
| // Delete access token. | // Delete access token. | ||||
| @@ -409,7 +399,6 @@ func SettingsApplications(ctx *middleware.Context) { | |||||
| // FIXME: split to two different functions and pages to handle access token and oauth2 | // FIXME: split to two different functions and pages to handle access token and oauth2 | ||||
| func SettingsApplicationsPost(ctx *middleware.Context, form auth.NewAccessTokenForm) { | func SettingsApplicationsPost(ctx *middleware.Context, form auth.NewAccessTokenForm) { | ||||
| ctx.Data["Title"] = ctx.Tr("settings") | ctx.Data["Title"] = ctx.Tr("settings") | ||||
| ctx.Data["PageIsUserSettings"] = true | |||||
| ctx.Data["PageIsSettingsApplications"] = true | ctx.Data["PageIsSettingsApplications"] = true | ||||
| switch ctx.Query("type") { | switch ctx.Query("type") { | ||||
| @@ -437,11 +426,18 @@ func SettingsApplicationsPost(ctx *middleware.Context, form auth.NewAccessTokenF | |||||
| func SettingsDelete(ctx *middleware.Context) { | func SettingsDelete(ctx *middleware.Context) { | ||||
| ctx.Data["Title"] = ctx.Tr("settings") | ctx.Data["Title"] = ctx.Tr("settings") | ||||
| ctx.Data["PageIsUserSettings"] = true | |||||
| ctx.Data["PageIsSettingsDelete"] = true | ctx.Data["PageIsSettingsDelete"] = true | ||||
| if ctx.Req.Method == "POST" { | if ctx.Req.Method == "POST" { | ||||
| // FIXME: validate password. | |||||
| if _, err := models.UserSignIn(ctx.User.Name, ctx.Query("password")); err != nil { | |||||
| if models.IsErrUserNotExist(err) { | |||||
| ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_password"), SETTINGS_DELETE, nil) | |||||
| } else { | |||||
| ctx.Handle(500, "UserSignIn", err) | |||||
| } | |||||
| return | |||||
| } | |||||
| if err := models.DeleteUser(ctx.User); err != nil { | if err := models.DeleteUser(ctx.User); err != nil { | ||||
| switch { | switch { | ||||
| case models.IsErrUserOwnRepos(err): | case models.IsErrUserOwnRepos(err): | ||||
| @@ -1 +1 @@ | |||||
| 0.6.5.0818 Beta | |||||
| 0.6.5.0819 Beta | |||||
| @@ -110,7 +110,7 @@ | |||||
| <i class="octicon icon octicon-person"></i> | <i class="octicon icon octicon-person"></i> | ||||
| {{.i18n.Tr "your_profile"}}<!-- Your profile --> | {{.i18n.Tr "your_profile"}}<!-- Your profile --> | ||||
| </a> | </a> | ||||
| <a class="item" href="{{AppSubUrl}}/user/settings"> | |||||
| <a class="{{if .PageIsUserSettings}}active{{end}} item" href="{{AppSubUrl}}/user/settings"> | |||||
| <i class="octicon icon octicon-settings"></i> | <i class="octicon icon octicon-settings"></i> | ||||
| {{.i18n.Tr "your_settings"}}<!-- Your settings --> | {{.i18n.Tr "your_settings"}}<!-- Your settings --> | ||||
| </a> | </a> | ||||
| @@ -121,7 +121,7 @@ | |||||
| {{if .IsAdmin}} | {{if .IsAdmin}} | ||||
| <div class="divider"></div> | <div class="divider"></div> | ||||
| <a class="item" href="{{AppSubUrl}}/admin"> | |||||
| <a class="{{if .PageIsAdmin}}active{{end}} item" href="{{AppSubUrl}}/admin"> | |||||
| <i class="icon settings"></i> | <i class="icon settings"></i> | ||||
| {{.i18n.Tr "admin_panel"}}<!-- Admin Panel --> | {{.i18n.Tr "admin_panel"}}<!-- Admin Panel --> | ||||
| </a> | </a> | ||||
| @@ -24,7 +24,7 @@ | |||||
| <label for="auth_username">{{.i18n.Tr "username"}}</label> | <label for="auth_username">{{.i18n.Tr "username"}}</label> | ||||
| <input id="auth_username" name="auth_username" value="{{.auth_username}}" {{if not .auth_username}}data-need-clear="true"{{end}}> | <input id="auth_username" name="auth_username" value="{{.auth_username}}" {{if not .auth_username}}data-need-clear="true"{{end}}> | ||||
| </div> | </div> | ||||
| <input class="fake"> | |||||
| <input class="fake" type="password"> | |||||
| <div class="inline field {{if .Err_Auth}}error{{end}}"> | <div class="inline field {{if .Err_Auth}}error{{end}}"> | ||||
| <label for="auth_password">{{.i18n.Tr "password"}}</label> | <label for="auth_password">{{.i18n.Tr "password"}}</label> | ||||
| <input id="auth_password" name="auth_password" type="password" value="{{.auth_password}}"> | <input id="auth_password" name="auth_password" type="password" value="{{.auth_password}}"> | ||||
| @@ -1,35 +1,51 @@ | |||||
| {{template "ng/base/head" .}} | |||||
| {{template "ng/base/header" .}} | |||||
| <div id="setting-wrapper" class="main-wrapper"> | |||||
| <div id="user-profile-setting" class="container clear"> | |||||
| {{template "user/settings/nav" .}} | |||||
| <div class="grid-4-5 left"> | |||||
| <div class="setting-content"> | |||||
| {{template "ng/base/alert" .}} | |||||
| <div id="setting-content"> | |||||
| <div id="user-profile-setting-content" class="panel panel-warning panel-radius"> | |||||
| <p class="panel-header"><strong>{{.i18n.Tr "settings.delete_account"}}</strong></p> | |||||
| <div class="panel-body panel-content"> | |||||
| <span class="alert alert-red alert-radius block"><i class="octicon octicon-alert"></i>{{.i18n.Tr "settings.delete_prompt" | Str2html}}</span> | |||||
| <form id="delete-account-form" action="{{AppSubUrl}}/user/settings/delete" method="post"> | |||||
| {{.CsrfTokenHtml}} | |||||
| <p class="field"> | |||||
| <span class="form-label"></span> | |||||
| <button class="btn btn-red btn-large btn-radius" id="delete-account-btn" href="#delete-account-modal">{{.i18n.Tr "settings.confirm_delete_account"}}</button> | |||||
| </p> | |||||
| </form> | |||||
| <div class="white-popup-block mfp-hide" id="delete-account-modal"> | |||||
| <h1 class="text-red">{{.i18n.Tr "settings.delete_account_title"}}</h1> | |||||
| <p>{{.i18n.Tr "settings.delete_account_desc"}}</p> | |||||
| <br> | |||||
| <button class="btn btn-red btn-large btn-radius" id="delete-account-submit">{{.i18n.Tr "settings.continue"}}</button> | |||||
| <button class="btn btn-large btn-radius popup-modal-dismiss">{{.i18n.Tr "settings.cancel"}}</button> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| {{template "base/head" .}} | |||||
| <div class="user settings"> | |||||
| <div class="ui container"> | |||||
| <div class="ui grid"> | |||||
| {{template "user/settings/navbar" .}} | |||||
| <div class="twelve wide column content"> | |||||
| {{template "base/alert" .}} | |||||
| <h4 class="ui top attached warning header"> | |||||
| {{.i18n.Tr "settings.delete_account"}} | |||||
| </h4> | |||||
| <div class="ui attached warning segment"> | |||||
| <div class="ui red message"> | |||||
| <p>{{.i18n.Tr "settings.delete_prompt" | Str2html}}</p> | |||||
| </div> | |||||
| <form class="ui form" id="delete-form" action="{{.Link}}" method="post"> | |||||
| {{.CsrfTokenHtml}} | |||||
| <input class="fake" type="password"> | |||||
| <div class="inline required field {{if .Err_Password}}error{{end}}"> | |||||
| <label for="password">{{.i18n.Tr "password"}}</label> | |||||
| <input id="password" name="password" type="password" autofocus required> | |||||
| </div> | </div> | ||||
| <div class="ui red button delete-button" data-type="form" data-form="#delete-form"> | |||||
| {{.i18n.Tr "settings.confirm_delete_account"}} | |||||
| </div> | |||||
| </form> | |||||
| </div> | </div> | ||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| <div class="ui small basic delete modal"> | |||||
| <div class="ui icon header"> | |||||
| <i class="trash icon"></i> | |||||
| {{.i18n.Tr "settings.delete_account_title"}} | |||||
| </div> | |||||
| <div class="content"> | |||||
| <p>{{.i18n.Tr "settings.delete_account_desc"}}</p> | |||||
| </div> | |||||
| <div class="actions"> | |||||
| <div class="ui red basic inverted cancel button"> | |||||
| <i class="remove icon"></i> | |||||
| {{.i18n.Tr "modal.no"}} | |||||
| </div> | |||||
| <div class="ui green basic inverted ok button"> | |||||
| <i class="checkmark icon"></i> | |||||
| {{.i18n.Tr "modal.yes"}} | |||||
| </div> | </div> | ||||
| </div> | |||||
| </div> | </div> | ||||
| {{template "ng/base/footer" .}} | |||||
| {{template "base/footer" .}} | |||||
| @@ -0,0 +1,28 @@ | |||||
| <div class="four wide column"> | |||||
| <div class="ui vertical menu"> | |||||
| <div class="header item">{{.i18n.Tr "settings"}}</div> | |||||
| <a class="{{if .PageIsSettingsProfile}}active{{end}} item" href="{{AppSubUrl}}/user/settings"> | |||||
| {{.i18n.Tr "settings.profile"}} | |||||
| </a> | |||||
| <a class="{{if .PageIsSettingsPassword}}active{{end}} item" href="{{AppSubUrl}}/user/settings/password"> | |||||
| {{.i18n.Tr "settings.password"}} | |||||
| </a> | |||||
| <a class="{{if .PageIsSettingsEmails}}active{{end}} item" href="{{AppSubUrl}}/user/settings/email"> | |||||
| {{.i18n.Tr "settings.emails"}} | |||||
| </a> | |||||
| <a class="{{if .PageIsSettingsSSHKeys}}active{{end}} item" href="{{AppSubUrl}}/user/settings/ssh"> | |||||
| {{.i18n.Tr "settings.ssh_keys"}} | |||||
| </a> | |||||
| {{if .HasOAuthService}} | |||||
| <a class="{{if .PageIsSettingsSocial}}active{{end}} item" href="{{AppSubUrl}}/user/settings/social"> | |||||
| {{.i18n.Tr "settings.social"}} | |||||
| </a> | |||||
| {{end}} | |||||
| <a class="{{if .PageIsSettingsApplications}}active{{end}} item" href="{{AppSubUrl}}/user/settings/applications"> | |||||
| {{.i18n.Tr "settings.applications"}} | |||||
| </a> | |||||
| <a class="{{if .PageIsSettingsDelete}}active{{end}} item" href="{{AppSubUrl}}/user/settings/delete"> | |||||
| {{.i18n.Tr "settings.delete"}} | |||||
| </a> | |||||
| </div> | |||||
| </div> | |||||