Skip to content

Commit 8371f94

Browse files
sapklunny
authored andcommitted
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
1 parent b7da5a6 commit 8371f94

File tree

14 files changed

+323
-139
lines changed

14 files changed

+323
-139
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
* BREAKING
66
* Password reset URL changed from `/user/forget_password` to `/user/forgot_password`
7+
* SSH keys management URL changed from `/user/settings/ssh` to `/user/settings/keys`
8+
79

810
## [1.1.0](https://github.com/go-gitea/gitea/releases/tag/v1.1.0) - 2017-03-09
911

models/error.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,36 @@ func (err ErrKeyNameAlreadyUsed) Error() string {
260260
return fmt.Sprintf("public key already exists [owner_id: %d, name: %s]", err.OwnerID, err.Name)
261261
}
262262

263+
// ErrGPGEmailNotFound represents a "ErrGPGEmailNotFound" kind of error.
264+
type ErrGPGEmailNotFound struct {
265+
Email string
266+
}
267+
268+
// IsErrGPGEmailNotFound checks if an error is a ErrGPGEmailNotFound.
269+
func IsErrGPGEmailNotFound(err error) bool {
270+
_, ok := err.(ErrGPGEmailNotFound)
271+
return ok
272+
}
273+
274+
func (err ErrGPGEmailNotFound) Error() string {
275+
return fmt.Sprintf("failed to found email or is not confirmed : %s", err.Email)
276+
}
277+
278+
// ErrGPGKeyParsing represents a "ErrGPGKeyParsing" kind of error.
279+
type ErrGPGKeyParsing struct {
280+
ParseError error
281+
}
282+
283+
// IsErrGPGKeyParsing checks if an error is a ErrGPGKeyParsing.
284+
func IsErrGPGKeyParsing(err error) bool {
285+
_, ok := err.(ErrGPGKeyParsing)
286+
return ok
287+
}
288+
289+
func (err ErrGPGKeyParsing) Error() string {
290+
return fmt.Sprintf("failed to parse gpg key %s", err.ParseError.Error())
291+
}
292+
263293
// ErrGPGKeyNotExist represents a "GPGKeyNotExist" kind of error.
264294
type ErrGPGKeyNotExist struct {
265295
ID int64

models/gpg_key.go

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ func GetGPGKeyByID(keyID int64) (*GPGKey, error) {
8989
func checkArmoredGPGKeyString(content string) (*openpgp.Entity, error) {
9090
list, err := openpgp.ReadArmoredKeyRing(strings.NewReader(content))
9191
if err != nil {
92-
return nil, err
92+
return nil, ErrGPGKeyParsing{err}
9393
}
9494
return list[0], nil
9595
}
@@ -219,7 +219,7 @@ func parseGPGKey(ownerID int64, e *openpgp.Entity) (*GPGKey, error) {
219219
}
220220
}
221221
if emails[n] == nil {
222-
return nil, fmt.Errorf("Failed to found email or is not confirmed : %s", ident.UserId.Email)
222+
return nil, ErrGPGEmailNotFound{ident.UserId.Email}
223223
}
224224
n++
225225
}
@@ -400,17 +400,16 @@ func ParseCommitWithSignature(c *git.Commit) *CommitVerification {
400400
}
401401
}
402402

403-
//Generating hash of commit
404-
hash, err := populateHash(sig.Hash, []byte(c.Signature.Payload))
405-
if err != nil { //Skipping ailed to generate hash
406-
log.Error(3, "PopulateHash: %v", err)
407-
return &CommitVerification{
408-
Verified: false,
409-
Reason: "gpg.error.generate_hash",
410-
}
411-
}
412-
413403
for _, k := range keys {
404+
//Generating hash of commit
405+
hash, err := populateHash(sig.Hash, []byte(c.Signature.Payload))
406+
if err != nil { //Skipping ailed to generate hash
407+
log.Error(3, "PopulateHash: %v", err)
408+
return &CommitVerification{
409+
Verified: false,
410+
Reason: "gpg.error.generate_hash",
411+
}
412+
}
414413
//We get PK
415414
if err := verifySign(sig, hash, k); err == nil {
416415
return &CommitVerification{ //Everything is ok
@@ -422,6 +421,16 @@ func ParseCommitWithSignature(c *git.Commit) *CommitVerification {
422421
}
423422
//And test also SubsKey
424423
for _, sk := range k.SubsKey {
424+
425+
//Generating hash of commit
426+
hash, err := populateHash(sig.Hash, []byte(c.Signature.Payload))
427+
if err != nil { //Skipping ailed to generate hash
428+
log.Error(3, "PopulateHash: %v", err)
429+
return &CommitVerification{
430+
Verified: false,
431+
Reason: "gpg.error.generate_hash",
432+
}
433+
}
425434
if err := verifySign(sig, hash, sk); err == nil {
426435
return &CommitVerification{ //Everything is ok
427436
Verified: true,

modules/auth/user_form.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -163,14 +163,15 @@ func (f *AddOpenIDForm) Validate(ctx *macaron.Context, errs binding.Errors) bind
163163
return validate(errs, ctx.Data, f, ctx.Locale)
164164
}
165165

166-
// AddSSHKeyForm form for adding SSH key
167-
type AddSSHKeyForm struct {
166+
// AddKeyForm form for adding SSH/GPG key
167+
type AddKeyForm struct {
168+
Type string `binding:"OmitEmpty"`
168169
Title string `binding:"Required;MaxSize(50)"`
169170
Content string `binding:"Required"`
170171
}
171172

172173
// Validate validates the fields
173-
func (f *AddSSHKeyForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
174+
func (f *AddKeyForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
174175
return validate(errs, ctx.Data, f, ctx.Locale)
175176
}
176177

options/locale/locale_en-US.ini

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@ user_not_exist = The given user does not exist.
258258
last_org_owner = Removing the last user from a owner team isn't allowed because there must always be at least one owner in any given organization.
259259
260260
invalid_ssh_key = Sorry, we're not able to verify your SSH key: %s
261+
invalid_gpg_key = Sorry, we're not able to verify your GPG key: %s
261262
unable_verify_ssh_key = Gitea cannot verify your SSH key, but we are assuming that it is valid, please double-check it.
262263
auth_failed = Authentication failed: %v
263264
@@ -285,7 +286,7 @@ form.name_pattern_not_allowed = Username pattern '%s' is not allowed.
285286
profile = Profile
286287
password = Password
287288
avatar = Avatar
288-
ssh_keys = SSH Keys
289+
ssh_gpg_keys = SSH / GPG Keys
289290
social = Social Accounts
290291
applications = Applications
291292
orgs = Organizations
@@ -349,20 +350,33 @@ keep_email_private_popup = Your email address will be hidden from other users if
349350
openid_desc = Your OpenID addresses will let you delegate authentication to your provider of choice
350351
351352
manage_ssh_keys = Manage SSH Keys
353+
manage_gpg_keys = Manage GPG Keys
352354
add_key = Add Key
353355
ssh_desc = This is a list of SSH keys associated with your account. Because these keys allow anyone using them to gain access to your repositories, it is highly important that you make sure you recognize them.
356+
gpg_desc = This is a list of GPG keys associated with your account. Because these keys allow verification of commit, it is highly important that you keep safe the corresponding private key.
354357
ssh_helper = <strong>Don't know how?</strong> Check out GitHub's guide to <a href="%s">create your own SSH keys</a> or solve <a href="%s">common problems</a> you might encounter using SSH.
358+
gpg_helper = <strong>Don't know how?</strong> Check out GitHub's guide <a href="%s">about GPG</a>.
355359
add_new_key = Add SSH Key
360+
add_new_gpg_key = Add GPG Key
356361
ssh_key_been_used = Public key content has already been used.
357362
ssh_key_name_used = Public key with same name already exists.
363+
gpg_key_id_used = Public GPG key with same id already exists.
364+
gpg_key_email_not_found = The email attached to the GPG key couldn't be found or is not yet confirmed: %s
365+
subkeys = Subkeys
366+
key_id = Key ID
358367
key_name = Key Name
359368
key_content = Content
360369
add_key_success = Your new SSH key '%s' has been added successfully!
370+
add_gpg_key_success = Your new GPG key '%s' has been added successfully!
361371
delete_key = Delete
362372
ssh_key_deletion = SSH Key Deletion
373+
gpg_key_deletion = GPG Key Deletion
363374
ssh_key_deletion_desc = Delete this SSH key will disable all access using this SSH key for your account. Do you want to continue?
375+
gpg_key_deletion_desc = Delete this GPG key will disable all commit verification sign with this GPG key. Do you want to continue?
364376
ssh_key_deletion_success = SSH key has been deleted successfully!
377+
gpg_key_deletion_success = GPG key has been deleted successfully!
365378
add_on = Added on
379+
valid_until = Valid until
366380
last_used = Last used on
367381
no_activity = No recent activity
368382
key_state_desc = This key is used in last 7 days
@@ -1364,7 +1378,6 @@ mark_as_unread = Mark as unread
13641378
error.extract_sign = Failed to extract signature
13651379
error.generate_hash = Failed to generate hash of commit
13661380
error.no_committer_account = No account linked to committer email
1367-
error.no_gpg_keys_found = "Failed to retrieve publics keys of committer"
13681381
error.no_gpg_keys_found = "No known key found for this signature in database"
13691382
error.not_signed_commit = "Not a signed commit"
13701383
error.failed_retrieval_gpg_keys = "Failed to retrieve any key attached to the commiter account"

public/js/index.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1408,7 +1408,11 @@ $(document).ready(function () {
14081408
// Helpers.
14091409
$('.delete-button').click(function () {
14101410
var $this = $(this);
1411-
$('.delete.modal').modal({
1411+
var filter = "";
1412+
if ($this.attr("id")) {
1413+
filter += "#"+$this.attr("id")
1414+
}
1415+
$('.delete.modal'+filter).modal({
14121416
closable: false,
14131417
onApprove: function () {
14141418
if ($this.data('type') == "form") {

routers/repo/setting.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -664,7 +664,7 @@ func DeployKeys(ctx *context.Context) {
664664
}
665665

666666
// DeployKeysPost response for adding a deploy key of a repository
667-
func DeployKeysPost(ctx *context.Context, form auth.AddSSHKeyForm) {
667+
func DeployKeysPost(ctx *context.Context, form auth.AddKeyForm) {
668668
ctx.Data["Title"] = ctx.Tr("repo.settings.deploy_keys")
669669
ctx.Data["PageIsSettingsKeys"] = true
670670

routers/routes/routes.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -214,9 +214,9 @@ func RegisterRoutes(m *macaron.Macaron) {
214214
})
215215
}
216216

217-
m.Combo("/ssh").Get(user.SettingsSSHKeys).
218-
Post(bindIgnErr(auth.AddSSHKeyForm{}), user.SettingsSSHKeysPost)
219-
m.Post("/ssh/delete", user.DeleteSSHKey)
217+
m.Combo("/keys").Get(user.SettingsKeys).
218+
Post(bindIgnErr(auth.AddKeyForm{}), user.SettingsKeysPost)
219+
m.Post("/keys/delete", user.DeleteKey)
220220
m.Combo("/applications").Get(user.SettingsApplications).
221221
Post(bindIgnErr(auth.NewAccessTokenForm{}), user.SettingsApplicationsPost)
222222
m.Post("/applications/delete", user.SettingsDeleteApplication)
@@ -438,7 +438,7 @@ func RegisterRoutes(m *macaron.Macaron) {
438438

439439
m.Group("/keys", func() {
440440
m.Combo("").Get(repo.DeployKeys).
441-
Post(bindIgnErr(auth.AddSSHKeyForm{}), repo.DeployKeysPost)
441+
Post(bindIgnErr(auth.AddKeyForm{}), repo.DeployKeysPost)
442442
m.Post("/delete", repo.DeleteDeployKey)
443443
})
444444

0 commit comments

Comments
 (0)