Finish method for having multiple emails/user.

All basics are implemented. Missing are the right (localized) strings
and the page markup could have a look at by a frontend guy.
release/v1.15
Peter 2014-12-17 17:42:54 +02:00
parent f34b04cfc0
commit b033f2f535
5 changed files with 178 additions and 0 deletions

View File

@ -241,6 +241,8 @@ func runWeb(*cli.Context) {
m.Get("", user.Settings) m.Get("", user.Settings)
m.Post("", bindIgnErr(auth.UpdateProfileForm{}), user.SettingsPost) m.Post("", bindIgnErr(auth.UpdateProfileForm{}), user.SettingsPost)
m.Post("/avatar", binding.MultipartForm(auth.UploadAvatarForm{}), user.SettingsAvatar) m.Post("/avatar", binding.MultipartForm(auth.UploadAvatarForm{}), user.SettingsAvatar)
m.Get("/email", user.SettingsEmails)
m.Post("/email", bindIgnErr(auth.AddEmailForm{}), user.SettingsEmailPost)
m.Get("/password", user.SettingsPassword) m.Get("/password", user.SettingsPassword)
m.Post("/password", bindIgnErr(auth.ChangePasswordForm{}), user.SettingsPasswordPost) m.Post("/password", bindIgnErr(auth.ChangePasswordForm{}), user.SettingsPasswordPost)
m.Get("/ssh", user.SettingsSSHKeys) m.Get("/ssh", user.SettingsSSHKeys)
@ -252,6 +254,7 @@ func runWeb(*cli.Context) {
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)
m.Any("/activate_email", user.ActivateEmail)
m.Get("/email2user", user.Email2User) m.Get("/email2user", user.Email2User)
m.Get("/forget_password", user.ForgotPasswd) m.Get("/forget_password", user.ForgotPasswd)
m.Post("/forget_password", user.ForgotPasswdPost) m.Post("/forget_password", user.ForgotPasswdPost)

View File

@ -97,6 +97,14 @@ func (f *UploadAvatarForm) Validate(ctx *macaron.Context, errs binding.Errors) b
return validate(errs, ctx.Data, f, ctx.Locale) return validate(errs, ctx.Data, f, ctx.Locale)
} }
type AddEmailForm struct {
Email string `form:"email" binding:"Required;Email;MaxSize(50)"`
}
func (f *AddEmailForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}
type ChangePasswordForm struct { type ChangePasswordForm struct {
OldPassword string `form:"old_password" binding:"Required;MinSize(6);MaxSize(255)"` OldPassword string `form:"old_password" binding:"Required;MinSize(6);MaxSize(255)"`
Password string `form:"password" binding:"Required;MinSize(6);MaxSize(255)"` Password string `form:"password" binding:"Required;MinSize(6);MaxSize(255)"`

View File

@ -14,6 +14,7 @@ import (
"github.com/gogits/gogs/modules/auth" "github.com/gogits/gogs/modules/auth"
"github.com/gogits/gogs/modules/base" "github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/log" "github.com/gogits/gogs/modules/log"
"github.com/gogits/gogs/modules/mailer"
"github.com/gogits/gogs/modules/middleware" "github.com/gogits/gogs/modules/middleware"
"github.com/gogits/gogs/modules/setting" "github.com/gogits/gogs/modules/setting"
) )
@ -21,6 +22,7 @@ import (
const ( const (
SETTINGS_PROFILE base.TplName = "user/settings/profile" SETTINGS_PROFILE base.TplName = "user/settings/profile"
SETTINGS_PASSWORD base.TplName = "user/settings/password" SETTINGS_PASSWORD base.TplName = "user/settings/password"
SETTINGS_EMAILS base.TplName = "user/settings/email"
SETTINGS_SSH_KEYS base.TplName = "user/settings/sshkeys" SETTINGS_SSH_KEYS base.TplName = "user/settings/sshkeys"
SETTINGS_SOCIAL base.TplName = "user/settings/social" SETTINGS_SOCIAL base.TplName = "user/settings/social"
SETTINGS_APPLICATIONS base.TplName = "user/settings/applications" SETTINGS_APPLICATIONS base.TplName = "user/settings/applications"
@ -126,6 +128,112 @@ func SettingsAvatar(ctx *middleware.Context, form auth.UploadAvatarForm) {
ctx.Flash.Success(ctx.Tr("settings.update_avatar_success")) ctx.Flash.Success(ctx.Tr("settings.update_avatar_success"))
} }
func SettingsEmails(ctx *middleware.Context) {
ctx.Data["Title"] = ctx.Tr("settings")
ctx.Data["PageIsUserSettings"] = true
ctx.Data["PageIsSettingsEmails"] = true
var err error
ctx.Data["Emails"], err = models.GetEmailAddresses(ctx.User.Id)
if err != nil {
ctx.Handle(500, "email.GetEmailAddresses", err)
return
}
ctx.HTML(200, SETTINGS_EMAILS)
}
func SettingsEmailPost(ctx *middleware.Context, form auth.AddEmailForm) {
ctx.Data["Title"] = ctx.Tr("settings")
ctx.Data["PageIsUserSettings"] = true
ctx.Data["PageIsSettingsEmails"] = true
var err error
ctx.Data["Emails"], err = models.GetEmailAddresses(ctx.User.Id)
if err != nil {
ctx.Handle(500, "email.GetEmailAddresses", err)
return
}
// Delete Email address.
if ctx.Query("_method") == "DELETE" {
id := com.StrTo(ctx.Query("id")).MustInt64()
if id <= 0 {
return
}
if err = models.DeleteEmailAddress(&models.EmailAddress{Id: id}); err != nil {
ctx.Handle(500, "DeleteEmail", err)
} else {
log.Trace("Email address deleted: %s", ctx.User.Name)
ctx.Redirect(setting.AppSubUrl + "/user/settings/email")
}
return
}
// Make emailaddress primary.
if ctx.Query("_method") == "PRIMARY" {
id := com.StrTo(ctx.Query("id")).MustInt64()
if id <= 0 {
return
}
if err = models.MakeEmailPrimary(&models.EmailAddress{Id: id}); err != nil {
ctx.Handle(500, "MakeEmailPrimary", err)
} else {
log.Trace("Email made primary: %s", ctx.User.Name)
ctx.Redirect(setting.AppSubUrl + "/user/settings/email")
}
return
}
// Add Email address.
if ctx.Req.Method == "POST" {
if ctx.HasError() {
ctx.HTML(200, SETTINGS_EMAILS)
return
}
cleanEmail := strings.Replace(form.Email, "\n", "", -1)
e := &models.EmailAddress{
OwnerId: ctx.User.Id,
Email: cleanEmail,
IsActivated: !setting.Service.RegisterEmailConfirm,
}
if err := models.AddEmailAddress(e); err != nil {
if err == models.ErrEmailAlreadyUsed {
ctx.RenderWithErr(ctx.Tr("form.email_has_been_used"), SETTINGS_EMAILS, &form)
return
}
ctx.Handle(500, "email.AddEmailAddress", err)
return
} else {
// Send confirmation e-mail
if setting.Service.RegisterEmailConfirm {
mailer.SendActivateEmail(ctx.Render, ctx.User, e)
if err := ctx.Cache.Put("MailResendLimit_"+ctx.User.LowerName, ctx.User.LowerName, 180); err != nil {
log.Error(4, "Set cache(MailResendLimit) fail: %v", err)
}
ctx.Flash.Success(ctx.Tr("settings.add_email_success_confirmation_email_sent"))
} else {
ctx.Flash.Success(ctx.Tr("settings.add_email_success"))
}
log.Trace("Email address added: %s", e.Email)
ctx.Redirect(setting.AppSubUrl + "/user/settings/email")
return
}
}
ctx.HTML(200, SETTINGS_EMAILS)
}
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["PageIsUserSettings"] = true

View File

@ -0,0 +1,58 @@
{{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="user-email-setting-content">
<div id="user-email-panel" class="panel panel-radius">
<div class="panel-header">
<strong>{{.i18n.Tr "settings.manage_emails"}}</strong>
</div>
<ul class="panel-body setting-list">
<li>{{.i18n.Tr "settings.email_desc"}}</li>
{{range .Emails}}
<li class="email clear">
<div class="email-content left">
<p><strong>{{.Email}}</strong></p>
</div>
{{if not .IsPrimary}}
{{if .IsActivated}}
<form action="{{AppSubUrl}}/user/settings/email" method="post">
{{$.CsrfTokenHtml}}
<input name="_method" type="hidden" value="PRIMARY">
<input name="id" type="hidden" value="{{.Id}}">
<button class="right email-btn btn btn-green btn-radius btn-small">{{$.i18n.Tr "settings.primary_email"}}</button>
</form>
{{end}}
<form action="{{AppSubUrl}}/user/settings/email" method="post">
{{$.CsrfTokenHtml}}
<input name="_method" type="hidden" value="DELETE">
<input name="id" type="hidden" value="{{.Id}}">
<button class="right email-btn btn btn-red btn-radius btn-small">{{$.i18n.Tr "settings.delete_email"}}</button>
</form>
{{end}}
</li>
{{end}}
<form action="{{AppSubUrl}}/user/settings/email" method="post">
{{.CsrfTokenHtml}}
<p class="panel-header"><strong>{{.i18n.Tr "settings.add_new_email"}}</strong></p>
<p class="field">
<label class="req" for="email">{{.i18n.Tr "settings.email"}}</label>
<input class="ipt ipt-radius" id="email" name="email" type="text" required />
</p>
<p class="field">
<label></label>
<button class="btn btn-green btn-radius" id="email-add-btn">{{.i18n.Tr "settings.add_email"}}</button>
</p>
</form>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
{{template "ng/base/footer" .}}

View File

@ -4,6 +4,7 @@
<ul class="menu menu-vertical switching-list grid-1-5 left"> <ul class="menu menu-vertical switching-list grid-1-5 left">
<li {{if .PageIsSettingsProfile}}class="current"{{end}}><a href="{{AppSubUrl}}/user/settings">{{.i18n.Tr "settings.profile"}}</a></li> <li {{if .PageIsSettingsProfile}}class="current"{{end}}><a href="{{AppSubUrl}}/user/settings">{{.i18n.Tr "settings.profile"}}</a></li>
<li {{if .PageIsSettingsPassword}}class="current"{{end}}><a href="{{AppSubUrl}}/user/settings/password">{{.i18n.Tr "settings.password"}}</a></li> <li {{if .PageIsSettingsPassword}}class="current"{{end}}><a href="{{AppSubUrl}}/user/settings/password">{{.i18n.Tr "settings.password"}}</a></li>
<li {{if .PageIsSettingsEmail}}class="current"{{end}}><a href="{{AppSubUrl}}/user/settings/email">{{.i18n.Tr "settings.emails"}}</a></li>
<li {{if .PageIsSettingsSSHKeys}}class="current"{{end}}><a href="{{AppSubUrl}}/user/settings/ssh">{{.i18n.Tr "settings.ssh_keys"}}</a></li> <li {{if .PageIsSettingsSSHKeys}}class="current"{{end}}><a href="{{AppSubUrl}}/user/settings/ssh">{{.i18n.Tr "settings.ssh_keys"}}</a></li>
<li {{if .PageIsSettingsSocial}}class="current"{{end}}><a href="{{AppSubUrl}}/user/settings/social">{{.i18n.Tr "settings.social"}}</a></li> <li {{if .PageIsSettingsSocial}}class="current"{{end}}><a href="{{AppSubUrl}}/user/settings/social">{{.i18n.Tr "settings.social"}}</a></li>
<li {{if .PageIsSettingsApplications}}class="current"{{end}}><a href="{{AppSubUrl}}/user/settings/applications">{{.i18n.Tr "settings.applications"}}</a></li> <li {{if .PageIsSettingsApplications}}class="current"{{end}}><a href="{{AppSubUrl}}/user/settings/applications">{{.i18n.Tr "settings.applications"}}</a></li>