Skip to content

Rework SSH key management UI to add GPG #1293

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Apr 26, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

* BREAKING
* Password reset URL changed from `/user/forget_password` to `/user/forgot_password`
* SSH keys management URL changed from `/user/settings/ssh` to `/user/settings/keys`


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

Expand Down
30 changes: 30 additions & 0 deletions models/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,36 @@ func (err ErrKeyNameAlreadyUsed) Error() string {
return fmt.Sprintf("public key already exists [owner_id: %d, name: %s]", err.OwnerID, err.Name)
}

// ErrGPGEmailNotFound represents a "ErrGPGEmailNotFound" kind of error.
type ErrGPGEmailNotFound struct {
Email string
}

// IsErrGPGEmailNotFound checks if an error is a ErrGPGEmailNotFound.
func IsErrGPGEmailNotFound(err error) bool {
_, ok := err.(ErrGPGEmailNotFound)
return ok
}

func (err ErrGPGEmailNotFound) Error() string {
return fmt.Sprintf("failed to found email or is not confirmed : %s", err.Email)
}

// ErrGPGKeyParsing represents a "ErrGPGKeyParsing" kind of error.
type ErrGPGKeyParsing struct {
ParseError error
}

// IsErrGPGKeyParsing checks if an error is a ErrGPGKeyParsing.
func IsErrGPGKeyParsing(err error) bool {
_, ok := err.(ErrGPGKeyParsing)
return ok
}

func (err ErrGPGKeyParsing) Error() string {
return fmt.Sprintf("failed to parse gpg key %s", err.ParseError.Error())
}

// ErrGPGKeyNotExist represents a "GPGKeyNotExist" kind of error.
type ErrGPGKeyNotExist struct {
ID int64
Expand Down
33 changes: 21 additions & 12 deletions models/gpg_key.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ func GetGPGKeyByID(keyID int64) (*GPGKey, error) {
func checkArmoredGPGKeyString(content string) (*openpgp.Entity, error) {
list, err := openpgp.ReadArmoredKeyRing(strings.NewReader(content))
if err != nil {
return nil, err
return nil, ErrGPGKeyParsing{err}
}
return list[0], nil
}
Expand Down Expand Up @@ -219,7 +219,7 @@ func parseGPGKey(ownerID int64, e *openpgp.Entity) (*GPGKey, error) {
}
}
if emails[n] == nil {
return nil, fmt.Errorf("Failed to found email or is not confirmed : %s", ident.UserId.Email)
return nil, ErrGPGEmailNotFound{ident.UserId.Email}
}
n++
}
Expand Down Expand Up @@ -400,17 +400,16 @@ func ParseCommitWithSignature(c *git.Commit) *CommitVerification {
}
}

//Generating hash of commit
hash, err := populateHash(sig.Hash, []byte(c.Signature.Payload))
if err != nil { //Skipping ailed to generate hash
log.Error(3, "PopulateHash: %v", err)
return &CommitVerification{
Verified: false,
Reason: "gpg.error.generate_hash",
}
}

for _, k := range keys {
//Generating hash of commit
hash, err := populateHash(sig.Hash, []byte(c.Signature.Payload))
if err != nil { //Skipping ailed to generate hash
log.Error(3, "PopulateHash: %v", err)
return &CommitVerification{
Verified: false,
Reason: "gpg.error.generate_hash",
}
}
//We get PK
if err := verifySign(sig, hash, k); err == nil {
return &CommitVerification{ //Everything is ok
Expand All @@ -422,6 +421,16 @@ func ParseCommitWithSignature(c *git.Commit) *CommitVerification {
}
//And test also SubsKey
for _, sk := range k.SubsKey {

//Generating hash of commit
hash, err := populateHash(sig.Hash, []byte(c.Signature.Payload))
if err != nil { //Skipping ailed to generate hash
log.Error(3, "PopulateHash: %v", err)
return &CommitVerification{
Verified: false,
Reason: "gpg.error.generate_hash",
}
}
if err := verifySign(sig, hash, sk); err == nil {
return &CommitVerification{ //Everything is ok
Verified: true,
Expand Down
7 changes: 4 additions & 3 deletions modules/auth/user_form.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,14 +163,15 @@ func (f *AddOpenIDForm) Validate(ctx *macaron.Context, errs binding.Errors) bind
return validate(errs, ctx.Data, f, ctx.Locale)
}

// AddSSHKeyForm form for adding SSH key
type AddSSHKeyForm struct {
// AddKeyForm form for adding SSH/GPG key
type AddKeyForm struct {
Type string `binding:"OmitEmpty"`
Title string `binding:"Required;MaxSize(50)"`
Content string `binding:"Required"`
}

// Validate validates the fields
func (f *AddSSHKeyForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
func (f *AddKeyForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
}

Expand Down
17 changes: 15 additions & 2 deletions options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ user_not_exist = The given user does not exist.
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.

invalid_ssh_key = Sorry, we're not able to verify your SSH key: %s
invalid_gpg_key = Sorry, we're not able to verify your GPG key: %s
unable_verify_ssh_key = Gitea cannot verify your SSH key, but we are assuming that it is valid, please double-check it.
auth_failed = Authentication failed: %v

Expand Down Expand Up @@ -285,7 +286,7 @@ form.name_pattern_not_allowed = Username pattern '%s' is not allowed.
profile = Profile
password = Password
avatar = Avatar
ssh_keys = SSH Keys
ssh_gpg_keys = SSH / GPG Keys
social = Social Accounts
applications = Applications
orgs = Organizations
Expand Down Expand Up @@ -349,20 +350,33 @@ keep_email_private_popup = Your email address will be hidden from other users if
openid_desc = Your OpenID addresses will let you delegate authentication to your provider of choice

manage_ssh_keys = Manage SSH Keys
manage_gpg_keys = Manage GPG Keys
add_key = Add Key
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.
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.
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.
gpg_helper = <strong>Don't know how?</strong> Check out GitHub's guide <a href="%s">about GPG</a>.
add_new_key = Add SSH Key
add_new_gpg_key = Add GPG Key
ssh_key_been_used = Public key content has already been used.
ssh_key_name_used = Public key with same name already exists.
gpg_key_id_used = Public GPG key with same id already exists.
gpg_key_email_not_found = The email attached to the GPG key couldn't be found or is not yet confirmed: %s
subkeys = Subkeys
key_id = Key ID
key_name = Key Name
key_content = Content
add_key_success = Your new SSH key '%s' has been added successfully!
add_gpg_key_success = Your new GPG key '%s' has been added successfully!
delete_key = Delete
ssh_key_deletion = SSH Key Deletion
gpg_key_deletion = GPG Key Deletion
ssh_key_deletion_desc = Delete this SSH key will disable all access using this SSH key for your account. Do you want to continue?
gpg_key_deletion_desc = Delete this GPG key will disable all commit verification sign with this GPG key. Do you want to continue?
ssh_key_deletion_success = SSH key has been deleted successfully!
gpg_key_deletion_success = GPG key has been deleted successfully!
add_on = Added on
valid_until = Valid until
last_used = Last used on
no_activity = No recent activity
key_state_desc = This key is used in last 7 days
Expand Down Expand Up @@ -1364,7 +1378,6 @@ mark_as_unread = Mark as unread
error.extract_sign = Failed to extract signature
error.generate_hash = Failed to generate hash of commit
error.no_committer_account = No account linked to committer email
error.no_gpg_keys_found = "Failed to retrieve publics keys of committer"
error.no_gpg_keys_found = "No known key found for this signature in database"
error.not_signed_commit = "Not a signed commit"
error.failed_retrieval_gpg_keys = "Failed to retrieve any key attached to the commiter account"
6 changes: 5 additions & 1 deletion public/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -1408,7 +1408,11 @@ $(document).ready(function () {
// Helpers.
$('.delete-button').click(function () {
var $this = $(this);
$('.delete.modal').modal({
var filter = "";
if ($this.attr("id")) {
filter += "#"+$this.attr("id")
}
$('.delete.modal'+filter).modal({
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure that nothing else on the site uses this?

Copy link
Member Author

@sapk sapk Apr 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have check that all matching .delete-button don't have id so that this change don't interact with it. I will double check and confirm it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I confirm !

closable: false,
onApprove: function () {
if ($this.data('type') == "form") {
Expand Down
2 changes: 1 addition & 1 deletion routers/repo/setting.go
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
8 changes: 4 additions & 4 deletions routers/routes/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
})

Expand Down
Loading