You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

pull_sign.go 3.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. // Copyright 2019 The Gitea Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package models
  5. import (
  6. "code.gitea.io/gitea/modules/git"
  7. "code.gitea.io/gitea/modules/log"
  8. "code.gitea.io/gitea/modules/setting"
  9. )
  10. // SignMerge determines if we should sign a PR merge commit to the base repository
  11. func (pr *PullRequest) SignMerge(u *User, tmpBasePath, baseCommit, headCommit string) (bool, string, error) {
  12. if err := pr.GetBaseRepo(); err != nil {
  13. log.Error("Unable to get Base Repo for pull request")
  14. return false, "", err
  15. }
  16. repo := pr.BaseRepo
  17. signingKey := signingKey(repo.RepoPath())
  18. if signingKey == "" {
  19. return false, "", &ErrWontSign{noKey}
  20. }
  21. rules := signingModeFromStrings(setting.Repository.Signing.Merges)
  22. var gitRepo *git.Repository
  23. var err error
  24. for _, rule := range rules {
  25. switch rule {
  26. case never:
  27. return false, "", &ErrWontSign{never}
  28. case always:
  29. break
  30. case pubkey:
  31. keys, err := ListGPGKeys(u.ID, ListOptions{})
  32. if err != nil {
  33. return false, "", err
  34. }
  35. if len(keys) == 0 {
  36. return false, "", &ErrWontSign{pubkey}
  37. }
  38. case twofa:
  39. twofaModel, err := GetTwoFactorByUID(u.ID)
  40. if err != nil && !IsErrTwoFactorNotEnrolled(err) {
  41. return false, "", err
  42. }
  43. if twofaModel == nil {
  44. return false, "", &ErrWontSign{twofa}
  45. }
  46. case approved:
  47. protectedBranch, err := GetProtectedBranchBy(repo.ID, pr.BaseBranch)
  48. if err != nil {
  49. return false, "", err
  50. }
  51. if protectedBranch == nil {
  52. return false, "", &ErrWontSign{approved}
  53. }
  54. if protectedBranch.GetGrantedApprovalsCount(pr) < 1 {
  55. return false, "", &ErrWontSign{approved}
  56. }
  57. case baseSigned:
  58. if gitRepo == nil {
  59. gitRepo, err = git.OpenRepository(tmpBasePath)
  60. if err != nil {
  61. return false, "", err
  62. }
  63. defer gitRepo.Close()
  64. }
  65. commit, err := gitRepo.GetCommit(baseCommit)
  66. if err != nil {
  67. return false, "", err
  68. }
  69. verification := ParseCommitWithSignature(commit)
  70. if !verification.Verified {
  71. return false, "", &ErrWontSign{baseSigned}
  72. }
  73. case headSigned:
  74. if gitRepo == nil {
  75. gitRepo, err = git.OpenRepository(tmpBasePath)
  76. if err != nil {
  77. return false, "", err
  78. }
  79. defer gitRepo.Close()
  80. }
  81. commit, err := gitRepo.GetCommit(headCommit)
  82. if err != nil {
  83. return false, "", err
  84. }
  85. verification := ParseCommitWithSignature(commit)
  86. if !verification.Verified {
  87. return false, "", &ErrWontSign{headSigned}
  88. }
  89. case commitsSigned:
  90. if gitRepo == nil {
  91. gitRepo, err = git.OpenRepository(tmpBasePath)
  92. if err != nil {
  93. return false, "", err
  94. }
  95. defer gitRepo.Close()
  96. }
  97. commit, err := gitRepo.GetCommit(headCommit)
  98. if err != nil {
  99. return false, "", err
  100. }
  101. verification := ParseCommitWithSignature(commit)
  102. if !verification.Verified {
  103. return false, "", &ErrWontSign{commitsSigned}
  104. }
  105. // need to work out merge-base
  106. mergeBaseCommit, _, err := gitRepo.GetMergeBase("", baseCommit, headCommit)
  107. if err != nil {
  108. return false, "", err
  109. }
  110. commitList, err := commit.CommitsBeforeUntil(mergeBaseCommit)
  111. if err != nil {
  112. return false, "", err
  113. }
  114. for e := commitList.Front(); e != nil; e = e.Next() {
  115. commit = e.Value.(*git.Commit)
  116. verification := ParseCommitWithSignature(commit)
  117. if !verification.Verified {
  118. return false, "", &ErrWontSign{commitsSigned}
  119. }
  120. }
  121. }
  122. }
  123. return true, signingKey, nil
  124. }