Rework SSH key management UI to add GPG (#1293)

* Rework SSH key management UI to add GPG

* Add more detail to gpg key display

* Update CHANGELOG.md

* Implement deletion UI

* Implement adding gpg UI

* Various fixes

- Fix duplicate entry in locale
- Re-generate hash before verification since they are consumed

* Add missing translation

* Split template

* Catch not found/verified email error
This commit is contained in:
Antoine GIRARD 2017-04-26 15:10:43 +02:00 committed by Lunny Xiao
parent b7da5a6cb7
commit 8371f94d06
14 changed files with 324 additions and 140 deletions

View file

@ -664,7 +664,7 @@ func DeployKeys(ctx *context.Context) {
}
// DeployKeysPost response for adding a deploy key of a repository
func DeployKeysPost(ctx *context.Context, form auth.AddSSHKeyForm) {
func DeployKeysPost(ctx *context.Context, form auth.AddKeyForm) {
ctx.Data["Title"] = ctx.Tr("repo.settings.deploy_keys")
ctx.Data["PageIsSettingsKeys"] = true

View file

@ -214,9 +214,9 @@ func RegisterRoutes(m *macaron.Macaron) {
})
}
m.Combo("/ssh").Get(user.SettingsSSHKeys).
Post(bindIgnErr(auth.AddSSHKeyForm{}), user.SettingsSSHKeysPost)
m.Post("/ssh/delete", user.DeleteSSHKey)
m.Combo("/keys").Get(user.SettingsKeys).
Post(bindIgnErr(auth.AddKeyForm{}), user.SettingsKeysPost)
m.Post("/keys/delete", user.DeleteKey)
m.Combo("/applications").Get(user.SettingsApplications).
Post(bindIgnErr(auth.NewAccessTokenForm{}), user.SettingsApplicationsPost)
m.Post("/applications/delete", user.SettingsDeleteApplication)
@ -438,7 +438,7 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Group("/keys", func() {
m.Combo("").Get(repo.DeployKeys).
Post(bindIgnErr(auth.AddSSHKeyForm{}), repo.DeployKeysPost)
Post(bindIgnErr(auth.AddKeyForm{}), repo.DeployKeysPost)
m.Post("/delete", repo.DeleteDeployKey)
})

View file

@ -32,7 +32,7 @@ const (
tplSettingsAvatar base.TplName = "user/settings/avatar"
tplSettingsPassword base.TplName = "user/settings/password"
tplSettingsEmails base.TplName = "user/settings/email"
tplSettingsSSHKeys base.TplName = "user/settings/sshkeys"
tplSettingsKeys base.TplName = "user/settings/keys"
tplSettingsSocial base.TplName = "user/settings/social"
tplSettingsApplications base.TplName = "user/settings/applications"
tplSettingsTwofa base.TplName = "user/settings/twofa"
@ -320,10 +320,10 @@ func DeleteEmail(ctx *context.Context) {
})
}
// SettingsSSHKeys render user's SSH public keys page
func SettingsSSHKeys(ctx *context.Context) {
// SettingsKeys render user's SSH/GPG public keys page
func SettingsKeys(ctx *context.Context) {
ctx.Data["Title"] = ctx.Tr("settings")
ctx.Data["PageIsSettingsSSHKeys"] = true
ctx.Data["PageIsSettingsKeys"] = true
keys, err := models.ListPublicKeys(ctx.User.ID)
if err != nil {
@ -332,13 +332,20 @@ func SettingsSSHKeys(ctx *context.Context) {
}
ctx.Data["Keys"] = keys
ctx.HTML(200, tplSettingsSSHKeys)
gpgkeys, err := models.ListGPGKeys(ctx.User.ID)
if err != nil {
ctx.Handle(500, "ListGPGKeys", err)
return
}
ctx.Data["GPGKeys"] = gpgkeys
ctx.HTML(200, tplSettingsKeys)
}
// SettingsSSHKeysPost response for change user's SSH keys
func SettingsSSHKeysPost(ctx *context.Context, form auth.AddSSHKeyForm) {
// SettingsKeysPost response for change user's SSH/GPG keys
func SettingsKeysPost(ctx *context.Context, form auth.AddKeyForm) {
ctx.Data["Title"] = ctx.Tr("settings")
ctx.Data["PageIsSettingsSSHKeys"] = true
ctx.Data["PageIsSettingsKeys"] = true
keys, err := models.ListPublicKeys(ctx.User.ID)
if err != nil {
@ -347,51 +354,97 @@ func SettingsSSHKeysPost(ctx *context.Context, form auth.AddSSHKeyForm) {
}
ctx.Data["Keys"] = keys
gpgkeys, err := models.ListGPGKeys(ctx.User.ID)
if err != nil {
ctx.Handle(500, "ListGPGKeys", err)
return
}
ctx.Data["GPGKeys"] = gpgkeys
if ctx.HasError() {
ctx.HTML(200, tplSettingsSSHKeys)
ctx.HTML(200, tplSettingsKeys)
return
}
content, err := models.CheckPublicKeyString(form.Content)
if err != nil {
if models.IsErrKeyUnableVerify(err) {
ctx.Flash.Info(ctx.Tr("form.unable_verify_ssh_key"))
} else {
ctx.Flash.Error(ctx.Tr("form.invalid_ssh_key", err.Error()))
ctx.Redirect(setting.AppSubURL + "/user/settings/ssh")
switch form.Type {
case "gpg":
key, err := models.AddGPGKey(ctx.User.ID, form.Content)
if err != nil {
ctx.Data["HasGPGError"] = true
switch {
case models.IsErrGPGKeyParsing(err):
ctx.Flash.Error(ctx.Tr("form.invalid_gpg_key", err.Error()))
ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
case models.IsErrGPGKeyIDAlreadyUsed(err):
ctx.Data["Err_Content"] = true
ctx.RenderWithErr(ctx.Tr("settings.gpg_key_id_used"), tplSettingsKeys, &form)
case models.IsErrGPGEmailNotFound(err):
ctx.Data["Err_Content"] = true
ctx.RenderWithErr(ctx.Tr("settings.gpg_key_email_not_found", err.(models.ErrGPGEmailNotFound).Email), tplSettingsKeys, &form)
default:
ctx.Handle(500, "AddPublicKey", err)
}
return
}
}
if _, err = models.AddPublicKey(ctx.User.ID, form.Title, content); err != nil {
ctx.Data["HasError"] = true
switch {
case models.IsErrKeyAlreadyExist(err):
ctx.Data["Err_Content"] = true
ctx.RenderWithErr(ctx.Tr("settings.ssh_key_been_used"), tplSettingsSSHKeys, &form)
case models.IsErrKeyNameAlreadyUsed(err):
ctx.Data["Err_Title"] = true
ctx.RenderWithErr(ctx.Tr("settings.ssh_key_name_used"), tplSettingsSSHKeys, &form)
default:
ctx.Handle(500, "AddPublicKey", err)
ctx.Flash.Success(ctx.Tr("settings.add_gpg_key_success", key.KeyID))
ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
case "ssh":
content, err := models.CheckPublicKeyString(form.Content)
if err != nil {
if models.IsErrKeyUnableVerify(err) {
ctx.Flash.Info(ctx.Tr("form.unable_verify_ssh_key"))
} else {
ctx.Flash.Error(ctx.Tr("form.invalid_ssh_key", err.Error()))
ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
return
}
}
return
if _, err = models.AddPublicKey(ctx.User.ID, form.Title, content); err != nil {
ctx.Data["HasSSHError"] = true
switch {
case models.IsErrKeyAlreadyExist(err):
ctx.Data["Err_Content"] = true
ctx.RenderWithErr(ctx.Tr("settings.ssh_key_been_used"), tplSettingsKeys, &form)
case models.IsErrKeyNameAlreadyUsed(err):
ctx.Data["Err_Title"] = true
ctx.RenderWithErr(ctx.Tr("settings.ssh_key_name_used"), tplSettingsKeys, &form)
default:
ctx.Handle(500, "AddPublicKey", err)
}
return
}
ctx.Flash.Success(ctx.Tr("settings.add_key_success", form.Title))
ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
default:
ctx.Flash.Warning("Function not implemented")
ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
}
ctx.Flash.Success(ctx.Tr("settings.add_key_success", form.Title))
ctx.Redirect(setting.AppSubURL + "/user/settings/ssh")
}
// DeleteSSHKey response for delete user's SSH key
func DeleteSSHKey(ctx *context.Context) {
if err := models.DeletePublicKey(ctx.User, ctx.QueryInt64("id")); err != nil {
ctx.Flash.Error("DeletePublicKey: " + err.Error())
} else {
ctx.Flash.Success(ctx.Tr("settings.ssh_key_deletion_success"))
}
// DeleteKey response for delete user's SSH/GPG key
func DeleteKey(ctx *context.Context) {
switch ctx.Query("type") {
case "gpg":
if err := models.DeleteGPGKey(ctx.User, ctx.QueryInt64("id")); err != nil {
ctx.Flash.Error("DeleteGPGKey: " + err.Error())
} else {
ctx.Flash.Success(ctx.Tr("settings.gpg_key_deletion_success"))
}
case "ssh":
if err := models.DeletePublicKey(ctx.User, ctx.QueryInt64("id")); err != nil {
ctx.Flash.Error("DeletePublicKey: " + err.Error())
} else {
ctx.Flash.Success(ctx.Tr("settings.ssh_key_deletion_success"))
}
default:
ctx.Flash.Warning("Function not implemented")
ctx.Redirect(setting.AppSubURL + "/user/settings/keys")
}
ctx.JSON(200, map[string]interface{}{
"redirect": setting.AppSubURL + "/user/settings/ssh",
"redirect": setting.AppSubURL + "/user/settings/keys",
})
}