2019-12-15 14:06:31 +03:00
// Copyright 2019 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package models
import (
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
)
// SignMerge determines if we should sign a PR merge commit to the base repository
2020-01-15 11:32:57 +03:00
func ( pr * PullRequest ) SignMerge ( u * User , tmpBasePath , baseCommit , headCommit string ) ( bool , string , error ) {
2020-03-03 01:31:55 +03:00
if err := pr . LoadBaseRepo ( ) ; err != nil {
2019-12-15 14:06:31 +03:00
log . Error ( "Unable to get Base Repo for pull request" )
2020-01-15 11:32:57 +03:00
return false , "" , err
2019-12-15 14:06:31 +03:00
}
repo := pr . BaseRepo
signingKey := signingKey ( repo . RepoPath ( ) )
if signingKey == "" {
2020-01-15 11:32:57 +03:00
return false , "" , & ErrWontSign { noKey }
2019-12-15 14:06:31 +03:00
}
rules := signingModeFromStrings ( setting . Repository . Signing . Merges )
var gitRepo * git . Repository
var err error
for _ , rule := range rules {
switch rule {
case never :
2020-01-15 11:32:57 +03:00
return false , "" , & ErrWontSign { never }
2019-12-15 14:06:31 +03:00
case always :
break
case pubkey :
2020-01-24 22:00:29 +03:00
keys , err := ListGPGKeys ( u . ID , ListOptions { } )
2020-01-15 11:32:57 +03:00
if err != nil {
return false , "" , err
}
if len ( keys ) == 0 {
return false , "" , & ErrWontSign { pubkey }
2019-12-15 14:06:31 +03:00
}
case twofa :
2020-01-15 11:32:57 +03:00
twofaModel , err := GetTwoFactorByUID ( u . ID )
2020-01-27 02:44:12 +03:00
if err != nil && ! IsErrTwoFactorNotEnrolled ( err ) {
2020-01-15 11:32:57 +03:00
return false , "" , err
}
if twofaModel == nil {
return false , "" , & ErrWontSign { twofa }
2019-12-15 14:06:31 +03:00
}
case approved :
protectedBranch , err := GetProtectedBranchBy ( repo . ID , pr . BaseBranch )
2020-01-15 11:32:57 +03:00
if err != nil {
return false , "" , err
}
if protectedBranch == nil {
return false , "" , & ErrWontSign { approved }
2019-12-15 14:06:31 +03:00
}
if protectedBranch . GetGrantedApprovalsCount ( pr ) < 1 {
2020-01-15 11:32:57 +03:00
return false , "" , & ErrWontSign { approved }
2019-12-15 14:06:31 +03:00
}
case baseSigned :
if gitRepo == nil {
gitRepo , err = git . OpenRepository ( tmpBasePath )
if err != nil {
2020-01-15 11:32:57 +03:00
return false , "" , err
2019-12-15 14:06:31 +03:00
}
defer gitRepo . Close ( )
}
commit , err := gitRepo . GetCommit ( baseCommit )
if err != nil {
2020-01-15 11:32:57 +03:00
return false , "" , err
2019-12-15 14:06:31 +03:00
}
verification := ParseCommitWithSignature ( commit )
if ! verification . Verified {
2020-01-15 11:32:57 +03:00
return false , "" , & ErrWontSign { baseSigned }
2019-12-15 14:06:31 +03:00
}
case headSigned :
if gitRepo == nil {
gitRepo , err = git . OpenRepository ( tmpBasePath )
if err != nil {
2020-01-15 11:32:57 +03:00
return false , "" , err
2019-12-15 14:06:31 +03:00
}
defer gitRepo . Close ( )
}
commit , err := gitRepo . GetCommit ( headCommit )
if err != nil {
2020-01-15 11:32:57 +03:00
return false , "" , err
2019-12-15 14:06:31 +03:00
}
verification := ParseCommitWithSignature ( commit )
if ! verification . Verified {
2020-01-15 11:32:57 +03:00
return false , "" , & ErrWontSign { headSigned }
2019-12-15 14:06:31 +03:00
}
case commitsSigned :
if gitRepo == nil {
gitRepo , err = git . OpenRepository ( tmpBasePath )
if err != nil {
2020-01-15 11:32:57 +03:00
return false , "" , err
2019-12-15 14:06:31 +03:00
}
defer gitRepo . Close ( )
}
commit , err := gitRepo . GetCommit ( headCommit )
if err != nil {
2020-01-15 11:32:57 +03:00
return false , "" , err
2019-12-15 14:06:31 +03:00
}
verification := ParseCommitWithSignature ( commit )
if ! verification . Verified {
2020-01-15 11:32:57 +03:00
return false , "" , & ErrWontSign { commitsSigned }
2019-12-15 14:06:31 +03:00
}
// need to work out merge-base
mergeBaseCommit , _ , err := gitRepo . GetMergeBase ( "" , baseCommit , headCommit )
if err != nil {
2020-01-15 11:32:57 +03:00
return false , "" , err
2019-12-15 14:06:31 +03:00
}
commitList , err := commit . CommitsBeforeUntil ( mergeBaseCommit )
if err != nil {
2020-01-15 11:32:57 +03:00
return false , "" , err
2019-12-15 14:06:31 +03:00
}
for e := commitList . Front ( ) ; e != nil ; e = e . Next ( ) {
commit = e . Value . ( * git . Commit )
verification := ParseCommitWithSignature ( commit )
if ! verification . Verified {
2020-01-15 11:32:57 +03:00
return false , "" , & ErrWontSign { commitsSigned }
2019-12-15 14:06:31 +03:00
}
}
}
}
2020-01-15 11:32:57 +03:00
return true , signingKey , nil
2019-12-15 14:06:31 +03:00
}