mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 08:30:25 +08:00 
			
		
		
		
	Only check at least one email gpg key (#2266)
* Only require one email (possibly not yet validated) * Update message error and check validation of commit * Add integrations tests * Complete integration for import * Add pre-check/optimization * Add some test (not finished) * Finish * Fix fixtures * Fix typo * Don't guess key ID
This commit is contained in:
		
				
					committed by
					
						
						Lunny Xiao
					
				
			
			
				
	
			
			
			
						parent
						
							5f4210a9b0
						
					
				
				
					commit
					7c417bbb0d
				
			@@ -4,9 +4,7 @@
 | 
			
		||||
 | 
			
		||||
package models
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
)
 | 
			
		||||
import "fmt"
 | 
			
		||||
 | 
			
		||||
// ErrNameReserved represents a "reserved name" error.
 | 
			
		||||
type ErrNameReserved struct {
 | 
			
		||||
@@ -260,19 +258,19 @@ 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
 | 
			
		||||
// ErrGPGNoEmailFound represents a "ErrGPGNoEmailFound" kind of error.
 | 
			
		||||
type ErrGPGNoEmailFound struct {
 | 
			
		||||
	FailedEmails []string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsErrGPGEmailNotFound checks if an error is a ErrGPGEmailNotFound.
 | 
			
		||||
func IsErrGPGEmailNotFound(err error) bool {
 | 
			
		||||
	_, ok := err.(ErrGPGEmailNotFound)
 | 
			
		||||
// IsErrGPGNoEmailFound checks if an error is a ErrGPGNoEmailFound.
 | 
			
		||||
func IsErrGPGNoEmailFound(err error) bool {
 | 
			
		||||
	_, ok := err.(ErrGPGNoEmailFound)
 | 
			
		||||
	return ok
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (err ErrGPGEmailNotFound) Error() string {
 | 
			
		||||
	return fmt.Sprintf("failed to found email or is not confirmed : %s", err.Email)
 | 
			
		||||
func (err ErrGPGNoEmailFound) Error() string {
 | 
			
		||||
	return fmt.Sprintf("none of the emails attached to the GPG key could be found: %v", err.FailedEmails)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrGPGKeyParsing represents a "ErrGPGKeyParsing" kind of error.
 | 
			
		||||
 
 | 
			
		||||
@@ -176,3 +176,15 @@
 | 
			
		||||
  lower_name: repo15
 | 
			
		||||
  name: repo15
 | 
			
		||||
  is_bare: true
 | 
			
		||||
 | 
			
		||||
-
 | 
			
		||||
  id: 16
 | 
			
		||||
  owner_id: 2
 | 
			
		||||
  lower_name: repo16
 | 
			
		||||
  name: repo16
 | 
			
		||||
  is_private: false
 | 
			
		||||
  num_issues: 0
 | 
			
		||||
  num_closed_issues: 0
 | 
			
		||||
  num_pulls: 0
 | 
			
		||||
  num_closed_pulls: 0
 | 
			
		||||
  num_watches: 0
 | 
			
		||||
 
 | 
			
		||||
@@ -26,7 +26,7 @@
 | 
			
		||||
  is_admin: false
 | 
			
		||||
  avatar: avatar2
 | 
			
		||||
  avatar_email: user2@example.com
 | 
			
		||||
  num_repos: 3
 | 
			
		||||
  num_repos: 4
 | 
			
		||||
  num_stars: 2
 | 
			
		||||
  num_followers: 2
 | 
			
		||||
  num_following: 1
 | 
			
		||||
 
 | 
			
		||||
@@ -208,21 +208,27 @@ func parseGPGKey(ownerID int64, e *openpgp.Entity) (*GPGKey, error) {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	emails := make([]*EmailAddress, len(e.Identities))
 | 
			
		||||
	n := 0
 | 
			
		||||
 | 
			
		||||
	emails := make([]*EmailAddress, 0, len(e.Identities))
 | 
			
		||||
	for _, ident := range e.Identities {
 | 
			
		||||
		email := strings.ToLower(strings.TrimSpace(ident.UserId.Email))
 | 
			
		||||
		for _, e := range userEmails {
 | 
			
		||||
			if e.Email == email && e.IsActivated {
 | 
			
		||||
				emails[n] = e
 | 
			
		||||
			if e.Email == email {
 | 
			
		||||
				emails = append(emails, e)
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if emails[n] == nil {
 | 
			
		||||
			return nil, ErrGPGEmailNotFound{ident.UserId.Email}
 | 
			
		||||
		}
 | 
			
		||||
		n++
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	//In the case no email as been found
 | 
			
		||||
	if len(emails) == 0 {
 | 
			
		||||
		failedEmails := make([]string, 0, len(e.Identities))
 | 
			
		||||
		for _, ident := range e.Identities {
 | 
			
		||||
			failedEmails = append(failedEmails, ident.UserId.Email)
 | 
			
		||||
		}
 | 
			
		||||
		return nil, ErrGPGNoEmailFound{failedEmails}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	content, err := base64EncPubKey(pubkey)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
@@ -380,8 +386,8 @@ func ParseCommitWithSignature(c *git.Commit) *CommitVerification {
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		//Find Committer account
 | 
			
		||||
		committer, err := GetUserByEmail(c.Committer.Email)
 | 
			
		||||
		if err != nil { //Skipping not user for commiter
 | 
			
		||||
		committer, err := GetUserByEmail(c.Committer.Email) //This find the user by primary email or activated email so commit will not be valid if email is not
 | 
			
		||||
		if err != nil {                                     //Skipping not user for commiter
 | 
			
		||||
			log.Error(3, "NoCommitterAccount: %v", err)
 | 
			
		||||
			return &CommitVerification{
 | 
			
		||||
				Verified: false,
 | 
			
		||||
@@ -399,6 +405,18 @@ func ParseCommitWithSignature(c *git.Commit) *CommitVerification {
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for _, k := range keys {
 | 
			
		||||
			//Pre-check (& optimization) that emails attached to key can be attached to the commiter email and can validate
 | 
			
		||||
			canValidate := false
 | 
			
		||||
			for _, e := range k.Emails {
 | 
			
		||||
				if e.IsActivated && e.Email == c.Committer.Email {
 | 
			
		||||
					canValidate = true
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if !canValidate {
 | 
			
		||||
				continue //Skip this key
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			//Generating hash of commit
 | 
			
		||||
			hash, err := populateHash(sig.Hash, []byte(c.Signature.Payload))
 | 
			
		||||
			if err != nil { //Skipping ailed to generate hash
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user