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.

121 lines
3.0 KiB

  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) {
  12. if err := pr.GetBaseRepo(); err != nil {
  13. log.Error("Unable to get Base Repo for pull request")
  14. return false, ""
  15. }
  16. repo := pr.BaseRepo
  17. signingKey := signingKey(repo.RepoPath())
  18. if signingKey == "" {
  19. return false, ""
  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, ""
  28. case always:
  29. break
  30. case pubkey:
  31. keys, err := ListGPGKeys(u.ID)
  32. if err != nil || len(keys) == 0 {
  33. return false, ""
  34. }
  35. case twofa:
  36. twofa, err := GetTwoFactorByUID(u.ID)
  37. if err != nil || twofa == nil {
  38. return false, ""
  39. }
  40. case approved:
  41. protectedBranch, err := GetProtectedBranchBy(repo.ID, pr.BaseBranch)
  42. if err != nil || protectedBranch == nil {
  43. return false, ""
  44. }
  45. if protectedBranch.GetGrantedApprovalsCount(pr) < 1 {
  46. return false, ""
  47. }
  48. case baseSigned:
  49. if gitRepo == nil {
  50. gitRepo, err = git.OpenRepository(tmpBasePath)
  51. if err != nil {
  52. return false, ""
  53. }
  54. defer gitRepo.Close()
  55. }
  56. commit, err := gitRepo.GetCommit(baseCommit)
  57. if err != nil {
  58. return false, ""
  59. }
  60. verification := ParseCommitWithSignature(commit)
  61. if !verification.Verified {
  62. return false, ""
  63. }
  64. case headSigned:
  65. if gitRepo == nil {
  66. gitRepo, err = git.OpenRepository(tmpBasePath)
  67. if err != nil {
  68. return false, ""
  69. }
  70. defer gitRepo.Close()
  71. }
  72. commit, err := gitRepo.GetCommit(headCommit)
  73. if err != nil {
  74. return false, ""
  75. }
  76. verification := ParseCommitWithSignature(commit)
  77. if !verification.Verified {
  78. return false, ""
  79. }
  80. case commitsSigned:
  81. if gitRepo == nil {
  82. gitRepo, err = git.OpenRepository(tmpBasePath)
  83. if err != nil {
  84. return false, ""
  85. }
  86. defer gitRepo.Close()
  87. }
  88. commit, err := gitRepo.GetCommit(headCommit)
  89. if err != nil {
  90. return false, ""
  91. }
  92. verification := ParseCommitWithSignature(commit)
  93. if !verification.Verified {
  94. return false, ""
  95. }
  96. // need to work out merge-base
  97. mergeBaseCommit, _, err := gitRepo.GetMergeBase("", baseCommit, headCommit)
  98. if err != nil {
  99. return false, ""
  100. }
  101. commitList, err := commit.CommitsBeforeUntil(mergeBaseCommit)
  102. if err != nil {
  103. return false, ""
  104. }
  105. for e := commitList.Front(); e != nil; e = e.Next() {
  106. commit = e.Value.(*git.Commit)
  107. verification := ParseCommitWithSignature(commit)
  108. if !verification.Verified {
  109. return false, ""
  110. }
  111. }
  112. }
  113. }
  114. return true, signingKey
  115. }