| @@ -249,7 +249,7 @@ func runWeb(ctx *cli.Context) { | |||
| }) | |||
| }, ignSignIn) | |||
| // User. | |||
| // ***** START: User ***** | |||
| m.Group("/user", func() { | |||
| m.Get("/login", user.SignIn) | |||
| m.Post("/login", bindIgnErr(auth.SignInForm{}), user.SignInPost) | |||
| @@ -259,6 +259,7 @@ func runWeb(ctx *cli.Context) { | |||
| m.Get("/reset_password", user.ResetPasswd) | |||
| m.Post("/reset_password", user.ResetPasswdPost) | |||
| }, reqSignOut) | |||
| m.Group("/user/settings", func() { | |||
| m.Get("", user.Settings) | |||
| m.Post("", bindIgnErr(auth.UpdateProfileForm{}), user.SettingsPost) | |||
| @@ -272,7 +273,11 @@ func runWeb(ctx *cli.Context) { | |||
| m.Get("/social", user.SettingsSocial) | |||
| m.Combo("/applications").Get(user.SettingsApplications).Post(bindIgnErr(auth.NewAccessTokenForm{}), user.SettingsApplicationsPost) | |||
| 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() { | |||
| // r.Get("/feeds", binding.Bind(auth.FeedsForm{}), user.Feeds) | |||
| m.Any("/activate", user.Activate) | |||
| @@ -282,6 +287,7 @@ func runWeb(ctx *cli.Context) { | |||
| m.Post("/forget_password", user.ForgotPasswdPost) | |||
| m.Get("/logout", user.SignOut) | |||
| }) | |||
| // ***** END: User ***** | |||
| // Gravatar service. | |||
| avt := avatar.CacheServer("public/img/avatar/", "public/img/avatar_default.jpg") | |||
| @@ -395,6 +395,26 @@ | |||
| "strictMath": 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": { | |||
| "allowInsecureImports": 0, | |||
| "createSourceMap": 0, | |||
| @@ -17,7 +17,7 @@ import ( | |||
| "github.com/gogits/gogs/modules/setting" | |||
| ) | |||
| const APP_VER = "0.6.5.0818 Beta" | |||
| const APP_VER = "0.6.5.0819 Beta" | |||
| func init() { | |||
| runtime.GOMAXPROCS(runtime.NumCPU()) | |||
| @@ -336,6 +336,11 @@ $(document).ready(function () { | |||
| $('.delete.modal').modal({ | |||
| closable: false, | |||
| onApprove: function () { | |||
| if ($this.data('type') == "form") { | |||
| $($this.data('form')).submit(); | |||
| return; | |||
| } | |||
| $.post($this.data('url'), { | |||
| "_csrf": csrf, | |||
| "id": $this.data("id") | |||
| @@ -102,6 +102,15 @@ img { | |||
| padding-left: 0.75rem; | |||
| vertical-align: middle; | |||
| } | |||
| .warning { | |||
| &.header { | |||
| background-color: #F9EDBE!important; | |||
| border-color: #F0C36D; | |||
| } | |||
| &.segment { | |||
| border-color: #F0C36D; | |||
| } | |||
| } | |||
| .avatar.image { | |||
| border-radius: 3px; | |||
| @@ -0,0 +1,4 @@ | |||
| .user { | |||
| padding-top: 15px; | |||
| padding-bottom: @footer-margin * 3; | |||
| } | |||
| @@ -5,4 +5,5 @@ | |||
| @import "_install"; | |||
| @import "_form"; | |||
| @import "_repository"; | |||
| @import "_user"; | |||
| @import "_admin"; | |||
| @@ -33,14 +33,12 @@ const ( | |||
| func Settings(ctx *middleware.Context) { | |||
| ctx.Data["Title"] = ctx.Tr("settings") | |||
| ctx.Data["PageIsUserSettings"] = true | |||
| ctx.Data["PageIsSettingsProfile"] = true | |||
| ctx.HTML(200, SETTINGS_PROFILE) | |||
| } | |||
| func SettingsPost(ctx *middleware.Context, form auth.UpdateProfileForm) { | |||
| ctx.Data["Title"] = ctx.Tr("settings") | |||
| ctx.Data["PageIsUserSettings"] = true | |||
| ctx.Data["PageIsSettingsProfile"] = true | |||
| if ctx.HasError() { | |||
| @@ -132,7 +130,6 @@ func SettingsAvatar(ctx *middleware.Context, form auth.UploadAvatarForm) { | |||
| func SettingsEmails(ctx *middleware.Context) { | |||
| ctx.Data["Title"] = ctx.Tr("settings") | |||
| ctx.Data["PageIsUserSettings"] = true | |||
| ctx.Data["PageIsSettingsEmails"] = true | |||
| emails, err := models.GetEmailAddresses(ctx.User.Id) | |||
| @@ -147,7 +144,6 @@ func SettingsEmails(ctx *middleware.Context) { | |||
| func SettingsEmailPost(ctx *middleware.Context, form auth.AddEmailForm) { | |||
| ctx.Data["Title"] = ctx.Tr("settings") | |||
| ctx.Data["PageIsUserSettings"] = true | |||
| ctx.Data["PageIsSettingsEmails"] = true | |||
| emails, err := models.GetEmailAddresses(ctx.User.Id) | |||
| @@ -232,14 +228,12 @@ func SettingsEmailPost(ctx *middleware.Context, form auth.AddEmailForm) { | |||
| func SettingsPassword(ctx *middleware.Context) { | |||
| ctx.Data["Title"] = ctx.Tr("settings") | |||
| ctx.Data["PageIsUserSettings"] = true | |||
| ctx.Data["PageIsSettingsPassword"] = true | |||
| ctx.HTML(200, SETTINGS_PASSWORD) | |||
| } | |||
| func SettingsPasswordPost(ctx *middleware.Context, form auth.ChangePasswordForm) { | |||
| ctx.Data["Title"] = ctx.Tr("settings") | |||
| ctx.Data["PageIsUserSettings"] = true | |||
| ctx.Data["PageIsSettingsPassword"] = true | |||
| if ctx.HasError() { | |||
| @@ -273,7 +267,6 @@ func SettingsPasswordPost(ctx *middleware.Context, form auth.ChangePasswordForm) | |||
| func SettingsSSHKeys(ctx *middleware.Context) { | |||
| ctx.Data["Title"] = ctx.Tr("settings") | |||
| ctx.Data["PageIsUserSettings"] = true | |||
| ctx.Data["PageIsSettingsSSHKeys"] = true | |||
| var err error | |||
| @@ -288,7 +281,6 @@ func SettingsSSHKeys(ctx *middleware.Context) { | |||
| func SettingsSSHKeysPost(ctx *middleware.Context, form auth.AddSSHKeyForm) { | |||
| ctx.Data["Title"] = ctx.Tr("settings") | |||
| ctx.Data["PageIsUserSettings"] = true | |||
| ctx.Data["PageIsSettingsSSHKeys"] = true | |||
| var err error | |||
| @@ -355,7 +347,6 @@ func SettingsSSHKeysPost(ctx *middleware.Context, form auth.AddSSHKeyForm) { | |||
| func SettingsSocial(ctx *middleware.Context) { | |||
| ctx.Data["Title"] = ctx.Tr("settings") | |||
| ctx.Data["PageIsUserSettings"] = true | |||
| ctx.Data["PageIsSettingsSocial"] = true | |||
| // Unbind social account. | |||
| @@ -381,7 +372,6 @@ func SettingsSocial(ctx *middleware.Context) { | |||
| func SettingsApplications(ctx *middleware.Context) { | |||
| ctx.Data["Title"] = ctx.Tr("settings") | |||
| ctx.Data["PageIsUserSettings"] = true | |||
| ctx.Data["PageIsSettingsApplications"] = true | |||
| // 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 | |||
| func SettingsApplicationsPost(ctx *middleware.Context, form auth.NewAccessTokenForm) { | |||
| ctx.Data["Title"] = ctx.Tr("settings") | |||
| ctx.Data["PageIsUserSettings"] = true | |||
| ctx.Data["PageIsSettingsApplications"] = true | |||
| switch ctx.Query("type") { | |||
| @@ -437,11 +426,18 @@ func SettingsApplicationsPost(ctx *middleware.Context, form auth.NewAccessTokenF | |||
| func SettingsDelete(ctx *middleware.Context) { | |||
| ctx.Data["Title"] = ctx.Tr("settings") | |||
| ctx.Data["PageIsUserSettings"] = true | |||
| ctx.Data["PageIsSettingsDelete"] = true | |||
| 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 { | |||
| switch { | |||
| 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> | |||
| {{.i18n.Tr "your_profile"}}<!-- Your profile --> | |||
| </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> | |||
| {{.i18n.Tr "your_settings"}}<!-- Your settings --> | |||
| </a> | |||
| @@ -121,7 +121,7 @@ | |||
| {{if .IsAdmin}} | |||
| <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> | |||
| {{.i18n.Tr "admin_panel"}}<!-- Admin Panel --> | |||
| </a> | |||
| @@ -24,7 +24,7 @@ | |||
| <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}}> | |||
| </div> | |||
| <input class="fake"> | |||
| <input class="fake" type="password"> | |||
| <div class="inline field {{if .Err_Auth}}error{{end}}"> | |||
| <label for="auth_password">{{.i18n.Tr "password"}}</label> | |||
| <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 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 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> | |||
| {{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> | |||