new delete account UI and password confirmation

This commit is contained in:
Unknwon 2015-08-19 02:49:44 +08:00
parent 81b8427438
commit 2493454587
14 changed files with 137 additions and 52 deletions

View File

@ -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")

View File

@ -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,

View File

@ -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())

File diff suppressed because one or more lines are too long

View File

@ -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")

View File

@ -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;

4
public/less/_user.less Normal file
View File

@ -0,0 +1,4 @@
.user {
padding-top: 15px;
padding-bottom: @footer-margin * 3;
}

View File

@ -5,4 +5,5 @@
@import "_install"; @import "_install";
@import "_form"; @import "_form";
@import "_repository"; @import "_repository";
@import "_user";
@import "_admin"; @import "_admin";

View File

@ -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):

View File

@ -1 +1 @@
0.6.5.0818 Beta 0.6.5.0819 Beta

View File

@ -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>

View File

@ -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}}">

View File

@ -1,35 +1,51 @@
{{template "ng/base/head" .}} {{template "base/head" .}}
{{template "ng/base/header" .}} <div class="user settings">
<div id="setting-wrapper" class="main-wrapper"> <div class="ui container">
<div id="user-profile-setting" class="container clear"> <div class="ui grid">
{{template "user/settings/nav" .}} {{template "user/settings/navbar" .}}
<div class="grid-4-5 left"> <div class="twelve wide column content">
<div class="setting-content"> {{template "base/alert" .}}
{{template "ng/base/alert" .}} <h4 class="ui top attached warning header">
<div id="setting-content"> {{.i18n.Tr "settings.delete_account"}}
<div id="user-profile-setting-content" class="panel panel-warning panel-radius"> </h4>
<p class="panel-header"><strong>{{.i18n.Tr "settings.delete_account"}}</strong></p> <div class="ui attached warning segment">
<div class="panel-body panel-content"> <div class="ui red message">
<span class="alert alert-red alert-radius block"><i class="octicon octicon-alert"></i>{{.i18n.Tr "settings.delete_prompt" | Str2html}}</span> <p>{{.i18n.Tr "settings.delete_prompt" | Str2html}}</p>
<form id="delete-account-form" action="{{AppSubUrl}}/user/settings/delete" method="post"> </div>
<form class="ui form" id="delete-form" action="{{.Link}}" method="post">
{{.CsrfTokenHtml}} {{.CsrfTokenHtml}}
<p class="field"> <input class="fake" type="password">
<span class="form-label"></span> <div class="inline required field {{if .Err_Password}}error{{end}}">
<button class="btn btn-red btn-large btn-radius" id="delete-account-btn" href="#delete-account-modal">{{.i18n.Tr "settings.confirm_delete_account"}}</button> <label for="password">{{.i18n.Tr "password"}}</label>
</p> <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> </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> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
{{template "ng/base/footer" .}}
<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 "base/footer" .}}

View File

@ -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>